Fixed #124 Decoding error of Jpeg-rgb image
Hi there. I think that I fixed the issue #124.
I encountered this kind of issue when I tried to handle some scientific images with this lib. After crawling on the internet, I read TiffTechNote2.
http://libtiff.maptools.org/TIFFTechNote2.html
And it says;
In lossy JPEG compression, it is customary to convert color source data to YCbCr and then downsample it before JPEG compression. This gives 2:1 data compression with hardly any visible image degradation, and it permits additional space savings within the JPEG compression step proper. However, these steps are not considered part of the ISO JPEG standard. The ISO standard is "color blind": it accepts data in any color space. For TIFF purposes, the JPEG compression tag is considered to represent the ISO JPEG compression standard only. The ISO standard is applied to the same data that would be stored in the TIFF file if no compression were used. Therefore, if color conversion or downsampling are used, they must be reflected in the regular TIFF fields; these steps are not considered to be implicit in the JPEG compression tag value. PhotometricInterpretation and related fields shall describe the color space actually stored in the file. With the TIFF 6.0 field definitions, downsampling is permissible only for YCbCr data, and it must correspond to the YCbCrSubSampling field. (Note that the default value for this field is not 1,1; so the default for YCbCr is to apply downsampling!) It is likely that future versions of TIFF will provide additional PhotometricInterpretation values and a more general way of defining subsampling, so as to allow more flexibility in JPEG-compressed files. But that issue is not addressed in this Tech Note. Implementors should note that many popular JPEG codecs (compressor/decompressors) provide automatic color conversion and downsampling, so that the application may supply full-size RGB data which is nonetheless converted to downsampled YCbCr. This is an implementation convenience which does not excuse the TIFF control layer from its responsibility to know what is really going on. The PhotometricInterpretation and subsampling fields written to the file must describe what is actually in the file.
It seems that jpeg-decoder incorrectly handed the RGB data as YCbCR and this lead to #123 error. So I looked the code of jpeg-decoder and found the code below.
https://github.com/image-rs/jpeg-decoder/blob/ab6d326a7b194568725731a19603fb580814452d/src/decoder.rs#L1018
fn choose_color_convert_func(component_count: usize,
_is_jfif: bool,
color_transform: Option<AdobeColorTransform>)
-> Result<fn(&mut [u8])> {
match component_count {
3 => {
// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe
// Unknown means the data is RGB, so we don't need to perform any color conversion on it.
if color_transform == Some(AdobeColorTransform::Unknown) {
Ok(color_convert_line_null)
}
else {
Ok(color_convert_line_ycbcr)
}
},
4 => {
// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe
match color_transform {
Some(AdobeColorTransform::Unknown) => Ok(color_convert_line_cmyk),
Some(_) => Ok(color_convert_line_ycck),
None => Err(Error::Format("4 components without Adobe APP14 metadata to indicate color space".to_owned())),
}
},
_ => panic!(),
}
}
I think embedding APP 14 metadata to jpeg_tables would be the solution. And it works. After the modification, the image TomasKralCZ uploaded is correctly decoded in my environment.
I barely write rust and I don't know TIFF format much, so there would be some mistakes. If so, please let me know. Thanks.
@yujota Ping because we've decided to bump to MSRV to 1.48 in any case. I believe this should unblock some of the issues here.
A version of this was merged in #162, so I'm going to go ahead and close