1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/GraphicNativeTransform.hxx>
22 #include <vcl/gfxlink.hxx>
23 #include <vcl/graphicfilter.hxx>
24 #include <com/sun/star/uno/Sequence.hxx>
25 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include "jpeg/Exif.hxx"
28 #include "jpeg/JpegTransform.hxx"
30 GraphicNativeTransform::GraphicNativeTransform(Graphic
& rGraphic
) :
34 GraphicNativeTransform::~GraphicNativeTransform()
37 bool GraphicNativeTransform::canBeRotated()
39 GfxLink aLink
= mrGraphic
.GetLink();
41 // Don't allow rotation on animations for now
42 if (mrGraphic
.IsAnimated())
47 if ( aLink
.GetType() == GfxLinkType::NativeJpg
48 || aLink
.GetType() == GfxLinkType::NativePng
49 || aLink
.GetType() == GfxLinkType::NativeGif
50 || aLink
.GetType() == GfxLinkType::NONE
)
58 bool GraphicNativeTransform::rotate(sal_uInt16 aInputRotation
)
60 // Rotation can be between 0 and 3600
61 sal_uInt16 aRotation
= aInputRotation
% 3600;
65 return true; // No rotation is needed
67 else if (aRotation
!= 900 && aRotation
!= 1800 && aRotation
!= 2700)
72 GfxLink aLink
= mrGraphic
.GetLink();
73 if ( aLink
.GetType() == GfxLinkType::NativeJpg
)
75 return rotateJPEG(aRotation
);
77 else if ( aLink
.GetType() == GfxLinkType::NativePng
)
79 return rotateGeneric(aRotation
, "png");
81 else if ( aLink
.GetType() == GfxLinkType::NativeGif
)
83 return rotateGeneric(aRotation
, "gif");
85 else if ( aLink
.GetType() == GfxLinkType::NONE
)
87 return rotateBitmapOnly(aRotation
);
92 bool GraphicNativeTransform::rotateBitmapOnly(sal_uInt16 aRotation
)
94 if (mrGraphic
.IsAnimated())
99 BitmapEx aBitmap
= mrGraphic
.GetBitmapEx();
100 aBitmap
.Rotate(aRotation
, COL_BLACK
);
106 bool GraphicNativeTransform::rotateGeneric(sal_uInt16 aRotation
, const OUString
& aType
)
108 // Can't rotate animations yet
109 if (mrGraphic
.IsAnimated())
114 SvMemoryStream aStream
;
116 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
118 css::uno::Sequence
< css::beans::PropertyValue
> aFilterData( 3 );
119 aFilterData
[ 0 ].Name
= "Interlaced";
120 aFilterData
[ 0 ].Value
<<= (sal_Int32
) 0;
121 aFilterData
[ 1 ].Name
= "Compression";
122 aFilterData
[ 1 ].Value
<<= (sal_Int32
) 9;
123 aFilterData
[ 2 ].Name
= "Quality";
124 aFilterData
[ 2 ].Value
<<= (sal_Int32
) 90;
126 sal_uInt16 nFilterFormat
= rFilter
.GetExportFormatNumberForShortName( aType
);
128 BitmapEx aBitmap
= mrGraphic
.GetBitmapEx();
129 aBitmap
.Rotate(aRotation
, COL_BLACK
);
130 rFilter
.ExportGraphic( aBitmap
, "none", aStream
, nFilterFormat
, &aFilterData
);
132 aStream
.Seek( STREAM_SEEK_TO_BEGIN
);
135 rFilter
.ImportGraphic( aGraphic
, OUString("import"), aStream
);
137 mrGraphic
= aGraphic
;
141 bool GraphicNativeTransform::rotateJPEG(sal_uInt16 aRotation
)
143 BitmapEx aBitmap
= mrGraphic
.GetBitmapEx();
145 if (aBitmap
.GetSizePixel().Width() % 16 != 0 ||
146 aBitmap
.GetSizePixel().Height() % 16 != 0 )
148 rotateGeneric(aRotation
, "png");
152 GfxLink aLink
= mrGraphic
.GetLink();
154 SvMemoryStream aSourceStream
;
155 aSourceStream
.WriteBytes(aLink
.GetData(), aLink
.GetDataSize());
156 aSourceStream
.Seek( STREAM_SEEK_TO_BEGIN
);
158 Orientation aOrientation
= TOP_LEFT
;
161 if ( exif
.read(aSourceStream
) )
163 aOrientation
= exif
.getOrientation();
166 SvMemoryStream aTargetStream
;
167 JpegTransform
tranform(aSourceStream
, aTargetStream
);
168 tranform
.setRotate(aRotation
);
171 aTargetStream
.Seek( STREAM_SEEK_TO_BEGIN
);
173 // Reset orientation in exif if needed
174 if ( exif
.hasExif() && aOrientation
!= TOP_LEFT
)
176 exif
.setOrientation(TOP_LEFT
);
177 exif
.write(aTargetStream
);
180 aTargetStream
.Seek( STREAM_SEEK_TO_BEGIN
);
183 GraphicFilter
& rFilter
= GraphicFilter::GetGraphicFilter();
184 rFilter
.ImportGraphic( aGraphic
, OUString("import"), aTargetStream
);
185 mrGraphic
= aGraphic
;
191 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */