load-manipulate-update picture/pixels 的最佳方式是什么?
What is the best way to load-manipulate-update picture/pixels?
有 BufferedImage(顺便说一句,它是存储和编辑帧图形的最佳方式吗?)和对该图像进行一些编辑的功能。
我目前的做法:
//usage:
image.setData(update(image.getRaster()));
public Raster update(WritableRaster raster) {
int[] pixels = new int[raster.getWidth() * raster.getHeight()];
raster.getDataElements(0, 0, w, h, pixels); // raster to int[]
//pixels array operations
raster.setDataElements(0, 0, w, h, pixels); // int[] to raster
return raster;
}
发送光栅似乎是这种方法的瓶颈,但还有哪些其他选择?
通过将颜色值直接存储在光栅中,您可以高效地写入图像中的任何像素。我发现以这种方式动态操作图像的最有效方法是这样的:
BufferedImage image = new BufferedImage(inputWidth, inputHeight, BufferedImage.TYPE_INT_ARGB);
int[] rgbRaster = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
for(int i = 0; i < inputHeight; i++) {
for(int j = 0; j < inputWidth; j++) {
int index = (inputWidth * i) + j;
rgbRaster[index] = SOME_ARG_VALUE;
}
}
}
当然,您不必一遍又一遍地重新创建图像或光栅数组,只需创建一次,然后在需要时写入数组即可。很快,也很容易。
您的代码中的瓶颈实际上是 image.setData(...)
,因为它将 将 Raster
中的所有数据 复制到您的图像中(即使您只修改了update(...)
方法中的单个像素)。
然而,在这种情况下,这是完全没有必要的,因为 image.getRaster()
返回的 WritableRaster
表示像素的 "live view"。只需使用:
update(image.getRaster());
...应该可以,而且会快很多。
如果您知道您的图像是 TYPE_INT_*
,您可以按照@Terje 的建议,直接访问底层数据缓冲区。这可能会更快。请注意,像素数组也是一个 "live view",因此对数组的任何更改都会反映在图像中。
int[] rgb = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
这两种方法都可能使图像显示速度变慢(又名 "unmanaged"),但对于一般的图像处理,它们应该没问题。
有 BufferedImage(顺便说一句,它是存储和编辑帧图形的最佳方式吗?)和对该图像进行一些编辑的功能。
我目前的做法:
//usage:
image.setData(update(image.getRaster()));
public Raster update(WritableRaster raster) {
int[] pixels = new int[raster.getWidth() * raster.getHeight()];
raster.getDataElements(0, 0, w, h, pixels); // raster to int[]
//pixels array operations
raster.setDataElements(0, 0, w, h, pixels); // int[] to raster
return raster;
}
发送光栅似乎是这种方法的瓶颈,但还有哪些其他选择?
通过将颜色值直接存储在光栅中,您可以高效地写入图像中的任何像素。我发现以这种方式动态操作图像的最有效方法是这样的:
BufferedImage image = new BufferedImage(inputWidth, inputHeight, BufferedImage.TYPE_INT_ARGB);
int[] rgbRaster = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
for(int i = 0; i < inputHeight; i++) {
for(int j = 0; j < inputWidth; j++) {
int index = (inputWidth * i) + j;
rgbRaster[index] = SOME_ARG_VALUE;
}
}
}
当然,您不必一遍又一遍地重新创建图像或光栅数组,只需创建一次,然后在需要时写入数组即可。很快,也很容易。
您的代码中的瓶颈实际上是 image.setData(...)
,因为它将 将 Raster
中的所有数据 复制到您的图像中(即使您只修改了update(...)
方法中的单个像素)。
然而,在这种情况下,这是完全没有必要的,因为 image.getRaster()
返回的 WritableRaster
表示像素的 "live view"。只需使用:
update(image.getRaster());
...应该可以,而且会快很多。
如果您知道您的图像是 TYPE_INT_*
,您可以按照@Terje 的建议,直接访问底层数据缓冲区。这可能会更快。请注意,像素数组也是一个 "live view",因此对数组的任何更改都会反映在图像中。
int[] rgb = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
这两种方法都可能使图像显示速度变慢(又名 "unmanaged"),但对于一般的图像处理,它们应该没问题。