Aby być wyświetlany poprawnie CMYK obrazy powinny zawierać color space information jako ICC Profile. Tak więc najlepszym sposobem jest użycie tego profilu ICC, który może być łatwo wyodrębniony z Sanselan:
ICC_Profile iccProfile = Sanselan.getICCProfile(new File("filename.jpg"));
ColorSpace cs = new ICC_ColorSpace(iccProfile);
W przypadku nie ma profilu ICC dołączone do obrazu, użyłbym Adobe profiles jako domyślną.
Problem polega na tym, że nie można po prostu załadować pliku JPEG z niestandardową przestrzenią kolorów za pomocą ImageIO, ponieważ nie powiedzie się, rzucając wyjątek narzekając, że nie obsługuje on niektórych przestrzeni kolorów lub podobnych obiektów. Hense trzeba będzie pracować z rastrów:
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);
Następnie można użyć result
gdzie trzeba i będzie musiał przekonwertowane kolory.
W praktyce jednak natknąłem się na niektóre obrazy (zrobione aparatem i przetworzone przy użyciu Photoshopa), które miały w jakiś sposób odwrócone wartości kolorów, więc wynikowy obraz był zawsze odwrócony i nawet po odwróceniu ich ponownie były zbyt jasne. Chociaż nadal nie mają pojęcia, w jaki sposób dowiedzieć się, kiedy dokładnie go używać (gdy muszę odwrócić wartości pikseli), mam algorytm, który rozwiązuje te wartości i konwersja kolorów piksel po pikselu:
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);
}
jestem dość pewny, że RasterOp lub ColorConvertOp mogą być wykorzystane do usprawnienia konwersacji, ale to mi wystarczyło.
Poważnie, nie ma potrzeby korzystania z tych uproszczonych algorytmów konwersji CMYK do RGB, ponieważ można użyć profilu ICC, który jest osadzony w obrazie lub dostępny bezpłatnie od Adobe. Wynikowy obraz będzie wyglądał lepiej, jeśli nie jest idealny (z profilem osadzonym).
Wszyscy zawsze chcą szybką odpowiedź, jego sensu określić – Eric
Jak to rozwiązanie pracował dla Ciebie? Widzę, że próbowałeś to zrobić bez ICC_Colorspace, czy byłeś w stanie to utrzymać? – TacB0sS