Я скопирую свой ответ из другой ветки :
Для правильного отображения изображения CMYK должны содержать информацию о цветовом пространстве в качестве профиля ICC. Поэтому лучше всего использовать этот профиль ICC, который можно легко извлечь с помощью Sanselan :
ICC_Profile iccProfile = Sanselan.getICCProfile(new File("filename.jpg"));
ColorSpace cs = new ICC_ColorSpace(iccProfile);
Если к изображению не прикреплен профиль ICC, я бы по умолчанию использовал Профили Adobe .
Теперь проблема в том, что вы не можете просто загрузить файл JPEG с пользовательским цветовым пространством, используя ImageIO, так как он не сможет выдать исключение, жалуясь на то, что он не поддерживает некоторое цветовое пространство или подобный стиль. Скорее всего, вам придется работать с растрами:
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new ByteArrayInputStream(data));
Raster srcRaster = decoder.decodeAsRaster();
BufferedImage result = new BufferedImage(srcRaster.getWidth(), srcRaster.getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster resultRaster = result.getRaster();
ColorConvertOp cmykToRgb = new ColorConvertOp(cs, result.getColorModel().getColorSpace(), null);
cmykToRgb.filter(srcRaster, resultRaster);
Затем вы можете использовать result
там, где вам нужно, и он будет преобразовывать цвета.
На практике, однако, я сталкивался с некоторыми изображениями (снятыми камерой и обработанными с помощью Photoshop), которые каким-то образом инвертировали значения цвета, поэтому полученное изображение всегда инвертировалось, и даже после повторного инвертирования они были слишком яркими. Хотя я до сих пор не знаю, как узнать, когда именно его использовать (когда мне нужно инвертировать значения пикселей), у меня есть алгоритм, который корректирует эти значения и преобразует цвет пиксель за пикселем:
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new ByteArrayInputStream(data));
Raster srcRaster = decoder.decodeAsRaster();
BufferedImage ret = new BufferedImage(srcRaster.getWidth(), srcRaster.getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster resultRaster = ret.getRaster();
for (int x = srcRaster.getMinX(); x < srcRaster.getWidth(); ++x)
for (int y = srcRaster.getMinY(); y < srcRaster.getHeight(); ++y) {
float[] p = srcRaster.getPixel(x, y, (float[])null);
for (int i = 0; i < p.length; ++i)
p[i] = 1 - p[i] / 255f;
p = cs.toRGB(p);
for (int i = 0; i < p.length; ++i)
p[i] = p[i] * 255f;
resultRaster.setPixel(x, y, p);
}
Я почти уверен, что RasterOp или ColorConvertOp могут быть использованы для повышения эффективности разговора, но этого мне было достаточно.
Серьезно, нет необходимости использовать эти упрощенные алгоритмы преобразования CMYK в RGB, так как вы можете использовать профиль ICC, который встроен в изображение или доступен бесплатно от Adobe. Результирующее изображение будет выглядеть лучше, если не идеально (со встроенным профилем).