in imagecore/formats/internal/jpeg.cpp [1220:1316]
bool ImageWriterJPEG::copyLossless(ImageReader* reader)
{
#if IMAGECORE_WITH_JPEG_TRANSFORMS
if( setjmp(m_JPEGError.jmp) ) {
fprintf(stderr, "error during jpeg lossless copy: %s", s_JPEGLastError);
jpeg_destroy_compress(&m_JPEGCompress);
return false;
}
if( reader->getFormat() != kImageFormat_JPEG ) {
jpeg_destroy_compress(&m_JPEGCompress);
return false;
}
ImageReaderJPEG* jpegReader = (ImageReaderJPEG*)reader;
setSourceReader(reader);
if( setjmp(jpegReader->m_JPEGError.jmp) ) {
fprintf(stderr, "error during jpeg lossless copy: %s", s_JPEGLastError);
jpeg_destroy_compress(&m_JPEGCompress);
return false;
}
jpeg_transform_info transform;
memset(&transform, 0, sizeof(jpeg_transform_info));
if( (m_WriteOptions & kWriteOption_LosslessPerfect) != 0 ) {
transform.perfect = true;
} else{
// Trim edge blocks, otherwise the garbage padding data will be visible.
transform.trim = true;
}
bool haveTransform = false;
EImageOrientation orientation = reader->getOrientation();
// If we're preserving the EXIF orientation tag, we can skip this.
bool skipRotate = (m_WriteOptions & kWriteOption_WriteExifOrientation) != 0 || (m_WriteOptions & kWriteOption_CopyMetaData) != 0;
if( !skipRotate && (orientation == kImageOrientation_Down || orientation == kImageOrientation_Left || orientation == kImageOrientation_Right) ) {
switch( orientation ) {
case kImageOrientation_Down:
transform.transform = JXFORM_ROT_180;
break;
case kImageOrientation_Left:
transform.transform = JXFORM_ROT_90;
break;
case kImageOrientation_Right:
transform.transform = JXFORM_ROT_270;
break;
case kImageOrientation_Up:
break;
}
haveTransform = true;
}
if( !jtransform_request_workspace(&jpegReader->m_JPEGDecompress, &transform) ) {
// This will fail if perfect is specified, but the rotation results in lost edge blocks.
jpeg_destroy_compress(&m_JPEGCompress);
return false;
}
jpeg_copy_critical_parameters(&jpegReader->m_JPEGDecompress, &m_JPEGCompress);
if( (m_WriteOptions & kWriteOption_Progressive) != 0 ) {
jpeg_simple_progression(&m_JPEGCompress);
}
// Always re-optimize the huffman table for the new JPEG.
m_JPEGCompress.optimize_coding = true;
jvirt_barray_ptr* sourceCoeffs = jpeg_read_coefficients(&jpegReader->m_JPEGDecompress);
jvirt_barray_ptr* destCoeffs = sourceCoeffs;
if( haveTransform ) {
destCoeffs = jtransform_adjust_parameters(&jpegReader->m_JPEGDecompress, &m_JPEGCompress, sourceCoeffs, &transform);
}
jpeg_write_coefficients(&m_JPEGCompress, destCoeffs);
if( haveTransform ) {
jtransform_execute_transformation(&jpegReader->m_JPEGDecompress, &m_JPEGCompress, sourceCoeffs, &transform);
}
if( !writeMarkers() ) {
jpeg_destroy_compress(&m_JPEGCompress);
return false;
}
if( !endWrite() ) {
jpeg_destroy_compress(&m_JPEGCompress);
return false;
}
return true;
#else
return false;
#endif
}