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 .
21 #include <boost/scoped_array.hpp>
24 maOrientation(TOP_LEFT
),
32 void Exif::setOrientation(Orientation aOrientation
) {
33 maOrientation
= aOrientation
;
36 Orientation
Exif::convertToOrientation(sal_Int32 value
)
39 case 1: return TOP_LEFT
;
40 case 2: return TOP_RIGHT
;
41 case 3: return BOTTOM_RIGHT
;
42 case 4: return BOTTOM_LEFT
;
43 case 5: return LEFT_TOP
;
44 case 6: return RIGHT_TOP
;
45 case 7: return RIGHT_BOTTOM
;
46 case 8: return LEFT_BOTTOM
;
51 sal_Int32
Exif::getRotation()
53 switch(maOrientation
) {
69 bool Exif::read(SvStream
& rStream
)
71 sal_Int32 nStreamPosition
= rStream
.Tell();
72 bool result
= processJpeg(rStream
, false);
73 rStream
.Seek( nStreamPosition
);
78 bool Exif::write(SvStream
& rStream
)
80 sal_Int32 nStreamPosition
= rStream
.Tell();
81 bool result
= processJpeg(rStream
, true);
82 rStream
.Seek( nStreamPosition
);
87 bool Exif::processJpeg(SvStream
& rStream
, bool bSetValue
)
92 rStream
.Seek(STREAM_SEEK_TO_END
);
93 sal_uInt32 aSize
= rStream
.Tell();
94 rStream
.Seek(STREAM_SEEK_TO_BEGIN
);
96 rStream
.SetEndian( SvStreamEndian::BIG
);
97 rStream
.ReadUInt16( aMagic16
);
99 // Compare JPEG magic bytes
100 if( 0xFFD8 != aMagic16
)
105 sal_uInt32 aPreviousPosition
= STREAM_SEEK_TO_BEGIN
;
109 sal_uInt8 aMarker
= 0xD9;
112 for (aCount
= 0; aCount
< 7; aCount
++)
114 rStream
.ReadUChar( aMarker
);
125 rStream
.ReadUInt16( aLength
);
127 if (aLength
< 8 || aLength
> rStream
.remainingSize())
134 return processExif(rStream
, aLength
, bSetValue
);
136 else if (aMarker
== 0xD9)
142 sal_uInt32 aCurrentPosition
= rStream
.SeekRel(aLength
-1);
143 if (aCurrentPosition
== aPreviousPosition
|| aCurrentPosition
> aSize
)
147 aPreviousPosition
= aCurrentPosition
;
153 bool Exif::processIFD(sal_uInt8
* pExifData
, sal_uInt16 aLength
, sal_uInt16 aOffset
, sal_uInt16 aNumberOfTags
, bool bSetValue
, bool bSwap
)
157 while (aOffset
<= aLength
- 12 && aNumberOfTags
> 0)
159 ifd
= reinterpret_cast<ExifIFD
*>(&pExifData
[aOffset
]);
160 sal_uInt16 tag
= ifd
->tag
;
163 tag
= OSL_SWAPWORD(ifd
->tag
);
166 if (tag
== ORIENTATION
)
170 ifd
->tag
= ORIENTATION
;
173 ifd
->offset
= maOrientation
;
176 ifd
->tag
= OSL_SWAPWORD(ifd
->tag
);
177 ifd
->offset
= OSL_SWAPWORD(ifd
->offset
);
182 sal_uInt32 nIfdOffset
= ifd
->offset
;
184 nIfdOffset
= OSL_SWAPWORD(ifd
->offset
);
185 maOrientation
= convertToOrientation(nIfdOffset
);
195 bool Exif::processExif(SvStream
& rStream
, sal_uInt16 aSectionLength
, bool bSetValue
)
200 rStream
.ReadUInt32( aMagic32
);
201 rStream
.ReadUInt16( aMagic16
);
203 // Compare EXIF magic bytes
204 if( 0x45786966 != aMagic32
|| 0x0000 != aMagic16
)
209 sal_uInt16 aLength
= aSectionLength
- 6; // Length = Section - Header
211 boost::scoped_array
<sal_uInt8
> aExifData(new sal_uInt8
[aLength
]);
212 sal_uInt32 aExifDataBeginPosition
= rStream
.Tell();
214 rStream
.Read(aExifData
.get(), aLength
);
217 mbExifPresent
= true;
219 TiffHeader
* aTiffHeader
= reinterpret_cast<TiffHeader
*>(&aExifData
[0]);
221 bool bIntel
= aTiffHeader
->byteOrder
== 0x4949; //big-endian
222 bool bMotorola
= aTiffHeader
->byteOrder
== 0x4D4D; //little-endian
224 if (!bIntel
&& !bMotorola
)
241 aTiffHeader
->tagAlign
= OSL_SWAPWORD(aTiffHeader
->tagAlign
);
242 aTiffHeader
->offset
= OSL_SWAPDWORD(aTiffHeader
->offset
);
245 if (aTiffHeader
->tagAlign
!= 0x002A) // TIFF tag
250 sal_uInt16 aOffset
= aTiffHeader
->offset
;
252 sal_uInt16 aNumberOfTags
= aExifData
[aOffset
];
255 aNumberOfTags
= ((aExifData
[aOffset
] << 8) | aExifData
[aOffset
+1]);
258 processIFD(aExifData
.get(), aLength
, aOffset
+2, aNumberOfTags
, bSetValue
, bSwap
);
262 rStream
.Seek(aExifDataBeginPosition
);
263 rStream
.Write(aExifData
.get(), aLength
);
269 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */