我有一种方法将类型为TYPE_CUSTOM的BufferedImages转换为TYPE_INT_RGB。我使用以下代码,但我真的希望找到一种更快的方法。
BufferedImage newImg = new BufferedImage(
src.getWidth(),
src.getHeight(),
BufferedImage.TYPE_INT_RGB);
ColorConvertOp op = new ColorConvertOp(null);
op.filter(src, newImg);
它工作正常,但它很慢,我想知道是否有更快的方法来进行这种转换。
转化前的ColorModel:
ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@1c92586f transparency = 1 has alpha = false isAlphaPre = false
转换后的ColorModel:
DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=0
谢谢!
更新
使用原始像素数据是最好的方法。由于TYPE_CUSTOM实际上是RGB转换,因此手动操作非常简单,比ColorConvertOp快95%。
public static BufferedImage makeCompatible(BufferedImage img) throws IOException {
// Allocate the new image
BufferedImage dstImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
// Check if the ColorSpace is RGB and the TransferType is BYTE.
// Otherwise this fast method does not work as expected
ColorModel cm = img.getColorModel();
if ( cm.getColorSpace().getType() == ColorSpace.TYPE_RGB && img.getRaster().getTransferType() == DataBuffer.TYPE_BYTE ) {
//Allocate arrays
int len = img.getWidth()*img.getHeight();
byte[] src = new byte[len*3];
int[] dst = new int[len];
// Read the src image data into the array
img.getRaster().getDataElements(0, 0, img.getWidth(), img.getHeight(), src);
// Convert to INT_RGB
int j = 0;
for ( int i=0; i<len; i++ ) {
dst[i] = (((int)src[j++] & 0xFF) << 16) |
(((int)src[j++] & 0xFF) << 8) |
(((int)src[j++] & 0xFF));
}
// Set the dst image data
dstImage.getRaster().setDataElements(0, 0, img.getWidth(), img.getHeight(), dst);
return dstImage;
}
ColorConvertOp op = new ColorConvertOp(null);
op.filter(img, dstImage);
return dstImage;
}
答案 0 :(得分:7)
BufferedImages非常缓慢。我有一个解决方案,但我不确定你会喜欢它。处理和转换缓冲图像的最快方法是从BufferedImage内部提取原始数据数组。您可以通过调用buffImg.getRaster()并将其转换为特定栅格来实现。然后调用raster.getDataStorage()。一旦您可以访问原始数据,就可以编写快速图像处理代码,而BufferedImages中的所有抽象都不会降低速度。这项技术还需要深入了解图像格式和您的一些逆向工程。这是我能够让图像处理代码足够快地运行我的应用程序的唯一方法。
示例:
ByteInterleavedRaster srcRaster = (ByteInterleavedRaster)src.getRaster();
byte srcData[] = srcRaster.getDataStorage();
IntegerInterleavedRaster dstRaster = (IntegerInterleavedRaster)dst.getRaster();
int dstData[] = dstRaster.getDataStorage();
dstData[0] = srcData[0] << 16 | srcData[1] << 8 | srcData[2];
或类似的东西。期待编译器错误警告您不要访问类似的低级别栅格。我遇到这种技术问题的唯一地方就是会发生访问冲突的applet内部。
答案 1 :(得分:3)
我发现使用Graphics.drawImage()代替ColorConvertOp的渲染速度提高了50倍。我只能假设drawImage()是GPU加速的。
,这真的很慢,比如100x200矩形的50ms
public void BufferdImage convert(BufferedImage input) {
BufferedImage output= new BufferedImage(input.getWidht(), input.getHeight(), BufferedImage.TYPE_BYTE_BINARY, CUSTOM_PALETTE);
ColorConvertOp op = new ColorConvertOp(input.getColorModel().getColorSpace(),
output.getColorModel().getColorSpace());
op.filter(input, output);
return output;
}
然而,这个寄存器&lt;相同输入1ms
public void BufferdImage convert(BufferedImage input) {
BufferedImage output= new BufferedImage(input.getWidht(), input.getHeight(), BufferedImage.TYPE_BYTE_BINARY, CUSTOM_PALETTE);
Graphics graphics = output.getGraphics();
graphics.drawImage(input, 0, 0, null);
graphics.dispose();
return output;
}
答案 2 :(得分:0)
您是否尝试过提供任何RenderingHints?没有保证,但使用
ColorConvertOp op = new ColorConvertOp(new RenderingHints(
RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_SPEED));
而不是代码段中的null
可能会加速它。
答案 3 :(得分:0)
我怀疑问题可能是ColorConvertOp()逐像素工作(保证“慢”)。
问:您是否可以使用gc.createCompatibleImage()?
问:原始位图是真彩色还是使用色彩图?
问:没有其他问题,您是否同意编写JNI接口?要么是您自己的自定义C代码,要么是外部库,例如ImageMagick?答案 4 :(得分:0)
如果您安装了JAI,那么您可以尝试卸载它,如果可以,或者在加载JPEG时寻找某种方法来禁用codecLib。在过去的生活中,我遇到了类似的问题(http://www.java.net/node/660804),ColorConvertOp当时是最快的。
我记得基本问题是Java2D一般都没有针对TYPE_CUSTOM图像进行优化。当你安装JAI时,它附带了codecLib,它有一个解码器返回TYPE_CUSTOM并被使用而不是默认值。 JAI名单可能会提供更多帮助,已经有好几年了。
答案 5 :(得分:-1)
也许试试这个:
Bitmap source = Bitmap.create(width, height, RGB_565);//don't remember exactly...
Canvas c = new Canvas(source);
// then
c.draw(bitmap, 0, 0);
然后将修改源位图。
稍后你可以这样做:
onDraw(Canvas canvas){
canvas.draw(source, rectSrs,rectDestination, op);
}
如果您可以管理,请始终重复使用位图,以便您能够获得更好的性能。您也可以使用其他画布函数来绘制位图