将BufferedImage绘制到另一个BufferedImage的最快方法

4

我正在尝试在Java中创建图像马赛克。我计算正在创建的新图像的大小,然后对于将成为马赛克一部分的每个子图像,我进行绘制调用。

伪代码:

create buffered image big enough to hold entire mosaic
create Graphics2D context from that image

for each buffered subimage that will be a part of the mosaic
   draw the subimage on the graphics context of big bufferedimage
   g2.drawImage(myImage, x,y,width,height,null,null)

有更好的方法吗?我希望有某种直接复制操作可用,因为我不想将子图像转换或缩放到更大的图像中。类似于每个子图像的raster的arraycopy的东西。我注意到有一个setData方法,它接受一个Raster对象,但该方法注明Raster必须在相同的坐标空间中。
有什么想法吗?这是我的程序中的一个瓶颈,我希望它尽可能快。
编辑: 事实证明我错了(当没有硬数据的情况下做出假设时通常是这样),关于瓶颈在哪里。我有一个错误,多个3MB图片一遍又一遍地被读取,而不是使用缓存在内存中的缩小版本的图像。当我进行修复时,运行时间从50分钟降至15秒。
2个回答

3
通常,drawImage() 调用将直接映射到硬件加速的 blit 操作。根据您使用的驱动程序/图形卡和 JVM,缩放也应该是硬件加速的。但是,如果可以避免缩放,当然应该这样做。
如果子图像适合较大的图像,则应选择宽度和高度,使其与子图像的宽度和高度相同,以此避免缩放。在这种情况下,最好使用 g.drawImage(Image img, int x, int y, ImageObserver observer)。

-1

你可以称之为

getPixels(int x, int y, int w, int h, int[] iArray)

在子图像上进行光栅化,然后...

setPixels(int x, int y, int w, int h, int[] iArray)

关于更大的图像的WritableRaster。至于效率或性能,我不知道。你必须自己测试。当然,这些图像必须是相同类型的(相同的颜色空间,相同的分辨率等),但听起来你已经假定了。


2
我强烈建议人们使用Marc上面的建议,因为它允许操作保持在硬件加速的管道中。将像素从图像中提取到Java数组中,然后再像上面建议的那样将它们推回去实际上需要两个坏事情;1它需要将图像从易失性VRAM空间中取出,并且不再是硬件加速的(getRGB也是如此),并且需要将像素值转换为int并从本地空间拉入JVM空间。这可能是从一个图像复制像素数据到另一个图像的最慢方法。 - Riyad Kalla
1
注意:这并不是对Adam建议的贬低,因为在Java图像库中有很多未知的怪异行为,除非您已经深入了解了Swing/Java2D API,否则您永远都不会知道它们(它们在Javadoc中没有提到)。 - Riyad Kalla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接