ColorConvertOp的更快替代品

Mat*_*ean 10 java jai javax.imageio

我有一个方法将类型为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);
Run Code Online (Sandbox Code Playgroud)

它工作正常,但它很慢,我想知道是否有更快的方法来进行此转换.

转换前的ColorModel:

ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@1c92586f transparency = 1 has alpha = false isAlphaPre = false
Run Code Online (Sandbox Code Playgroud)

转换后的ColorModel:

DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=0
Run Code Online (Sandbox Code Playgroud)

谢谢!


更新:

结果使用原始像素数据是最好的方法.由于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;
}
Run Code Online (Sandbox Code Playgroud)

les*_*mal 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];
Run Code Online (Sandbox Code Playgroud)

或类似的东西.期待编译器错误警告您不要访问这样的低级别栅格.我遇到过这种技术问题的唯一地方就是applet内部会发生访问冲突.