Java: Wie kann man die Pixel eines BufferedImage schnell kopieren? (Unit-Test enthalten)
Ich möchte eine Kopie (eines Rechteckbereichs) der ARGB-Werte aus einer Quelle erstellen.BufferedImage
in ein ZielBufferedImage
. Es darf kein Compositing durchgeführt werden: Wenn ich ein Pixel mit einem ARGB-Wert von 0x8000BE50 (Alpha-Wert bei 128) kopiere, muss das Zielpixel @ seigena 0x8000BE50, überschreibt das Zielpixel vollständig.
Ich habe eine sehr genaue Frage und habe einen Komponententest durchgeführt, um zu zeigen, was ich brauche. Der Komponententest ist voll funktionsfähig und in sich abgeschlossen. Er geht gut und macht genau das, was ich will.
Aber ich will einschneller und speichereffizienter Methode zum Ersetzen von copySrcIntoDstAt (...).
Das ist der springende Punkt meiner Frage: Ich bin nicht danach, wie man das Bild schneller "füllt" (was ich getan habe, ist nur ein Beispiel für einen Unit-Test). Ich möchte nur wissen, was ein @ wär schnell und speichereffizient Weg, um es zu tun (dh schnell und nicht unnötige Objekte zu erstellen).
Die von mir durchgeführte Proof-of-Concept-Implementierung ist offensichtlich sehr speichereffizient, aber langsagetRGB
und einsetRGB
für jedes Pixel).
Schematisch habe ich Folgendes: (wobei A die entsprechenden Pixel aus dem Zielbild vor dem Kopieren angibt)
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
Und ich möchte das haben:
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAAAAAAAAA
wo 'B' steht für die Pixel aus dem src Bild
Bitte beachten Sie, dass ich nach einem genauen Ersatz für das @ suchcopySrcIntoDstAt (...) -Methode, nicht für einen API-Link / ein API-Zitat.
import org.junit.Test;
import java.awt.image.BufferedImage;
import static org.junit.Assert.*;
public class TestCopy {
private static final int COL1 = 0x8000BE50; // alpha at 128
private static final int COL2 = 0x1732FE87; // alpha at 23
@Test
public void testPixelsCopy() {
final BufferedImage src = new BufferedImage( 5, 5, BufferedImage.TYPE_INT_ARGB );
final BufferedImage dst = new BufferedImage( 20, 20, BufferedImage.TYPE_INT_ARGB );
convenienceFill( src, COL1 );
convenienceFill( dst, COL2 );
copySrcIntoDstAt( src, dst, 3, 4 );
for (int x = 0; x < dst.getWidth(); x++) {
for (int y = 0; y < dst.getHeight(); y++) {
if ( x >= 3 && x <= 7 && y >= 4 && y <= 8 ) {
assertEquals( COL1, dst.getRGB(x,y) );
} else {
assertEquals( COL2, dst.getRGB(x,y) );
}
}
}
}
// clipping is unnecessary
private static void copySrcIntoDstAt(
final BufferedImage src,
final BufferedImage dst,
final int dx,
final int dy
) {
// TODO: replace this by a much more efficient method
for (int x = 0; x < src.getWidth(); x++) {
for (int y = 0; y < src.getHeight(); y++) {
dst.setRGB( dx + x, dy + y, src.getRGB(x,y) );
}
}
}
// This method is just a convenience method, there's
// no point in optimizing this method, this is not what
// this question is about
private static void convenienceFill(
final BufferedImage bi,
final int color
) {
for (int x = 0; x < bi.getWidth(); x++) {
for (int y = 0; y < bi.getHeight(); y++) {
bi.setRGB( x, y, color );
}
}
}
}