in imagecore/formats/internal/jpeg.cpp [294:378]
bool ImageReaderJPEG::beginReadInternal(unsigned int destWidth, unsigned int destHeight, EImageColorModel destColorModel)
{
J_COLOR_SPACE outputColorSpace = destColorModel == kColorModel_YUV_420 ? JCS_YCbCr : (HAVE_RGBX ? JCS_EXT_RGBX : JCS_RGB);
#if IMAGECORE_WITH_LCMS
if( m_RawColorProfileSize > 0 && (m_ReadOptions & kReadOption_ApplyColorProfile) != 0 && Image::colorModelIsRGBA(destColorModel) ) {
m_ColorProfile = cmsOpenProfileFromMem(m_RawColorProfile, m_RawColorProfileSize);
m_IgnoreColorProfile = true;
if( m_ColorProfile != NULL ) {
// Ignore mismatched color profiles.
if( m_JPEGDecompress.jpeg_color_space != JCS_GRAYSCALE || cmsGetColorSpace(m_ColorProfile) == cmsSigGrayData ) {
m_sRGBProfile = cmsCreate_sRGBProfile();
if( m_sRGBProfile == NULL) {
fprintf(stderr, "error: unable to allocate sRGB profile\n");
return false;
}
unsigned int inputFormat = getLCMSInputFormat(m_JPEGDecompress.jpeg_color_space, m_JPEGDecompress.saw_Adobe_marker);
m_ColorTransform = cmsCreateTransform(m_ColorProfile, inputFormat, m_sRGBProfile, HAVE_RGBX ? TYPE_RGBA_8 : TYPE_RGB_8, INTENT_PERCEPTUAL, 0);
if( m_ColorTransform == NULL ) {
fprintf(stderr, "error: unable to create ICC transform\n");
return false;
}
if( m_JPEGDecompress.jpeg_color_space == JCS_GRAYSCALE ) {
outputColorSpace = JCS_GRAYSCALE;
} else if( m_JPEGDecompress.jpeg_color_space == JCS_YCCK || m_JPEGDecompress.jpeg_color_space == JCS_CMYK ) {
outputColorSpace = JCS_CMYK;
}
m_IgnoreColorProfile = false;
}
}
}
#endif
m_JPEGDecompress.out_color_space = outputColorSpace;
m_JPEGDecompress.scale_num = 1;
m_JPEGDecompress.scale_denom = (unsigned int)roundf((float)m_Width / (float)destWidth);
// This is the default.
m_JPEGDecompress.dct_method = JDCT_ISLOW;
if( (m_ReadOptions & kReadOption_DecompressQualityFast) != 0) {
m_JPEGDecompress.do_fancy_upsampling = FALSE;
m_JPEGDecompress.dct_method = JDCT_FASTEST;
m_JPEGDecompress.do_block_smoothing = FALSE;
}
if( destColorModel == kColorModel_YUV_420 ) {
m_JPEGDecompress.raw_data_out = TRUE;
}
if( setjmp(m_JPEGError.jmp) ) {
fprintf(stderr, "error reading JPEG data: %s\n", s_JPEGLastError);
jpeg_abort_decompress(&m_JPEGDecompress);
return false;
}
jpeg_start_decompress(&m_JPEGDecompress);
if( destColorModel == kColorModel_YUV_420 ) {
// Make sure libjpeg doesn't try to upsample the UV components, we need them at half the resolution of Y.
// Recompute all of the scaling parameters jpeg_start_decompress configured.
for (int i = 1; i < 3; i++) {
m_JPEGDecompress.comp_info[i]._DCT_h_scaled_size = m_JPEGDecompress.comp_info[0]._DCT_h_scaled_size;
m_JPEGDecompress.comp_info[i]._DCT_v_scaled_size = m_JPEGDecompress.comp_info[0]._DCT_v_scaled_size;
m_JPEGDecompress.comp_info[i].MCU_sample_width = m_JPEGDecompress.comp_info[0].MCU_sample_width / 2;
m_JPEGDecompress.comp_info[i].downsampled_width = m_JPEGDecompress.comp_info[i].downsampled_width / 2;
m_JPEGDecompress.comp_info[i].downsampled_height = m_JPEGDecompress.comp_info[i].downsampled_height / 2;
}
// Re-trigger the dct method and table calculations.
int oldState = m_JPEGDecompress.global_state;
m_JPEGDecompress.global_state = 207;
jpeg_start_output(&m_JPEGDecompress, 1);
m_JPEGDecompress.global_state = oldState;
}
if( m_JPEGDecompress.output_width != destWidth || m_JPEGDecompress.output_height != destHeight ) {
fprintf(stderr, "JPEG scaled size mismatch");
jpeg_abort_decompress(&m_JPEGDecompress);
return false;
}
return true;
}