AWT BufferedImage to 2DArray

javaPanther

Mitglied
Hallo liebe Leute,
ich würde gerne ein BufferedImage in ein 2Dimensionales Array umwandeln. Leider ist mein aktueller Weg etwas arg langsam:
Java:
for(int i=0; i<isleSize; i++){
			for(int j=0; j<isleSize; j++){
				int perlinHeight = perlinImage.getData().getPixel(i, j, (int[]) null)[0];
				int isleHeight = isleImage.getData().getPixel(i, j, (int[]) null)[0];

				if(perlinHeight + isleHeight >= 510){
					isleArray[i][j]=255;
				}else{
					isleArray[i][j] = (perlinHeight*3 + isleHeight*2)/5;
				}
			}
			System.out.println(i);
		}

Kennt Jemand einen besseren Weg hierfür?
 
Entweder habe ich die Falsche Methode benutzt oder es lag an etwas drittem, aber über Pixel einnzeln auslesen ergibt sich kein Performance Vorteil und eine Methode für das komplette Raster als Array konnte ich nicht erkennen.
 
Direkt im Puffer rummachen:
Java:
int[] puffer = ((DataBufferInt)(meinBufferedImage.getRaster().getDataBuffer())).getData();
Das ist ungetestet, und der richtige DataBuffer-Typ hängt vom imageType des BufferedImages ab; ein TYPE_INT_RGB ist bspw. mit einem DataBufferInt bestückt.

Ark
 
Ohhhh, Wahnsinn, die Performance hat sich locker vervierzigfacht! Ehemals 800ms jetzt 20ms.
Danke für den letzten Tipp. Meine Umsetzung (für alle die es interessiert):

Java:
int n = 0;
		for(int i=0; i<isleSize; i++){
			for(int j=0; j<isleSize; j++){
				int perlinHeight = new Color(((DataBufferInt)(perlinImage.getRaster().getDataBuffer())).getData()[n++]).getRed();
				int isleHeight = isleType[i][j];
				
				if(perlinHeight + isleHeight >= 510){
					isleArray[i][j]=255;
				}else{
					isleArray[i][j] = (perlinHeight*3 + isleHeight*2)/5;
				}
			}
		}

Wenn Jemand noch einen Vorschlag zur Verbesserung hätte wäre das toll ^^
 
So neues dummes Problem:
ich habe nun versucht das Ganze auch auf die vorher verwendeten Arrays umzumünzen und diese somit durch JPG's auszutauschen. Hierbei ergibt sich das Problem, dass ein DataBufferByte statt Int benötigt wird, wenn ich diesen aber verwende, dann hat der 480000 Elemente statt den erwarteten 160000 (400x400 Jpg Datei). Weiterhin kann ich die ausgegebenen Daten nicht in meiner Form verwerten:

Java:
BufferedImage isleImage = new BufferedImage(isleSize, isleSize, 1);
		try {
			isleImage = ImageIO.read(this.getClass().getClassLoader().getResource("InselRund.jpg"));
		} catch (IOException e) {
			e.printStackTrace();
		} 
		
		RenderingHints hint = new RenderingHints( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
		g.setRenderingHints( hint );
		g.setPaint( new PerlinPaint( java.awt.Color.white,java.awt.Color.black, g.getTransform().getScaleInstance(randX, randY), new Random().nextDouble()));
		g.fillRect(0,0,isleSize,isleSize);
		
		int n = 0;
		for(int i=0; i<isleSize; i++){
			for(int j=0; j<isleSize; j++){
				int perlinHeight = new Color(((DataBufferInt)(perlinImage.getRaster().getDataBuffer())).getData()[n]).getRed();
				int isleHeight = new Color(((DataBufferByte)(isleImage.getRaster().getDataBuffer())).getData()[n++]).getRed();
				
				if(perlinHeight + isleHeight >= 510){
					isleArray[i][j]=255;
				}else{
					isleArray[i][j] = (perlinHeight*3 + isleHeight*2)/5;
				}
			}
		}

Dankbar für jede Hilfe,
Gruß und Raus.
 
Die bytes Speichern R,G,B und A getrennt (bei einem int sind sie alle zusammen). Man kann zwischen einem RGBA-int und den R,G,B,A-bytes hin- und her rechnen:
Code:
byte r = ...;
byte g = ...;
byte b= ...;
byte a = ...;
int rgba = 
    (r << 24) |
    (g << 16) |
    (b <<  8) |
    (a <<  0);
bzw.
Code:
int rgba = ...;
byte r = (byte)((rgba >> 24) & 0xFF);
byte g = (byte)((rgba >> 16) & 0xFF);
byte b = (byte)((rgba >>  8) & 0xFF);
byte a = (byte)((rgba >>  0) & 0xFF);

Letzteres ist sicher auch deutlich schneller, als dort in der innersten Schleife immer ein "new Color" object zu erstellen, nur um sich davon das "red" abzuholen ...
 

Neue Themen


Zurück
Oben