Java: Wie schnell Kopie eines BufferedImage des Pixels zu tun? (Einheit Test eingeschlossen)

StackOverflow https://stackoverflow.com/questions/2825837

  •  26-09-2019
  •  | 
  •  

Frage

Ich mag eine Kopie tun (ein Rechteck Fläche) des ARGB Wertes von einer Quelle BufferedImage in ein Ziel BufferedImage. Kein Compositing getan werden soll. Wenn ich ein Pixel mit dem ARGB-Wert 0x8000BE50 (Alpha-Wert bei 128) zu kopieren, muss das Zielpixel sein genau 0x8000BE50, total Überschreiben den Zielpixels

Ich habe eine sehr präzise Frage, und ich machte einen Unit-Test zu zeigen, was ich brauche. Die Unit-Test ist voll funktionsfähig und in sich geschlossene und vergeht gut und tut genau das, was ich will.

Allerdings möchte ich eine schneller und speichereffiziente Methode ersetzen copySrcIntoDstAt (...).

Das ist der ganze Punkt meiner Frage: Ich bin nicht nach, wie man „fill“ das Bild in einem schnelleren Weg (was ich tat, ist nur ein Beispiel eine Einheit Test haben). Alles, was ich will, ist zu wissen, was ein schneller und effiziente Speicher , wie es (dh schnell und nicht zu schaffen unnötigen Objekte) zu tun wäre.

Die Proof-of-Concept-Implementierung ich gemacht habe, ist offensichtlich sehr speichereffizient, aber es ist langsam (tut einem getRGB und ein setRGB für jedes Pixel).

Schematisch, ich habe diese bekommt: (wobei A zeigt Pixel von dem Zielbild vor der Kopie entspricht)

AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA

Und ich will diese haben:

AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAAAAAAAAA

Dabei steht 'B' steht für die Pixel aus der src Bild.

Beachten Sie, dass ich für einen exakten Ersatz der Suche copySrcIntoDstAt (...) Methode nicht für eine API-Link / quote.

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 );
            }
        }
    }

}
War es hilfreich?

Lösung

private static void copySrcIntoDstAt(final BufferedImage src,
        final BufferedImage dst, final int dx, final int dy) {
    int[] srcbuf = ((DataBufferInt) src.getRaster().getDataBuffer()).getData();
    int[] dstbuf = ((DataBufferInt) dst.getRaster().getDataBuffer()).getData();
    int width = src.getWidth();
    int height = src.getHeight();
    int dstoffs = dx + dy * dst.getWidth();
    int srcoffs = 0;
    for (int y = 0 ; y < height ; y++ , dstoffs+= dst.getWidth(), srcoffs += width ) {
        System.arraycopy(srcbuf, srcoffs , dstbuf, dstoffs, width);
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top