Để được hiển thị một cách chính xác hình ảnh CMYK nên chứa color space information như ICC Profile. Vì vậy, cách tốt nhất là sử dụng mà ICC Profile mà có thể dễ dàng trích xuất với Sanselan:
ICC_Profile iccProfile = Sanselan.getICCProfile(new File("filename.jpg"));
ColorSpace cs = new ICC_ColorSpace(iccProfile);
Trong trường hợp không có hồ sơ ICC gắn liền với hình ảnh, tôi sẽ sử dụng Adobe profiles như mặc định.
Bây giờ vấn đề là bạn không thể tải tập tin JPEG với không gian màu tùy chỉnh bằng ImageIO vì nó sẽ không ném một ngoại lệ phàn nàn rằng nó không hỗ trợ một số không gian màu hoặc sthing như thế. Hense bạn sẽ phải làm việc với rasters:
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);
Sau đó bạn có thể sử dụng result
bất cứ nơi nào bạn cần và nó sẽ có màu chuyển đổi. Trong thực tế, tuy nhiên tôi đã đi qua một số hình ảnh (chụp bằng máy ảnh và xử lý bằng Photoshop) bằng cách nào đó đảo ngược giá trị màu để hình ảnh luôn đảo ngược và thậm chí sau khi đảo ngược chúng lại quá sáng. Mặc dù tôi vẫn không có ý tưởng làm thế nào để tìm hiểu chính xác khi sử dụng nó (khi tôi cần phải đảo ngược giá trị pixel), tôi có một thuật toán mà sửa chữa các giá trị và chuyển đổi màu từng pixel:
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);
}
Tôi khá chắc chắn RasterOp hoặc ColorConvertOp có thể được sử dụng để làm cho cuộc trò chuyện hiệu quả hơn, nhưng điều này là đủ cho tôi.
Nghiêm túc, không cần phải sử dụng các thuật toán chuyển đổi CMYK đơn giản hóa sang RGB này vì bạn có thể sử dụng Hồ sơ ICC được nhúng vào hình ảnh hoặc có sẵn miễn phí từ Adobe. Hình ảnh kết quả sẽ trông đẹp hơn nếu không hoàn hảo (với hồ sơ được nhúng).
Mọi người đều muốn có câu trả lời nhanh, vô dụng của nó để chỉ định – Eric
Giải pháp này có hiệu quả với bạn như thế nào? Tôi thấy rằng bạn đã cố gắng để đi về nó mà không có ICC_Colorspace, bạn có thể giữ nó lên? – TacB0sS