ARGB int array to CMYKA byte array convertion

旧街凉风 提交于 2019-12-25 01:07:19

问题


In this question: Convert RGB to CMYK, I got a way to convert RGB int array to CMYK byte array. Now I hope to convert ARGB int array to CMYKA byte array directly instead of working with the resulting CMYK array and adding the extra alpha channel afterwards. Is it possible?

I tried to use 4 bands offset to create the raster like this:

WritableRaster raster = Raster.createPackedRaster(db, imageWidth, imageHeight, imageWidth, new int[]{0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000}, null);

But I got an error: Numbers of source Raster bands and source color space components do not match. I understand this comes from the fact the source color space only has 3 components. I am just wondering if it's possible to create some kind of 4 components color space or something to work around this.

This is the current version I am working with:

public static byte[] RGB2CMYK(ICC_ColorSpace cmykColorSpace, int[] rgb, int imageWidth, int imageHeight, boolean hasAlpha) {
    DataBuffer db = new DataBufferInt(rgb, rgb.length);
    WritableRaster raster = Raster.createPackedRaster(db, imageWidth, imageHeight, imageWidth, new int[]{0x00ff0000, 0x0000ff00, 0x000000ff}, null);
    ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);

    ColorConvertOp cco = new ColorConvertOp(sRGB, cmykColorSpace, null);

    WritableRaster cmykRaster = cco.filter(raster, null);
    byte[] cmyk = (byte[])cmykRaster.getDataElements(0, 0, imageWidth, imageHeight, null);

    if(!hasAlpha) return cmyk;

    byte[] cmyka = new byte[rgb.length*5];

    for(int i = 0, j = 0, k = 0; i < rgb.length; i++) {
        cmyka[k++] = cmyk[j++];
        cmyka[k++] = cmyk[j++];
        cmyka[k++] = cmyk[j++];
        cmyka[k++] = cmyk[j++];
        cmyka[k++] = (byte)(rgb[i]>>24 & 0xff);
    }

    return cmyka;
}

回答1:


I figured out a way to do this:

// Convert RGB to CMYK w/o alpha
public static byte[] RGB2CMYK(ICC_ColorSpace cmykColorSpace, int[] rgb, int imageWidth, int imageHeight, boolean hasAlpha) {
    DataBuffer db = new DataBufferInt(rgb, rgb.length);
    int[] bandMasks = new int[]{0x00ff0000, 0x0000ff00, 0x000000ff};
    ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
    ColorConvertOp cco = new ColorConvertOp(sRGB, cmykColorSpace, null);
    ColorModel cm = null;
    WritableRaster cmykRaster = null;       
    if(hasAlpha) {
        cm = ColorModel.getRGBdefault();
        bandMasks = new int[]{0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000};  
    } else 
        cm = new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff);
    WritableRaster raster = Raster.createPackedRaster(db, imageWidth, imageHeight, imageWidth, bandMasks, null);
    BufferedImage rgbImage = new BufferedImage(cm, raster, false, null);
    BufferedImage cmykImage = cco.filter(rgbImage, null);
    cmykRaster = cmykImage.getRaster();

    return (byte[])cmykRaster.getDataElements(0, 0, imageWidth, imageHeight, null);
}

I also found out it's much faster to do filter on a BufferedImage instead of a Raster. Might be some hardware acceleration.



来源:https://stackoverflow.com/questions/24069341/argb-int-array-to-cmyka-byte-array-convertion

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!