Преобразование массива ARGB в массив байтов CMYKA
В этом вопросе: Конвертировать RGB в CMYK, я получил способ конвертировать массив RGB int в байтовый массив CMYK. Теперь я надеюсь преобразовать массив ARGB int в байтовый массив CMYKA напрямую, вместо того, чтобы работать с полученным массивом CMYK и впоследствии добавить дополнительный альфа-канал. Является ли это возможным?
Я попытался использовать смещение на 4 полосы, чтобы создать растр следующим образом:
WritableRaster raster = Raster.createPackedRaster(db, imageWidth, imageHeight, imageWidth, new int[]{0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000}, null);
Но я получил ошибку: номера исходных растровых полос и компонентов исходного цветового пространства не совпадают. Я понимаю, что это происходит из-за того, что исходное цветовое пространство имеет только 3 компонента. Мне просто интересно, возможно ли создать какое-то 4-компонентное цветовое пространство или что-то, чтобы обойти это.
Это текущая версия, с которой я работаю:
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 ответ
Я нашел способ сделать это:
// 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);
}
Я также обнаружил, что гораздо быстрее сделать фильтр на BufferedImage вместо растра. Может быть какое-то аппаратное ускорение.