2016-06-02 2 views
1

Ich wollte ein gepuffertes Bild in das entsprechende Pixelwertarray konvertieren. Ich fand einen Code dafür:Ausnahme in BufferedImage.getData(). GetPixels()

public static double[] createArrFromIm(BufferedImage im){ 
     int imWidth = im.getWidth(); 
     int imHeight = im.getHeight(); 
     double[] imArr = new double[imWidth* imHeight]; 
     im.getData().getPixels(0, 0, imWidth, imHeight, imArr); 
     return imArr; 
} 

Der ursprüngliche Autor, der diesen Code-Block auch einige Beispielbilder gab schrieb, die für diesen Block perfekt arbeiten. Allerdings, wenn ich versuche, diesen Block gegen meine Bilder zu laufen (die Bilder sind immer 125 * 150), der Block wirft gebundener Ausnahme in Zeile einen Array-Index:

 im.getData().getPixels(0, 0, imWidth, imHeight, imArr); 

Dieser Vorfall scheint mir sehr obskur. Jede Hilfe oder Anregung wird sehr spürbar sein. Vielen Dank.

+0

einige Tipps, die Sie eine Antwort bekommen könnte helfen: Wenn Sie mit einer Ausnahme helfen wollen, immer den vollen Stapel hinzufügen Verfolge die Frage! Wenn bestimmte Bilder zum Reproduzieren der Ausnahme benötigt werden, sollten Sie den Code zum Erstellen oder Lesen sowie eine Beispieldatei hinzufügen. Schließlich verweisen Sie auf einen "Autor, der diesen Codeblock geschrieben hat". Es ist wahrscheinlich eine gute Idee, dorthin zu verlinken, wo Sie den Code für den Kontext gefunden haben. Glückliche Kodierung! :-) – haraldK

Antwort

-1

Haben sie das Raster mit:

public static double[] createArrFromIm(BufferedImage im){ 
    int imWidth = im.getWidth(); 
    int imHeight = im.getHeight(); 
    double[] imArr = new double[imWidth* imHeight]; 
    for (int y=0, nb=0 ; y < imHeight ; y++) 
     for (int x=0 ; x < imWidth ; x++, nb++) 
      imArr[nb] = im.getRaster().getSampleDouble(x, y, 0) ; 
    return imArr; 
} 

Wie @haraldK hingewiesen, getData() auch funktioniert, aber es gibt eine Kopie des Rasters, also ist es langsamer.

Es gibt einen schnelleren Weg mit dem DataBuffer, aber dann müssen Sie die BufferedImage-Codierung verwalten, da Sie direkten Zugriff auf die Pixelwerte haben.

Und hier ist die Antwort, warum was Sie getan haben, hat nicht funktioniert. im.getData().getPixels() gibt ein Array zurück, es füllt nicht das Array, das Sie als Parameter angeben. Das Array, das Sie als Parameter angeben, bestimmt nur den Rückgabetyp. Also, wenn Sie getData verwenden wollen (es ist nicht die beste Option), was Sie tun müssen:

double[] imArr = im.getData().getPixels(0, 0, imWidth, imHeight, (double[])null) ; 
+0

'im.getData()' bekommt schon das 'Raster' (na ja, eine Kopie davon, jedenfalls), deine Methode ist einfach schneller. Warum würde deine Version funktionieren und die OP nicht? Ich sage es nicht, aber eine Erklärung wäre nützlich. – haraldK

+0

Ja, die getData() gibt eine Kopie zurück, also benutze ich sie nie. Was ist "OP's", ich würde gerne Ihre Frage beantworten. – FiReTiTi

+0

OP = Originalplakat. [Quelle] (http://www.urbandictionary.com/define.php?term=op). Der Typ, der die Frage geschrieben hat. – haraldK

2

Wie @FiReTiTi sagt, sollten Sie die getRaster() Methode anstelle der getData() Methode verwenden, es sei denn, Sie wirklich wollen eine Kopie der Bilddaten.

Dies ist jedoch nicht die Ursache der Ausnahme. Das Problem ist, dass Ihr double Array nur Speicherplatz für ein einzelnes Band reserviert (ähnlich funktioniert die Version von FiReTiTi, weil er explizit den letzten Parameter 0 belässt und nur das erste Band anfordert). Dies ist für Einzelband (Graustufen) -Bilder gut, aber ich nehme an, dass Sie RGB, CMYK oder ein anderes Farbmodell mit mehreren Bändern verwenden.

Die Lösung ist den zugewiesenen Speicherplatz mit der Anzahl der Bänder zu multiplizieren, wie unten:

public static double[] createArrFromIm(BufferedImage im) { 
    int imWidth = im.getWidth(); 
    int imHeight = im.getHeight(); 
    int imBands = im.getRaster().getNumBands(); // typically 3 or 4, depending on RGB or ARGB 

    double[] imArr = new double[imWidth * imHeight * imBands]; 
    im.getRaster().getPixels(0, 0, imWidth, imHeight, imArr); 

    return imArr; 
}