19

BufferedImagesource からdestination への ARGB 値の (長方形領域の) コピーを実行したいと考えていますBufferedImage。合成は行わないでください。ARGB 値が 0x8000BE50 (アルファ値は 128) のピクセルをコピーする場合、コピー先ピクセルは正確に0x8000BE50 である必要があり、コピー先ピクセルを完全にオーバーライドします。

非常に正確な質問があり、必要なものを示すために単体テストを作成しました。単体テストは完全に機能し、自己完結型であり、問​​題なく合格しており、まさに私が望んでいることを行っています。

ただし、copySrcIntoDstAt (...)を置き換えるには、より高速でメモリ効率の高い方法が必要です。

それが私の質問の要点です。私は、画像をより速く「塗りつぶす」方法を求めていません(私が行ったことは、単体テストを行うための単なる例です)。私が望むのは、それを行うための高速でメモリ効率の良い方法 (つまり、高速で不要なオブジェクトを作成しない方法) を知ることだけです。

私が作成した概念実証の実装は、明らかにメモリ効率が非常に高いですが、低速です (すべてのピクセルに対して1getRGBつと 1 つを実行します)。setRGB

概略的に、私はこれを持っています: (ここで、A はコピー前のコピー先画像からの対応するピクセルを示します)

AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA

そして、私はこれが欲しい:

AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAAAAAAAAA

ここで、「B」はsrc画像のピクセルを表します。

APIリンク/引用ではなく、 copySrcIntoDstAt(...)メソッドの正確な代替品を探していることに注意してください。

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

}
4

1 に答える 1

23
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);
    }
}
于 2010-05-13T10:48:03.827 に答える