color looks wrong when CMYK jpg changed to RGB after opened and saved by image-rs
This happens when I simply used image-rs to open and save a CMYK jpg file
Expected
I expect the CMYK jpg file stays the same(file size, colorspace, etc.) I did not expect a CMYK jpg be changed to RGB jpg automatically. Because this CMYK jpg is used for printing.
Actual behaviour
the original CMYK jpg file is 12.5Mb, in CMYK; after opened and saved by image-rs, the size was changed to 2.2Mb, color spaced was changed to RGB(found out with Photoshop), and the image color looks different than the original file.
Reproduction steps
Download the original CMYK image file from the link below, and simply run:
use image;
/*
Cargo.toml:
[dependencies]
image = "0.23"
*/
fn main() {
let img = image::open("cmyk_original.jpg").unwrap();
img.save("cmyk_open_and_saved.jpg").unwrap();
}
Related Resources
original cmyk image file uploaded to mega.io open and saved by image-rs
It seems like this is caused by not using the ICC profile embedded in the image to do the CMYK to RGB conversion.
With the risk of being rude(I don't mean to), I just wanna ask is there any update/progress on this issue? Thanks in advance.
It's not exactly what you're looking for but qcms now supports doing CMYK to RGB conversions. The following produces an sRGB png file that should have more correct colors.
use jpeg_decoder::Decoder;
use std::fs::File;
use std::io::BufReader;
let file = File::open("cmyk_original.jpg").expect("failed to open file");
let mut decoder = Decoder::new(BufReader::new(file));
let pixels = decoder.decode().expect("failed to decode image");
let metadata = decoder.info().unwrap();
let profile = decoder.icc_profile().unwrap();
let profile = qcms::Profile::new_from_slice(&profile).unwrap();
let srgb = qcms::Profile::new_sRGB();
let xfm = qcms::Transform::new_to(&profile, &srgb, qcms::DataType::CMYK, qcms::DataType::RGB8, qcms::Intent::Perceptual).unwrap();
let mut result = vec![0; pixels.len()/4 * 3];
xfm.convert(&pixels, &mut result);
// write the result to a PNG
let mut encoder = png::Encoder::new(std::fs::File::create("out.png").unwrap(), metadata.width as u32, metadata.height as u32);
encoder.set_color(png::ColorType::Rgb);
encoder.set_srgb(png::SrgbRenderingIntent::Perceptual);
let mut writer = encoder.write_header().unwrap();
writer.write_image_data(&result).unwrap(); // Save