Schnelles laden und zeichnen von RGB-Daten in BufferedImage
In einigen Java-code läuft auf Windows, bin ich beim Lesen einige große Blöcke von RGB-Daten von der Festplatte und wollen diese Anzeige auf dem Bildschirm so schnell wie möglich. Die RGB-Daten mit 8 bit pro Kanal ohne alpha. Derzeit habe ich einen code wie den folgenden erstellen des BufferedImage.
BufferedImage getBufferedImage(File file, int width, int height) {
byte[] rgbData = readRGBFromFile(file);
WritableRaster raster = Raster.createInterleavedRaster(
rgbData, width, height,
width * 3, //scanlineStride
3, //pixelStride
new int[]{0, 1, 2}, //bandOffsets
null);
ColorModel colorModel = new ComponentColorModel(
ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[]{8, 8, 8}, //bits
false, //hasAlpha
false, //isPreMultiplied
ComponentColorModel.OPAQUE,
DataBuffer.TYPE_BYTE);
return new BufferedImage(colorModel, raster, false, null);
}
Das problem ist, dass die Leistung der rendering-diese auf dem Bildschirm ist sehr langsam. Rund 250 - 300 ms. Ich habe gelesen, dass für die beste Leistung, die Sie benötigen, um die Anzeige in ein BufferedImage, das mit dem Bildschirm kompatibel. Zu tun, ich pass das gepufferte Bild zurückgegeben, die von der oben genannten Methode eine Methode wie diese.
BufferedImage createCompatibleImage(BufferedImage image)
{
GraphicsConfiguration gc = GraphicsEnvironment.
getLocalGraphicsEnvironment().
getDefaultScreenDevice().
getDefaultConfiguration();
BufferedImage newImage = gc.createCompatibleImage(
image.getWidth(),
image.getHeight(),
Transparency.TRANSLUCENT);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
Dass die Methode im wesentlichen wandelt es von RGB auf ARGB auf Windows und es beschleunigt wirklich die Anzeige, aber diese Methode braucht ~300 ms bei 1600 x 1200 RGB-Daten block. Also ich hab jetzt im Grunde gehandelt, die performance-Einbußen der Zeichnung problem auf eine Umwandlung problem.
300ms ist etwa die gleiche Zeit, wie es dauert, zu laden, die RGB-Daten von der Festplatte. Ich würde denken, ich könnte etwas tun, schneller.
Gibt es eine bessere Art und Weise kann ich die Konvertierung? Oder würde es helfen, wenn ich veränderte die RGB-Daten und zusätzlichen Alphakanal mich vorher? Wenn ja, was würde mein Raster und ColorModel Aussehen. Auch, da mein RGB-Daten nicht enthalten Transparenz kann ich keine performance-Verbesserungen durch die Verwendung von pre-alpha multipliziert, oder was?
Sorry, bisschen ich bin ein wenig verloren auf dieser ColorModel, Raster-Zeug.
Dank!
InformationsquelleAutor awinbra | 2011-06-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich weiß, dies ist eine wirklich alte Frage, ich bin nur dieses posting, für alle anderen, die stolpern könnte, auf diese Frage auf der Suche nach mehr Optionen. Ich hatte ein Problem vor kurzem wo ich versuchte, nehmen Sie einen großen (720p) RGB byte[] und machen es zu einem
BufferedImage
. Die ursprüngliche Umsetzung war ich mit sah etwas wie diesem (hier vereinfacht):Selbst mit Optimierungen, wie die Erstellung der
BufferedImage
undComponentSampleModel
einmal, und wiederverwenden Sie, der Letzte Schritt ist die BerufungsetData
auf dieBufferedImage
noch in der Größenordnung von 50-60 Millisekunden, das ist inakzeptabel.Was ich am Ende zu realisieren ist, dass, zumindest für mein Szenario, können Sie tatsächlich schreiben zur Unterstützung ein byte-array der
BufferedImage
direkt und umgehen die meisten intermediate-Verarbeitung (vorausgesetzt, die backing-Metadaten für das Bild ist schon korrekt). Also habe ich meinen code wie folgt Aussehen:Nur dadurch, meine Leistungen verbesserten sich um etwa einen Faktor 20. Ich habe jetzt den gleichen Rahmen in 3-5 Millisekunden anstatt 50-60 Millisekunden.
Kann dies nicht in allen Fällen anwendbar sein, aber ich dachte, ich würde teilen, falls jemand anderes findet es nützlich.
BufferedImage
um diese blödesetData()
schneller zu arbeiten. Du hast mich gerettet, vielen Dank! 🙂Ich bin verwirrt... Was genau ist hier Los? dass
System.arraycopy()
zu sein scheint, überschreiben dieimgData
. Sollte es nicht anders herum sein?Es ist schon eine Weile her, seit ich dieses geschrieben, so verzeihen Sie, wenn dies fehlt...
imgData
ist ein Verweis auf die eigentlichebyte[]
(gespeichert als eine member-variable des BufferedImage ist WritableRaster), die zum Rendern des Bildes durch denBufferedImage
Klasse.frame
ist einbyte[]
ich gebaut, die ich will, zu erbringen über ein BufferedImage. So ist das System.arraycopy(...) kopiert das Bild, das ich gebaut habe (enthalten inframe
) zur Unterstützungbyte[]
in den Eingeweiden derBufferedImage
. Nun, wenn dieBufferedImage
gerendert wird, ist es mithilfe der Daten ausframe
dass ich kopiert und in dieBufferedImage
selbstInformationsquelleAutor Brent Writes Code
Nach dem spielen, um mit diesem habe ich eine anständige Antwort, das funktioniert für Windows, wenn die aktuellen Grafik-Konfiguration ist über den ARGB-integer packed raster.
Was ich Tue, erstellen die kompatibel BufferedImage zuerst, dann habe ich manuell konvertieren meine RGB-bytes-array, um einen ARGB-int-array. Dann bekomme ich das Raster vom kompatiblen BufferedImage schreiben und meine ARGB ints in es. Dies ist viel schneller.
Ich habe auch eine Klasse die überprüft, ob die kompatibel BufferedImage in das format, das ich erwarten, wenn es nicht standardmäßig zu den älteren langsamer Vorgehen.
Hier ist die Klasse. Hoffe es hilft dir.
Compatabile
->Compatible
in der Quelle. 2) Markieren Sie Ihre Antwort "richtig".+1... ich war zu erwähnen, dass ColorModel retardedness wirklich verlangsamt alles unten (bis zu 3 GRÖßENORDNUNGEN AUF EINIGEN OS X-VERSIONEN, ja, mehr als 1000 mal langsamer**!**) und bietet im Grunde nichts (ernsthaft, wie viele professionelle Bild/video-manipulation, - Bearbeitung, die in Java geschrieben sind? Das ist richtig, null...) im Vergleich zu der Arbeit, die direkt mit int[]. Es ist ein weiterer Fall von "zomg wir haben Objekte, lassen Sie uns overthink und geflügelteile alles ohne Grund". int[] primitiven manipulation um den Sieg: das ist, wie Sie es zu tun haben, wenn die Geschwindigkeit ist ein Anliegen.
Ja, meine beschleunigen ging von rund 300ms, unter 15ms.
Ausgezeichnete Dank, dies funktioniert auch für die UNDURCHSICHTIGE überspringen, wenn Sie die Alpha, und es funktioniert auch unter Linux. Bedeutende Geschwindigkeit auf beiden. Hinweis auf Win7 fand ich das BufferedImage.TYPE_INT_ARGB ist TYPE_INT_ARGB_PRE, sollte aber noch funktionieren, wenn Sie zu kompensieren.
auch in diesem Fall erhalten Sie eine schöne 66.6666666667 FPS in einem Spiel, so dass weit hervorragend. Allerdings habe ich die schlechteste CPU ever. Ich würde wahrscheinlich nur noch 44 🙁
InformationsquelleAutor awinbra