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 }
35 
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 || aBitmap.GetSizePixel().Height() % 16 != 0)
125  {
126  rotateGeneric(aRotation, "png");
127  }
128  else
129  {
130  GfxLink aLink = mrGraphic.GetGfxLink();
131 
132  SvMemoryStream aSourceStream;
133  aSourceStream.WriteBytes(aLink.GetData(), aLink.GetDataSize());
134  aSourceStream.Seek(STREAM_SEEK_TO_BEGIN);
135 
136  exif::Orientation aOrientation = exif::TOP_LEFT;
137 
138  Exif exif;
139  if (exif.read(aSourceStream))
140  {
141  aOrientation = exif.getOrientation();
142  }
143 
144  SvMemoryStream aTargetStream;
145  JpegTransform transform(aSourceStream, aTargetStream);
146  transform.setRotate(aRotation);
147  transform.perform();
148 
149  aTargetStream.Seek(STREAM_SEEK_TO_BEGIN);
150 
151  // Reset orientation in exif if needed
152  if (exif.hasExif() && aOrientation != exif::TOP_LEFT)
153  {
155  exif.write(aTargetStream);
156  }
157 
158  aTargetStream.Seek(STREAM_SEEK_TO_BEGIN);
159 
160  Graphic aGraphic;
162  rFilter.ImportGraphic(aGraphic, "import", aTargetStream);
163  mrGraphic = aGraphic;
164  }
165 }
166 
167 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
void rotateJPEG(sal_uInt16 aRotation)
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)
Definition: Exif.hxx:24
long Height() const
void write(SvStream &rStream)
Definition: Exif.cxx:78
bool read(SvStream &rStream)
Definition: Exif.cxx:69
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:320
void setOrientation(exif::Orientation orientation)
Definition: Exif.cxx:33
GraphicNativeTransform(Graphic &rGraphic)
Orientation
Definition: Exif.hxx:26
void setRotate(sal_uInt16 aRotate)
#define STREAM_SEEK_TO_BEGIN
std::size_t WriteBytes(const void *pData, std::size_t nSize)
BitmapEx GetBitmapEx(const GraphicConversionParameters &rParameters=GraphicConversionParameters()) const
Definition: graph.cxx:330
GfxLink GetGfxLink() const
Definition: graph.cxx:508
ErrCode ExportGraphic(const Graphic &rGraphic, const INetURLObject &rPath, sal_uInt16 nFormat, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData=nullptr)
exif::Orientation getOrientation() const
Definition: Exif.hxx:73
Definition: Exif.hxx:42
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:71
bool Rotate(long nAngle10, const Color &rFillColor)
Rotate bitmap by the specified angle.
Definition: bitmapex.cxx:386