fdo#66006 Convert to PNG for JPEG that can't be losslessly rotated
If a JPEG image has a width or height which is not a multiple of 16
(width/heigh % 16 != 0) then it can't be completelly lossleessly
rotated (the last uncomplete MCUs can't be rotated) and the image
is cropped on the lower size. To prevent this such JPEG images
must be rotated to PNG to prevent loss. Afterwards image can still
be compressed with "Compress Graphic Dialog".
Change-Id: Ie2803512a93bba55573bf66c547f132f37cba711
diff --git a/vcl/source/filter/GraphicNativeTransform.cxx b/vcl/source/filter/GraphicNativeTransform.cxx
index 261ad90..69a10bd 100644
--- a/vcl/source/filter/GraphicNativeTransform.cxx
+++ b/vcl/source/filter/GraphicNativeTransform.cxx
@@ -141,45 +141,50 @@ bool GraphicNativeTransform::rotateGeneric(sal_uInt16 aRotation, OUString aType)
bool GraphicNativeTransform::rotateJPEG(sal_uInt16 aRotation)
{
GfxLink aLink = mrGraphic.GetLink();
SvMemoryStream aSourceStream;
aSourceStream.Write(aLink.GetData(), aLink.GetDataSize());
aSourceStream.Seek( STREAM_SEEK_TO_BEGIN );
Orientation aOrientation = TOP_LEFT;
Exif exif;
if ( exif.read(aSourceStream) )
{
aOrientation = exif.getOrientation();
}
SvMemoryStream aTargetStream;
JpegTransform tranform(aSourceStream, aTargetStream);
tranform.setRotate(aRotation);
tranform.perform();
aTargetStream.Seek( STREAM_SEEK_TO_BEGIN );
// Reset orientation in exif if needed
if ( exif.hasExif() && aOrientation != TOP_LEFT)
{
exif.setOrientation(TOP_LEFT);
exif.write(aTargetStream);
}
aTargetStream.Seek( STREAM_SEEK_TO_END );
sal_uInt32 aBufferSize = aTargetStream.Tell();
sal_uInt8* pBuffer = new sal_uInt8[ aBufferSize ];
aTargetStream.Seek( STREAM_SEEK_TO_BEGIN );
aTargetStream.Read( pBuffer, aBufferSize );
BitmapEx aBitmap = mrGraphic.GetBitmapEx();
aBitmap.Rotate(aRotation, COL_BLACK);
mrGraphic = aBitmap;
mrGraphic.SetLink( GfxLink( pBuffer, aBufferSize, aLink.GetType(), sal_True ) );
if (aBitmap.GetSizePixel().Width() % 16 != 0 ||
aBitmap.GetSizePixel().Height() % 16 != 0 )
{
rotateGeneric(aRotation, OUString("png"));
}
else
{
GfxLink aLink = mrGraphic.GetLink();
SvMemoryStream aSourceStream;
aSourceStream.Write(aLink.GetData(), aLink.GetDataSize());
aSourceStream.Seek( STREAM_SEEK_TO_BEGIN );
Orientation aOrientation = TOP_LEFT;
Exif exif;
if ( exif.read(aSourceStream) )
{
aOrientation = exif.getOrientation();
}
SvMemoryStream aTargetStream;
JpegTransform tranform(aSourceStream, aTargetStream);
tranform.setRotate(aRotation);
tranform.perform();
aTargetStream.Seek( STREAM_SEEK_TO_BEGIN );
// Reset orientation in exif if needed
if ( exif.hasExif() && aOrientation != TOP_LEFT)
{
exif.setOrientation(TOP_LEFT);
exif.write(aTargetStream);
}
aTargetStream.Seek( STREAM_SEEK_TO_BEGIN );
Graphic aGraphic;
GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
rFilter.ImportGraphic( aGraphic, OUString("import"), aTargetStream );
mrGraphic = aGraphic;
}
return true;
}