开发者

Java: how to do fast copy of a BufferedImage's pixels? (unit test included)

开发者 https://www.devze.com 2022-12-30 07:55 出处:网络
I want to do a copy (of a rectangle area) of the ARGB values from a source BufferedImage into a destination BufferedImage.No compositing should be done: if I copy a pixel with an ARGB value of 0x8000B

I want to do a copy (of a rectangle area) of the ARGB values from a source BufferedImage into a destination BufferedImage. No compositing should be done: if I copy a pixel with an ARGB value of 0x8000BE50 (alpha value at 128), then the destination pixel must be exactly 0x8000BE50, totally overriding the destination pixel.

I've got a very precise question and I made a unit test to show what I need. The unit test is fully functional and self-contained and is passing fine and is doing precisely what I want.

However, I want a faster and more memory efficient method to replace copySrcIntoDstAt(...).

That's the whole point of my question: I'm not after how to "fill" the image in a faster way (what I did is just an example to have a unit test). All I want is to know what would be a fast and memory efficient way to do it (ie fast and not creating needless objects).

The proof-of-concept implementation I've made is obviously very memory efficient, but it is slow (doing one getRGB and one setRGB for every pixel).

Schematically, I've got this: (where A indicates corresponding pixels from the destination image before the copy)

AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA

And I want to have this:

AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAAAAAAAAA

where 'B' represents the pixels from the src image.

Note that I'm looking for an exact replacement of the copySrcIntoDstAt(...) method, not for an 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 stat开发者_如何学Pythonic 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 );
            }
        }
    }

}


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

精彩评论

暂无评论...
验证码 换一张
取 消