简体   繁体   English

ARGB int数组到CMYKA字节数组的转换

[英]ARGB int array to CMYKA byte array convertion

In this question: Convert RGB to CMYK , I got a way to convert RGB int array to CMYK byte array. 在这个问题中: 将RGB转换为CMYK ,我有办法将RGB int数组转换为CMYK字节数组。 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. 现在,我希望直接将ARGB int数组转换为CMYKA字节数组,而不是使用生成的CMYK数组并随后添加额外的alpha通道。 Is it possible? 可能吗?

I tried to use 4 bands offset to create the raster like this: 我尝试使用4个带偏移量来创建栅格,如下所示:

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. 我了解这是因为源色彩空间只有3个成分。 I am just wondering if it's possible to create some kind of 4 components color space or something to work around this. 我只是想知道是否可以创建某种4种颜色空间的组件或解决此问题的方法。

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;
}

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. 我还发现对BufferedImage而不是Raster进行过滤要快得多 Might be some hardware acceleration. 可能是一些硬件加速。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM