当前位置: 首页 > 面试题库 >

Java:如何快速复制BufferedImage的像素?(包括单元测试)

卫泉
2023-03-14
问题内容

我想从源BufferedImage到目标复制ARGB值(矩形区域)BufferedImage。不应进行合成:如果我复制ARGB值为0x8000BE50(alpha值为128)的像素,则目标像素必须
恰好是 0x8000BE50,完全覆盖了目标像素。

我有一个非常精确的问题,我进行了单元测试以显示我的需求。单元测试功能齐全且功能齐全,通过得很好,并且可以满足我的要求。

但是,我想要一个 更快,更节省内存的 方法来替换 copySrcIntoDstAt (…)。

这就是我问题的全部重点:我不希望以更快的方式“填充”图像(我所做的只是一个进行单元测试的示例)。我只想知道什么是一种 快速且节省内存的
方法(即快速且不创建不必要的对象)。

我所做的概念验证实现显然非常有效地提高了内存效率,但是它很慢(每个像素做一个getRGB和一个setRGB)。

从概念上讲,我得到了:(其中A表示复制之前目标图像中的相应像素)

AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA

我想要这个:

AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAABBBBAAA
AAAAAAAAAAAAAAAAAAAA

其中“ B”代表 src 图像中的像素。

请注意,我正在寻找 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 );
            }
        }
    }

}

问题答案:
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);
    }
}


 类似资料:
  • 问题内容: 我从使用方法获得像素。像素存储在名为的数组中。在对数据数组进行一些操作之后,我需要再次创建一个,以便可以将其传递到一个模块,该模块将显示来自此数据数组的修改后的图像,但我对此感到困惑。 问题答案: 然后再次设置像素。 PS:如评论中所述,请使用@TacticalCoder的答案

  • 很长一段时间,1-2个月,我一直试图找到这个问题的答案: 我的图像硬件无法加速! 我一直在网上搜索,创造了我自己的方法,用键盘敲我的头(仍然感到疼痛),但没有成功。 虽然我讨厌Java SDK以外的库,但我尝试了LWJGL和JOGL,但由于一些愚蠢的原因,它们在我的计算机上不起作用。 我试着使用系统。setProperty(“Dsun.java2d.opengl”,“True”),我使用了Vola

  • 问题内容: 我想转换为 下面尝试的方法,但执行效果不佳(返回nil)。 如何转换此日期格式? 问题答案: Xcode 8•Swift 3 您需要转义“ T”并使用适当的时区符号。请注意,这取决于您的日期字符串代表带Z 还是不带+00:00 的UTC(距格林尼治标准时间为零秒)时区: 如果您需要一些参考,可以使用以下方法:

  • 问题内容: 我正在尝试获取所选项目,然后开始一些活动。不幸的是,我发现的大多数解决方案都在Objective-C或不起作用。 方法不打印标签。 有人可以帮我吗? 经过几次尝试,我将代码更改为与我发现的教程不同的代码。而且它也不起作用。现在我认为这是iOS模拟器的问题… 问题答案: 如果您想从单元格中获取值,则无需在 任务如下: 您还必须检查您必须设置的标识符。 希望能帮助到你。

  • 问题内容: 这个问题已经在这里有了答案 : 如何在Python中复制文件? (17个答案) 5年前关闭。 使用Windows File Explorer或Mac’s Finder将文件复制到常规右键单击复制>右键单击粘贴的时间至少要长3倍。有没有比Python更快的替代方法?可以采取什么措施来加快文件复制过程?(文件目标位于网络驱动器上……如果有任何区别……)。 编辑后: 这是我最终得到的结果:

  • 页面是动态生成的,因为现在我需要,所以不能缓存整个页面。但至少我想缓存所有静态内容,包括页面中包含的图像,有两种方式: 以及以常规的方式 在Varnish配置文件中,图像如和url被设置为缓存。 当页面在浏览器中打开两次,清漆似乎工作正常,和年龄是 现在,当我运行一个脚本来预热清漆缓存,然后第一次在浏览器中打开任何页面时,所有的jpgs、pngs和image.php年龄总是=0 用于预热缓存的脚本