bool ImageWriterJPEG::copyLossless()

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
}