Java:如何快速复制 BufferedImage 的像素?(包括单元测试)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2825837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: how to do fast copy of a BufferedImage's pixels? (unit test included)
提问by SyntaxT3rr0r
I want to do a copy (of a rectangle area) of the ARGB values from a source BufferedImageinto 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 exactly0x8000BE50, totally overriding the destination pixel.
我想将 ARGB 值从源复制(矩形区域)BufferedImage到目标BufferedImage。不应进行合成:如果我复制 ARGB 值为 0x8000BE50(alpha 值为 128)的像素,则目标像素必须恰好为0x8000BE50,完全覆盖目标像素。
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 efficientmethod to replace copySrcIntoDstAt(...).
但是,我想要一种更快、内存效率更高的方法来替换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 efficientway 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 getRGBand one setRGBfor every pixel).
我所做的概念验证实现显然是非常有效的内存,但速度很慢(对每个像素做一个getRGB和一个setRGB)。
Schematically, I've got this: (where A indicates corresponding pixels from the destination image before the copy)
示意性地,我有这个:(其中 A 表示复制前目标图像中的相应像素)
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 srcimage.
其中“B”代表来自src图像的像素。
Note that I'm looking for an exact replacement of the copySrcIntoDstAt(...)method, not for an API link/quote.
请注意,我正在寻找copySrcIntoDstAt(...)方法的精确替代品,而不是 API 链接/引用。
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 );
}
}
}
}
回答by stacker
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);
}
}

