LibreOffice Module vcl (master)  1
GraphicNativeTransform.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
21 
22 #include <vcl/gfxlink.hxx>
23 #include <vcl/graphicfilter.hxx>
24 #include <com/sun/star/beans/PropertyValue.hpp>
25 #include <com/sun/star/uno/Sequence.hxx>
26 #include <tools/stream.hxx>
27 
28 #include "jpeg/Exif.hxx"
29 #include "jpeg/JpegTransform.hxx"
30 
32  mrGraphic(rGraphic)
33 {}
34 
36 {}
37 
38 void GraphicNativeTransform::rotate(sal_uInt16 aInputRotation)
39 {
40  // Rotation can be between 0 and 3600
41  sal_uInt16 aRotation = aInputRotation % 3600;
42 
43  if (aRotation == 0)
44  {
45  return; // No rotation is needed
46  }
47  else if (aRotation != 900 && aRotation != 1800 && aRotation != 2700)
48  {
49  return;
50  }
51 
52  GfxLink aLink = mrGraphic.GetGfxLink();
53  if ( aLink.GetType() == GfxLinkType::NativeJpg )
54  {
55  rotateJPEG(aRotation);
56  }
57  else if ( aLink.GetType() == GfxLinkType::NativePng )
58  {
59  rotateGeneric(aRotation, "png");
60  }
61  else if ( aLink.GetType() == GfxLinkType::NativeGif )
62  {
63  rotateGeneric(aRotation, "gif");
64  }
65  else if ( aLink.GetType() == GfxLinkType::NONE )
66  {
67  rotateBitmapOnly(aRotation);
68  }
69 }
70 
71 bool GraphicNativeTransform::rotateBitmapOnly(sal_uInt16 aRotation)
72 {
73  if (mrGraphic.IsAnimated())
74  {
75  return false;
76  }
77 
78  BitmapEx aBitmap = mrGraphic.GetBitmapEx();
79  aBitmap.Rotate(aRotation, COL_BLACK);
80  mrGraphic = aBitmap;
81 
82  return true;
83 }
84 
85 bool GraphicNativeTransform::rotateGeneric(sal_uInt16 aRotation, const OUString& aType)
86 {
87  // Can't rotate animations yet
88  if (mrGraphic.IsAnimated())
89  {
90  return false;
91  }
92 
93  SvMemoryStream aStream;
94 
96 
97  css::uno::Sequence< css::beans::PropertyValue > aFilterData( 3 );
98  aFilterData[ 0 ].Name = "Interlaced";
99  aFilterData[ 0 ].Value <<= sal_Int32(0);
100  aFilterData[ 1 ].Name = "Compression";
101  aFilterData[ 1 ].Value <<= sal_Int32(9);
102  aFilterData[ 2 ].Name = "Quality";
103  aFilterData[ 2 ].Value <<= sal_Int32(90);
104 
105  sal_uInt16 nFilterFormat = rFilter.GetExportFormatNumberForShortName( aType );
106 
107  BitmapEx aBitmap = mrGraphic.GetBitmapEx();
108  aBitmap.Rotate(aRotation, COL_BLACK);
109  rFilter.ExportGraphic( aBitmap, "none", aStream, nFilterFormat, &aFilterData );
110 
111  aStream.Seek( STREAM_SEEK_TO_BEGIN );
112 
113  Graphic aGraphic;
114  rFilter.ImportGraphic( aGraphic, "import", aStream );
115 
116  mrGraphic = aGraphic;
117  return true;
118 }
119 
120 void GraphicNativeTransform::rotateJPEG(sal_uInt16 aRotation)
121 {
122  BitmapEx aBitmap = mrGraphic.GetBitmapEx();
123 
124  if (aBitmap.GetSizePixel().Width() % 16 != 0 ||
125  aBitmap.GetSizePixel().Height() % 16 != 0 )
126  {
127  rotateGeneric(aRotation, "png");
128  }
129  else
130  {
131  GfxLink aLink = mrGraphic.GetGfxLink();
132 
133  SvMemoryStream aSourceStream;
134  aSourceStream.WriteBytes(aLink.GetData(), aLink.GetDataSize());
135  aSourceStream.Seek( STREAM_SEEK_TO_BEGIN );
136 
137  Orientation aOrientation = TOP_LEFT;
138 
139  Exif exif;
140  if ( exif.read(aSourceStream) )
141  {
142  aOrientation = exif.getOrientation();
143  }
144 
145  SvMemoryStream aTargetStream;
146  JpegTransform tranform(aSourceStream, aTargetStream);
147  tranform.setRotate(aRotation);
148  tranform.perform();
149 
150  aTargetStream.Seek( STREAM_SEEK_TO_BEGIN );
151 
152  // Reset orientation in exif if needed
153  if ( exif.hasExif() && aOrientation != TOP_LEFT)
154  {
155  exif.setOrientation(TOP_LEFT);
156  exif.write(aTargetStream);
157  }
158 
159  aTargetStream.Seek( STREAM_SEEK_TO_BEGIN );
160 
161  Graphic aGraphic;
163  rFilter.ImportGraphic( aGraphic, "import", aTargetStream );
164  mrGraphic = aGraphic;
165  }
166 }
167 
168 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
void rotateJPEG(sal_uInt16 aRotation)
Orientation
Definition: Exif.hxx:25
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
ErrCode ImportGraphic(Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat=GRFILTER_FORMAT_DONTKNOW, sal_uInt16 *pDeterminedFormat=nullptr, GraphicFilterImportFlags nImportFlags=GraphicFilterImportFlags::NONE)
void setOrientation(Orientation orientation)
Definition: Exif.cxx:34
long Height() const
void write(SvStream &rStream)
Definition: Exif.cxx:80
bool read(SvStream &rStream)
Definition: Exif.cxx:71
sal_uInt64 Seek(sal_uInt64 nPos)
Class to import and export graphic formats.
sal_uInt16 GetExportFormatNumberForShortName(const OUString &rShortName)
bool IsAnimated() const
Definition: graph.cxx:339
GraphicNativeTransform(Graphic &rGraphic)
void setRotate(sal_uInt16 aRotate)
#define STREAM_SEEK_TO_BEGIN
std::size_t WriteBytes(const void *pData, std::size_t nSize)
Orientation getOrientation() const
Definition: Exif.hxx:71
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
Definition: graph.cxx:349
GfxLink GetGfxLink() const
Definition: graph.cxx:527
ErrCode ExportGraphic(const Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData=nullptr)
Definition: Exif.hxx:40
void rotate(sal_uInt16 aRotation)
static GraphicFilter & GetGraphicFilter()
const Size & GetSizePixel() const
Definition: bitmapex.hxx:83
bool rotateGeneric(sal_uInt16 aRotation, const OUString &aType)
bool rotateBitmapOnly(sal_uInt16 aRotation)
bool hasExif() const
Definition: Exif.hxx:69
bool Rotate(long nAngle10, const Color &rFillColor)
Rotate bitmap by the specified angle.
Definition: bitmapex.cxx:390