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 .
23 maOrientation(TOP_LEFT
),
30 Orientation
Exif::getOrientation() {
34 void Exif::setOrientation(Orientation aOrientation
) {
35 maOrientation
= aOrientation
;
38 Orientation
Exif::convertToOrientation(sal_Int32 value
)
41 case 1: return TOP_LEFT
;
42 case 2: return TOP_RIGHT
;
43 case 3: return BOTTOM_RIGHT
;
44 case 4: return BOTTOM_LEFT
;
45 case 5: return LEFT_TOP
;
46 case 6: return RIGHT_TOP
;
47 case 7: return RIGHT_BOTTOM
;
48 case 8: return LEFT_BOTTOM
;
53 sal_Int32
Exif::getRotation()
55 switch(maOrientation
) {
75 bool Exif::read(SvStream
& rStream
)
77 sal_Int32 nStreamPosition
= rStream
.Tell();
78 bool result
= processJpeg(rStream
, false);
79 rStream
.Seek( nStreamPosition
);
84 bool Exif::write(SvStream
& rStream
)
86 sal_Int32 nStreamPosition
= rStream
.Tell();
87 bool result
= processJpeg(rStream
, true);
88 rStream
.Seek( nStreamPosition
);
93 bool Exif::processJpeg(SvStream
& rStream
, bool bSetValue
)
98 rStream
.Seek(STREAM_SEEK_TO_END
);
99 sal_uInt32 aSize
= rStream
.Tell();
100 rStream
.Seek(STREAM_SEEK_TO_BEGIN
);
102 rStream
.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN
);
105 // Compare JPEG magic bytes
106 if( 0xFFD8 != aMagic16
)
111 sal_uInt32 aPreviousPosition
= STREAM_SEEK_TO_BEGIN
;
115 sal_uInt8 aMarker
= 0xD9;
118 for (aCount
= 0; aCount
< 7; aCount
++)
140 return processExif(rStream
, aLength
, bSetValue
);
142 else if (aMarker
== 0xD9)
148 sal_uInt32 aCurrentPosition
= rStream
.SeekRel(aLength
-1);
149 if (aCurrentPosition
== aPreviousPosition
|| aCurrentPosition
> aSize
)
153 aPreviousPosition
= aCurrentPosition
;
159 bool Exif::processIFD(sal_uInt8
* pExifData
, sal_uInt16 aLength
, sal_uInt16 aOffset
, sal_uInt16 aNumberOfTags
, bool bSetValue
, bool bSwap
)
163 while (aOffset
<= aLength
- 12 && aNumberOfTags
> 0)
165 ifd
= (ExifIFD
*) &pExifData
[aOffset
];
166 sal_uInt16 tag
= ifd
->tag
;
169 tag
= OSL_SWAPWORD(ifd
->tag
);
172 if (tag
== ORIENTATION
)
176 ifd
->tag
= ORIENTATION
;
179 ifd
->offset
= maOrientation
;
182 ifd
->tag
= OSL_SWAPWORD(ifd
->tag
);
183 ifd
->offset
= OSL_SWAPWORD(ifd
->offset
);
188 sal_uInt32 nIfdOffset
= ifd
->offset
;
190 nIfdOffset
= OSL_SWAPWORD(ifd
->offset
);
191 maOrientation
= convertToOrientation(nIfdOffset
);
201 bool Exif::processExif(SvStream
& rStream
, sal_uInt16 aSectionLength
, bool bSetValue
)
209 // Compare EXIF magic bytes
210 if( 0x45786966 != aMagic32
|| 0x0000 != aMagic16
)
215 sal_uInt16 aLength
= aSectionLength
- 6; // Length = Section - Header
217 sal_uInt8
* aExifData
= new sal_uInt8
[aLength
];
218 sal_uInt32 aExifDataBeginPosition
= rStream
.Tell();
220 rStream
.Read(aExifData
, aLength
);
223 mbExifPresent
= true;
225 TiffHeader
* aTiffHeader
= (TiffHeader
*) &aExifData
[0];
227 bool bIntel
= aTiffHeader
->byteOrder
== 0x4949; //big-endian
228 bool bMotorola
= aTiffHeader
->byteOrder
== 0x4D4D; //little-endian
230 if (!bIntel
&& !bMotorola
)
248 aTiffHeader
->tagAlign
= OSL_SWAPWORD(aTiffHeader
->tagAlign
);
249 aTiffHeader
->offset
= OSL_SWAPDWORD(aTiffHeader
->offset
);
252 if (aTiffHeader
->tagAlign
!= 0x002A) // TIFF tag
258 sal_uInt16 aOffset
= aTiffHeader
->offset
;
260 sal_uInt16 aNumberOfTags
= aExifData
[aOffset
];
263 aNumberOfTags
= ((aExifData
[aOffset
] << 8) | aExifData
[aOffset
+1]);
266 processIFD(aExifData
, aLength
, aOffset
+2, aNumberOfTags
, bSetValue
, bSwap
);
270 rStream
.Seek(aExifDataBeginPosition
);
271 rStream
.Write(aExifData
, aLength
);
278 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */