Kaydet (Commit) 4f3bc8cf authored tarafından Tomaž Vajngerl's avatar Tomaž Vajngerl

More correct reading of Exif metadata.

Change-Id: Id9e7754cfcbd1d7e8b512eb1c1a3384df2db149f
üst df155415
......@@ -20,7 +20,8 @@
#include "Exif.hxx"
Exif::Exif() :
maOrientation(TOP_LEFT)
maOrientation(TOP_LEFT),
mbExifPresent(false)
{}
Exif::~Exif()
......@@ -66,10 +67,15 @@ sal_Int32 Exif::getRotation()
return 0;
}
bool Exif::hasExif()
{
return mbExifPresent;
}
bool Exif::read(SvStream& rStream)
{
sal_Int32 nStreamPosition = rStream.Tell();
bool result = processJpegStream(rStream, false);
bool result = processJpeg(rStream, false);
rStream.Seek( nStreamPosition );
return result;
......@@ -78,33 +84,81 @@ bool Exif::read(SvStream& rStream)
bool Exif::write(SvStream& rStream)
{
sal_Int32 nStreamPosition = rStream.Tell();
bool result = processJpegStream(rStream, true);
bool result = processJpeg(rStream, true);
rStream.Seek( nStreamPosition );
return result;
}
bool Exif::processJpegStream(SvStream& rStream, bool bSetValue)
bool Exif::processJpeg(SvStream& rStream, bool bSetValue)
{
sal_uInt32 aMagic32;
sal_uInt16 aMagic16;
sal_uInt8 aMarker;
sal_uInt16 aLength;
rStream.Seek(STREAM_SEEK_TO_END);
sal_uInt32 aSize = rStream.Tell();
rStream.Seek(STREAM_SEEK_TO_BEGIN);
rStream.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
rStream >> aMagic32;
rStream >> aMagic16;
// Compare JPEG magic bytes
if( 0xffd8ff00 != ( aMagic32 & 0xffffff00 ) )
if( 0xFFD8 != aMagic16 )
{
return false;
}
rStream >> aLength;
if (aLength < 8)
sal_uInt32 aPreviousPosition = STREAM_SEEK_TO_BEGIN;
while(true)
{
return false;
sal_Int32 aCount;
for (aCount = 0; aCount < 7; aCount++)
{
rStream >> aMarker;
if (aMarker != 0xFF)
{
break;
}
if (aCount >= 6)
{
return false;
}
}
rStream >> aLength;
if (aLength < 8)
{
return false;
}
if (aMarker == 0xE1)
{
return processExif(rStream, aLength, bSetValue);
}
else if (aMarker == 0xD9)
{
return false;
}
else
{
sal_uInt32 aCurrentPosition = rStream.SeekRel(aLength-1);
if (aCurrentPosition == aPreviousPosition || aCurrentPosition > aSize)
{
return false;
}
aPreviousPosition = aCurrentPosition;
}
}
aLength -= 8;
return false;
}
bool Exif::processExif(SvStream& rStream, sal_uInt16 aSectionLength, bool bSetValue)
{
sal_uInt32 aMagic32;
sal_uInt16 aMagic16;
rStream >> aMagic32;
rStream >> aMagic16;
......@@ -115,26 +169,36 @@ bool Exif::processJpegStream(SvStream& rStream, bool bSetValue)
return false;
}
sal_uInt8* exifData = new sal_uInt8[aLength];
sal_uInt16 aLength = aSectionLength - 6; // Length = Section - Header
sal_uInt8* aExifData = new sal_uInt8[aLength];
sal_uInt32 aExifDataBeginPosition = rStream.Tell();
rStream.Read(exifData, aLength);
sal_uInt16 offset;
offset = exifData[5];
offset <<= 8;
offset += exifData[4];
rStream.Read(aExifData, aLength);
// Exif detected
mbExifPresent = true;
TiffHeader* aTiffHeader = (TiffHeader*) &aExifData[0];
if( 0x4949 != aTiffHeader->byteOrder || 0x002A != aTiffHeader->tagAlign )
{
return false;
}
sal_uInt16 aOffset = aTiffHeader->offset;
sal_uInt16 numberOfTags;
numberOfTags = exifData[offset+1];
numberOfTags <<= 8;
numberOfTags += exifData[offset];
sal_uInt16 aNumberOfTags = aExifData[aOffset];
aNumberOfTags = aExifData[aOffset + 1];
aNumberOfTags <<= 8;
aNumberOfTags += aExifData[aOffset];
offset += 2;
aOffset += 2;
ExifIFD* ifd = NULL;
while (offset <= aLength - 12 && numberOfTags > 0) {
ifd = (ExifIFD*) &exifData[offset];
while (aOffset <= aLength - 12 && aNumberOfTags > 0) {
ifd = (ExifIFD*) &aExifData[aOffset];
if (ifd->tag == Tag::ORIENTATION)
{
......@@ -151,14 +215,14 @@ bool Exif::processJpegStream(SvStream& rStream, bool bSetValue)
}
}
numberOfTags--;
offset += 12;
aNumberOfTags--;
aOffset += 12;
}
if (bSetValue)
{
rStream.Seek(aExifDataBeginPosition);
rStream.Write(exifData, aLength);
rStream.Write(aExifData, aLength);
}
return true;
......
......@@ -38,11 +38,11 @@ enum Orientation {
};
enum Tag {
IMAGE_WIDTH = 0x0100,
IMAGE_HEIGHT = 0x0101,
BITS_PER_SAMPLE = 0x0102,
COMPRESSION = 0x0103,
ORIENTATION = 0x0112
ORIENTATION = 0x0112,
X_RESOLUTION = 0x011a,
Y_RESOLUTION = 0x011b,
EXIF_OFFSET = 0x8769,
INTEROP_OFFSET = 0xa005
};
class Exif
......@@ -50,8 +50,10 @@ class Exif
private:
Orientation maOrientation;
sal_Int32 mnStreamPosition;
bool mbExifPresent;
bool processJpegStream(SvStream& rStream, bool bSetValue);
bool processJpeg(SvStream& rStream, bool bSetValue);
bool processExif(SvStream& rStream, sal_uInt16 aLength, bool bSetValue);
struct ExifIFD {
sal_uInt16 tag;
......@@ -60,12 +62,20 @@ private:
sal_uInt32 offset;
};
struct TiffHeader {
sal_uInt16 byteOrder;
sal_uInt16 tagAlign;
sal_uInt32 offset;
};
Orientation convertToOrientation(sal_Int32 value);
public :
Exif();
virtual ~Exif();
bool hasExif();
Orientation getOrientation();
sal_Int32 getRotation();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment