Subversion Repositories Scribus

Rev

Rev 13951 | Rev 19730 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
3685 fschmid 7
//--------------------------------------------------------------------------
8
// Program to pull the information out of various types of EFIF digital
9
// camera files and show it in a reasonably consistent way
10
//
11
// This module parses the very complicated exif structures.
12
//
13
// Matthias Wandel,  Dec 1999 - August 2000
14
//--------------------------------------------------------------------------
15
 
16
 
17
#include "exif.h"
13951 fschmid 18
#include <QTransform>
3685 fschmid 19
 
20
//--------------------------------------------------------------------------
21
// Table of Jpeg encoding process names
22
 
23
#define M_SOF0  0xC0            // Start Of Frame N
24
#define M_SOF1  0xC1            // N indicates which compression process
25
#define M_SOF2  0xC2            // Only SOF0-SOF2 are now in common use
26
#define M_SOF3  0xC3
27
#define M_SOF5  0xC5            // NB: codes C4 and CC are NOT SOF markers
28
#define M_SOF6  0xC6
29
#define M_SOF7  0xC7
30
#define M_SOF9  0xC9
31
#define M_SOF10 0xCA
32
#define M_SOF11 0xCB
33
#define M_SOF13 0xCD
34
#define M_SOF14 0xCE
35
#define M_SOF15 0xCF
36
#define M_SOI   0xD8            // Start Of Image (beginning of datastream)
37
#define M_EOI   0xD9            // End Of Image (end of datastream)
38
#define M_SOS   0xDA            // Start Of Scan (begins compressed data)
39
#define M_JFIF  0xE0            // Jfif marker
40
#define M_EXIF  0xE1            // Exif marker
41
#define M_COM   0xFE            // COMment
42
 
43
 
10911 fschmid 44
TagTable ProcessTable[] =
45
    {
46
        TagTable ( M_SOF0,   "Baseline" ),
47
        TagTable ( M_SOF1,   "Extended sequential" ),
48
        TagTable ( M_SOF2,   "Progressive" ),
49
        TagTable ( M_SOF3,   "Lossless" ),
50
        TagTable ( M_SOF5,   "Differential sequential" ),
51
        TagTable ( M_SOF6,   "Differential progressive" ),
52
        TagTable ( M_SOF7,   "Differential lossless" ),
53
        TagTable ( M_SOF9,   "Extended sequential, arithmetic coding" ),
54
        TagTable ( M_SOF10,  "Progressive, arithmetic coding" ),
55
        TagTable ( M_SOF11,  "Lossless, arithmetic coding" ),
56
        TagTable ( M_SOF13,  "Differential sequential, arithmetic coding" ),
57
        TagTable ( M_SOF14,  "Differential progressive, arithmetic coding" ),
58
        TagTable ( M_SOF15,  "Differential lossless, arithmetic coding" ),
59
        TagTable ( 0,        "Unknown" )
60
    };
3685 fschmid 61
 
62
//--------------------------------------------------------------------------
63
// Describes format descriptor
64
static int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
65
#define NUM_FORMATS 12
66
 
67
#define FMT_BYTE       1
68
#define FMT_STRING     2
69
#define FMT_USHORT     3
70
#define FMT_ULONG      4
71
#define FMT_URATIONAL  5
72
#define FMT_SBYTE      6
73
#define FMT_UNDEFINED  7
74
#define FMT_SSHORT     8
75
#define FMT_SLONG      9
76
#define FMT_SRATIONAL 10
77
#define FMT_SINGLE    11
78
#define FMT_DOUBLE    12
79
 
80
//--------------------------------------------------------------------------
81
// Describes tag values
82
 
83
#define TAG_EXIF_OFFSET       0x8769
84
#define TAG_INTEROP_OFFSET    0xa005
85
 
86
#define TAG_MAKE              0x010F
87
#define TAG_MODEL             0x0110
88
#define TAG_ORIENTATION       0x0112
89
 
90
#define TAG_EXPOSURETIME      0x829A
91
#define TAG_FNUMBER           0x829D
92
 
93
#define TAG_SHUTTERSPEED      0x9201
94
#define TAG_APERTURE          0x9202
95
#define TAG_MAXAPERTURE       0x9205
96
#define TAG_FOCALLENGTH       0x920A
97
 
98
#define TAG_DATETIME_ORIGINAL 0x9003
99
#define TAG_USERCOMMENT       0x9286
100
 
101
#define TAG_SUBJECT_DISTANCE  0x9206
102
#define TAG_FLASH             0x9209
103
 
104
#define TAG_FOCALPLANEXRES    0xa20E
105
#define TAG_FOCALPLANEUNITS   0xa210
106
#define TAG_EXIF_IMAGEWIDTH   0xA002
107
#define TAG_EXIF_IMAGELENGTH  0xA003
108
 
109
// the following is added 05-jan-2001 vcs
110
#define TAG_EXPOSURE_BIAS     0x9204
111
#define TAG_WHITEBALANCE      0x9208
112
#define TAG_METERING_MODE     0x9207
113
#define TAG_EXPOSURE_PROGRAM  0x8822
114
#define TAG_ISO_EQUIVALENT    0x8827
115
#define TAG_COMPRESSION_LEVEL 0x9102
116
 
117
#define TAG_THUMBNAIL_OFFSET  0x0201
118
#define TAG_THUMBNAIL_LENGTH  0x0202
119
 
120
 
121
/*static TagTable_t TagTable[] = {
122
  {   0x100,   "ImageWidth"},
123
  {   0x101,   "ImageLength"},
124
  {   0x102,   "BitsPerSample"},
125
  {   0x103,   "Compression"},
126
  {   0x106,   "PhotometricInterpretation"},
127
  {   0x10A,   "FillOrder"},
128
  {   0x10D,   "DocumentName"},
129
  {   0x10E,   "ImageDescription"},
130
  {   0x10F,   "Make"},
131
  {   0x110,   "Model"},
132
  {   0x111,   "StripOffsets"},
133
  {   0x112,   "Orientation"},
134
  {   0x115,   "SamplesPerPixel"},
135
  {   0x116,   "RowsPerStrip"},
136
  {   0x117,   "StripByteCounts"},
137
  {   0x11A,   "XResolution"},
138
  {   0x11B,   "YResolution"},
139
  {   0x11C,   "PlanarConfiguration"},
140
  {   0x128,   "ResolutionUnit"},
141
  {   0x12D,   "TransferFunction"},
142
  {   0x131,   "Software"},
143
  {   0x132,   "DateTime"},
144
  {   0x13B,   "Artist"},
145
  {   0x13E,   "WhitePoint"},
146
  {   0x13F,   "PrimaryChromaticities"},
147
  {   0x156,   "TransferRange"},
148
  {   0x200,   "JPEGProc"},
149
  {   0x201,   "ThumbnailOffset"},
150
  {   0x202,   "ThumbnailLength"},
151
  {   0x211,   "YCbCrCoefficients"},
152
  {   0x212,   "YCbCrSubSampling"},
153
  {   0x213,   "YCbCrPositioning"},
154
  {   0x214,   "ReferenceBlackWhite"},
155
  {   0x828D,  "CFARepeatPatternDim"},
156
  {   0x828E,  "CFAPattern"},
157
  {   0x828F,  "BatteryLevel"},
158
  {   0x8298,  "Copyright"},
159
  {   0x829A,  "ExposureTime"},
160
  {   0x829D,  "FNumber"},
161
  {   0x83BB,  "IPTC/NAA"},
162
  {   0x8769,  "ExifOffset"},
163
  {   0x8773,  "InterColorProfile"},
164
  {   0x8822,  "ExposureProgram"},
165
  {   0x8824,  "SpectralSensitivity"},
166
  {   0x8825,  "GPSInfo"},
167
  {   0x8827,  "ISOSpeedRatings"},
168
  {   0x8828,  "OECF"},
169
  {   0x9000,  "ExifVersion"},
170
  {   0x9003,  "DateTimeOriginal"},
171
  {   0x9004,  "DateTimeDigitized"},
172
  {   0x9101,  "ComponentsConfiguration"},
173
  {   0x9102,  "CompressedBitsPerPixel"},
174
  {   0x9201,  "ShutterSpeedValue"},
175
  {   0x9202,  "ApertureValue"},
176
  {   0x9203,  "BrightnessValue"},
177
  {   0x9204,  "ExposureBiasValue"},
178
  {   0x9205,  "MaxApertureValue"},
179
  {   0x9206,  "SubjectDistance"},
180
  {   0x9207,  "MeteringMode"},
181
  {   0x9208,  "LightSource"},
182
  {   0x9209,  "Flash"},
183
  {   0x920A,  "FocalLength"},
184
  {   0x927C,  "MakerNote"},
185
  {   0x9286,  "UserComment"},
186
  {   0x9290,  "SubSecTime"},
187
  {   0x9291,  "SubSecTimeOriginal"},
188
  {   0x9292,  "SubSecTimeDigitized"},
189
  {   0xA000,  "FlashPixVersion"},
190
  {   0xA001,  "ColorSpace"},
191
  {   0xA002,  "ExifImageWidth"},
192
  {   0xA003,  "ExifImageLength"},
193
  {   0xA005,  "InteroperabilityOffset"},
194
  {   0xA20B,  "FlashEnergy"},                 // 0x920B in TIFF/EP
195
  {   0xA20C,  "SpatialFrequencyResponse"},  // 0x920C    -  -
196
  {   0xA20E,  "FocalPlaneXResolution"},     // 0x920E    -  -
197
  {   0xA20F,  "FocalPlaneYResolution"},      // 0x920F    -  -
198
  {   0xA210,  "FocalPlaneResolutionUnit"},  // 0x9210    -  -
199
  {   0xA214,  "SubjectLocation"},             // 0x9214    -  -
200
  {   0xA215,  "ExposureIndex"},            // 0x9215    -  -
201
  {   0xA217,  "SensingMethod"},            // 0x9217    -  -
202
  {   0xA300,  "FileSource"},
203
  {   0xA301,  "SceneType"},
204
  {      0, NULL}
205
} ;
206
*/
207
 
10911 fschmid 208
int ExifData::getch ( QFile &infile )
10507 fschmid 209
{
10911 fschmid 210
        QByteArray a = infile.read ( 1 );
10507 fschmid 211
        uint r = 0;
10911 fschmid 212
        r = static_cast<uint> ( a[0] );
10507 fschmid 213
        r &= 0x000000FF;
10911 fschmid 214
        return static_cast<int> ( r );
10507 fschmid 215
}
3685 fschmid 216
//--------------------------------------------------------------------------
217
// Parse the marker stream until SOS or EOI is seen;
218
//--------------------------------------------------------------------------
10911 fschmid 219
int ExifData::ReadJpegSections ( QFile & infile, ReadMode_t ReadMode )
3685 fschmid 220
{
10911 fschmid 221
        int a;
12898 fschmid 222
        int SectionsRead;
3685 fschmid 223
 
10911 fschmid 224
        a = getch ( infile );
3685 fschmid 225
 
10911 fschmid 226
        if ( a != 0xff || getch ( infile ) != M_SOI )
227
        {
228
                SectionsRead = 0;
229
                return false;
230
        }
12898 fschmid 231
        for ( SectionsRead = 0; SectionsRead < MAX_SECTIONS-1; SectionsRead++ )
10911 fschmid 232
        {
233
                int marker = 0;
234
                int got;
235
                unsigned int ll,lh;
236
                unsigned int itemlen;
237
                uchar * Data;
3685 fschmid 238
 
10911 fschmid 239
                for ( a=0;a<7;a++ )
240
                {
241
                        marker = getch ( infile );
12898 fschmid 242
                        if ( marker != 0xff )
243
                                break;
10911 fschmid 244
                        if ( a >= 6 )
245
                                return false;
246
                }
247
                if ( marker == 0xff )
248
                        return false;
249
                // Read the length of the section.
250
                lh = ( uchar ) getch ( infile );
251
                ll = ( uchar ) getch ( infile );
252
                itemlen = ( lh << 8 ) | ll;
253
                if ( itemlen < 2 )
254
                        return false;
255
                Data = ( uchar * ) malloc ( itemlen+1 ); // Add 1 to allow sticking a 0 at the end.
3685 fschmid 256
 
10911 fschmid 257
                // Store first two pre-read bytes.
258
                Data[0] = ( uchar ) lh;
259
                Data[1] = ( uchar ) ll;
3685 fschmid 260
 
10911 fschmid 261
                got = infile.read ( ( char* ) Data+2, itemlen-2 ); // Read the whole section.
262
                if ( ( unsigned ) got != itemlen-2 )
263
                {
12898 fschmid 264
                        free(Data);
10911 fschmid 265
                        return false;
266
                }
3685 fschmid 267
 
10911 fschmid 268
                switch ( marker )
269
                {
3685 fschmid 270
 
10911 fschmid 271
                        case M_SOS:   // stop before hitting compressed data
12898 fschmid 272
                                free(Data);
10911 fschmid 273
                                return true;
3685 fschmid 274
 
10911 fschmid 275
                        case M_EOI:   // in case it's a tables-only JPEG stream
12898 fschmid 276
                                free(Data);
10911 fschmid 277
                                return false;
3685 fschmid 278
 
10911 fschmid 279
                        case M_COM: // Comment section
280
                                // pieczy 2002-02-12
281
                                // now the User comment goes to UserComment
282
                                // so we can store a Comment section also in READ_EXIF mode
283
                                process_COM ( Data, itemlen );
284
                                break;
3685 fschmid 285
 
10911 fschmid 286
                        case M_JFIF:
287
                                // Regular jpegs always have this tag, exif images have the exif
288
                                // marker instead, althogh ACDsee will write images with both markers.
289
                                // this program will re-create this marker on absence of exif marker.
290
                                // hence no need to keep the copy from the file.
291
                                break;
3685 fschmid 292
 
10911 fschmid 293
                        case M_EXIF:
294
                                // Seen files from some 'U-lead' software with Vivitar scanner
295
                                // that uses marker 31 for non exif stuff.  Thus make sure
296
                                // it says 'Exif' in the section before treating it as exif.
297
                                if ( ( ReadMode & READ_EXIF ) && memcmp ( Data+2, "Exif", 4 ) == 0 )
298
                                {
299
                                        process_EXIF ( ( uchar * ) Data, itemlen ); // FIXME: This call
300
                                        // requires Data to be array of at least 8 bytes. Code
301
                                        // above only checks for itemlen < 2.
3898 fschmid 302
                                        exifDataValid = true;
10911 fschmid 303
                                }
12898 fschmid 304
//                              else
305
//                              {
306
//                                      // Discard this section.
307
//                                      free ( Sections[--SectionsRead].Data );
3880 fschmid 308
//                    return false;
12898 fschmid 309
//                              }
10911 fschmid 310
                                break;
3685 fschmid 311
 
10911 fschmid 312
                        case M_SOF0:
313
                        case M_SOF1:
314
                        case M_SOF2:
315
                        case M_SOF3:
316
                        case M_SOF5:
317
                        case M_SOF6:
318
                        case M_SOF7:
319
                        case M_SOF9:
320
                        case M_SOF10:
321
                        case M_SOF11:
322
                        case M_SOF13:
323
                        case M_SOF14:
324
                        case M_SOF15:
325
                                process_SOFn ( Data, marker ); //FIXME: This call requires Data to
326
                                // be array of at least 8 bytes. Code above only checks for
327
                                // itemlen < 2.
10914 fschmid 328
                                break;
10911 fschmid 329
                        default:
330
                                break;
331
                }
12898 fschmid 332
                free(Data);
10911 fschmid 333
        }
334
        return true;
3685 fschmid 335
}
336
 
337
 
338
//--------------------------------------------------------------------------
339
// Discard read data.
340
//--------------------------------------------------------------------------
10911 fschmid 341
void ExifData::DiscardData ( void )
3685 fschmid 342
{
12898 fschmid 343
//      for ( int a=0; a < SectionsRead; a++ )
344
//              free ( Sections[a].Data );
345
//      SectionsRead = 0;
3685 fschmid 346
}
347
 
348
//--------------------------------------------------------------------------
349
// Convert a 16 bit unsigned value from file's native byte order
350
//--------------------------------------------------------------------------
10911 fschmid 351
int ExifData::Get16u ( void * Short )
3685 fschmid 352
{
10911 fschmid 353
        if ( MotorolaOrder )
354
        {
355
                return ( ( ( uchar * ) Short ) [0] << 8 ) | ( ( uchar * ) Short ) [1];
356
        }
357
        else
358
        {
359
                return ( ( ( uchar * ) Short ) [1] << 8 ) | ( ( uchar * ) Short ) [0];
360
        }
3685 fschmid 361
}
362
 
363
//--------------------------------------------------------------------------
364
// Convert a 32 bit signed value from file's native byte order
365
//--------------------------------------------------------------------------
10911 fschmid 366
int ExifData::Get32s ( void * Long )
3685 fschmid 367
{
10911 fschmid 368
        if ( MotorolaOrder )
369
        {
370
                return ( ( ( char * ) Long ) [0] << 24 ) | ( ( ( uchar * ) Long ) [1] << 16 )
371
                       | ( ( ( uchar * ) Long ) [2] << 8 ) | ( ( ( uchar * ) Long ) [3] << 0 );
372
        }
373
        else
374
        {
375
                return ( ( ( char * ) Long ) [3] << 24 ) | ( ( ( uchar * ) Long ) [2] << 16 )
376
                       | ( ( ( uchar * ) Long ) [1] << 8 ) | ( ( ( uchar * ) Long ) [0] << 0 );
377
        }
3685 fschmid 378
}
379
 
380
//--------------------------------------------------------------------------
381
// Convert a 32 bit unsigned value from file's native byte order
382
//--------------------------------------------------------------------------
10911 fschmid 383
unsigned ExifData::Get32u ( void * Long )
3685 fschmid 384
{
10911 fschmid 385
        return ( unsigned ) Get32s ( Long ) & 0xffffffff;
3685 fschmid 386
}
387
 
388
//--------------------------------------------------------------------------
389
// Evaluate number, be it int, rational, or float from directory.
390
//--------------------------------------------------------------------------
10911 fschmid 391
double ExifData::ConvertAnyFormat ( void * ValuePtr, int Format )
3685 fschmid 392
{
10911 fschmid 393
        double Value;
394
        Value = 0;
3685 fschmid 395
 
10911 fschmid 396
        switch ( Format )
397
        {
398
                case FMT_SBYTE:     Value = * ( signed char * ) ValuePtr;  break;
399
                case FMT_BYTE:      Value = * ( uchar * ) ValuePtr;        break;
3685 fschmid 400
 
10911 fschmid 401
                case FMT_USHORT:    Value = Get16u ( ValuePtr );          break;
3685 fschmid 402
 
10911 fschmid 403
                case FMT_ULONG:     Value = Get32u ( ValuePtr );          break;
3685 fschmid 404
 
10911 fschmid 405
                case FMT_URATIONAL:
406
                case FMT_SRATIONAL:
407
                {
408
                        int Num,Den;
409
                        Num = Get32s ( ValuePtr );
410
                        Den = Get32s ( 4+ ( char * ) ValuePtr );
411
                        if ( Den == 0 )
412
                        {
413
                                Value = 0;
414
                        }
415
                        else
416
                        {
417
                                Value = ( double ) Num/Den;
418
                        }
419
                        break;
420
                }
3685 fschmid 421
 
10911 fschmid 422
                case FMT_SSHORT:    Value = ( signed short ) Get16u ( ValuePtr );  break;
423
                case FMT_SLONG:     Value = Get32s ( ValuePtr );                break;
3685 fschmid 424
 
10911 fschmid 425
                        // Not sure if this is correct (never seen float used in Exif format)
426
                case FMT_SINGLE:    Value = ( double ) * ( float * ) ValuePtr;      break;
427
                case FMT_DOUBLE:    Value = * ( double * ) ValuePtr;             break;
428
        }
429
        return Value;
3685 fschmid 430
}
431
 
432
//--------------------------------------------------------------------------
433
// Process one of the nested EXIF directories.
434
//--------------------------------------------------------------------------
10911 fschmid 435
void ExifData::ProcessExifDir ( unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength )
3685 fschmid 436
{
10911 fschmid 437
        int de;
438
        int a;
439
        int NumDirEntries;
440
        unsigned ThumbnailOffset = 0;
441
        unsigned ThumbnailSize = 0;
442
        recurseLevel++;
443
        if (recurseLevel > 3)
444
                return;
445
        NumDirEntries = Get16u ( DirStart );
446
#define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
3685 fschmid 447
 
10911 fschmid 448
        {
449
                unsigned char * DirEnd;
450
                DirEnd = DIR_ENTRY_ADDR ( DirStart, NumDirEntries );
451
                if ( DirEnd+4 > ( OffsetBase+ExifLength ) )
452
                {
453
                        if ( DirEnd+2 == OffsetBase+ExifLength || DirEnd == OffsetBase+ExifLength )
454
                        {
455
                                // Version 1.3 of jhead would truncate a bit too much.
456
                                // This also caught later on as well.
457
                        }
458
                        else
459
                        {
460
                                // Note: Files that had thumbnails trimmed with jhead 1.3 or earlier
461
                                // might trigger this.
462
                                return;
3685 fschmid 463
//                throw FatalError("Illegally sized directory");
10911 fschmid 464
                        }
465
                }
466
                if ( DirEnd < LastExifRefd ) LastExifRefd = DirEnd;
467
        }
3685 fschmid 468
 
10911 fschmid 469
        for ( de=0;de<NumDirEntries;de++ )
470
        {
471
                int Tag, Format, Components;
472
                unsigned char * ValuePtr;
473
                int ByteCount;
474
                char * DirEntry;
475
                DirEntry = ( char * ) DIR_ENTRY_ADDR ( DirStart, de );
3685 fschmid 476
 
10911 fschmid 477
                Tag = Get16u ( DirEntry );
478
                Format = Get16u ( DirEntry+2 );
479
                Components = Get32u ( DirEntry+4 );
3685 fschmid 480
 
10911 fschmid 481
                if ( ( Format-1 ) >= NUM_FORMATS )
482
                {
483
                        // (-1) catches illegal zero case as unsigned underflows to positive large.
484
                        return;
3685 fschmid 485
//            throw FatalError("Illegal format code in EXIF dir");
10911 fschmid 486
                }
10914 fschmid 487
                if ((unsigned)Components > 0x10000)
488
                        continue;
10911 fschmid 489
                ByteCount = Components * BytesPerFormat[Format];
3685 fschmid 490
 
10911 fschmid 491
                if ( ByteCount > 4 )
492
                {
493
                        unsigned OffsetVal;
494
                        OffsetVal = Get32u ( DirEntry+8 );
495
                        // If its bigger than 4 bytes, the dir entry contains an offset.
496
                        if ( OffsetVal+ByteCount > ExifLength )
497
                        {
498
                                // Bogus pointer offset and / or bytecount value
499
                                //printf("Offset %d bytes %d ExifLen %d\n",OffsetVal, ByteCount, ExifLength);
3685 fschmid 500
 
10911 fschmid 501
                                return ;
3685 fschmid 502
//                throw FatalError("Illegal pointer offset value in EXIF");
10911 fschmid 503
                        }
504
                        ValuePtr = OffsetBase+OffsetVal;
505
                }
506
                else
507
                {
508
                        // 4 bytes or less and value is in the dir entry itself
509
                        ValuePtr = ( unsigned char * ) DirEntry+8;
510
                }
3685 fschmid 511
 
10911 fschmid 512
                if ( LastExifRefd < ValuePtr+ByteCount )
513
                {
514
                        // Keep track of last byte in the exif header that was actually referenced.
515
                        // That way, we know where the discardable thumbnail data begins.
516
                        LastExifRefd = ValuePtr+ByteCount;
517
                }
3685 fschmid 518
 
10911 fschmid 519
                // Extract useful components of tag
520
                switch ( Tag )
521
                {
3685 fschmid 522
 
10911 fschmid 523
                        case TAG_MAKE:
524
                                ExifData::CameraMake = QString ( ( char* ) ValuePtr );
525
                                break;
3685 fschmid 526
 
10911 fschmid 527
                        case TAG_MODEL:
528
                                ExifData::CameraModel = QString ( ( char* ) ValuePtr );
529
                                break;
3685 fschmid 530
 
10911 fschmid 531
                        case TAG_ORIENTATION:
16438 fschmid 532
                                if (orientationCount == 0)
533
                                {
534
                                        Orientation = ( int ) ConvertAnyFormat ( ValuePtr, Format );
535
                                        orientationCount++;
536
                                }
10911 fschmid 537
                                break;
3685 fschmid 538
 
10911 fschmid 539
                        case TAG_DATETIME_ORIGINAL:
540
                                DateTime = QString ( ( char* ) ValuePtr );
541
                                break;
3685 fschmid 542
 
10911 fschmid 543
                        case TAG_USERCOMMENT:
544
                                // Olympus has this padded with trailing spaces.  Remove these first.
545
                                for ( a=ByteCount;; )
546
                                {
547
                                        a--;
548
                                        if ( ( ValuePtr ) [a] == ' ' )
549
                                        {
550
                                                ( ValuePtr ) [a] = '\0';
551
                                        }
552
                                        else
553
                                        {
554
                                                break;
555
                                        }
556
                                        if ( a == 0 ) break;
557
                                }
3685 fschmid 558
 
10911 fschmid 559
                                // Copy the comment
560
                                if ( memcmp ( ValuePtr, "ASCII",5 ) == 0 )
561
                                {
562
                                        for ( a=5;a<10;a++ )
563
                                        {
564
                                                int c;
565
                                                c = ( ValuePtr ) [a];
566
                                                if ( c != '\0' && c != ' ' )
567
                                                {
568
                                                        //strncpy(ImageInfo.Comments, (const char*)(a+ValuePtr), 199);
569
                                                        UserComment.sprintf ( "%s", ( const char* ) ( a+ValuePtr ) );
570
                                                        break;
571
                                                }
572
                                        }
573
                                }
574
                                else
575
                                {
576
                                        //strncpy(ImageInfo.Comments, (const char*)ValuePtr, 199);
577
                                        UserComment.sprintf ( "%s", ( const char* ) ValuePtr );
578
                                }
579
                                break;
3685 fschmid 580
 
10911 fschmid 581
                        case TAG_FNUMBER:
582
                                // Simplest way of expressing aperture, so I trust it the most.
583
                                // (overwrite previously computd value if there is one)
584
                                ExifData::ApertureFNumber = ( float ) ConvertAnyFormat ( ValuePtr, Format );
585
                                break;
3685 fschmid 586
 
10911 fschmid 587
                        case TAG_APERTURE:
588
                        case TAG_MAXAPERTURE:
589
                                // More relevant info always comes earlier, so only use this field if we don't
590
                                // have appropriate aperture information yet.
591
                                if ( ExifData::ApertureFNumber == 0 )
592
                                {
593
                                        ExifData::ApertureFNumber
594
                                        = ( float ) exp ( ConvertAnyFormat ( ValuePtr, Format ) *log ( 2.0 ) *0.5 );
595
                                }
596
                                break;
3685 fschmid 597
 
10911 fschmid 598
                        case TAG_FOCALLENGTH:
599
                                // Nice digital cameras actually save the focal length as a function
600
                                // of how far they are zoomed in.
601
                                ExifData::FocalLength = ( float ) ConvertAnyFormat ( ValuePtr, Format );
602
                                break;
3685 fschmid 603
 
10911 fschmid 604
                        case TAG_SUBJECT_DISTANCE:
605
                                // Inidcates the distacne the autofocus camera is focused to.
606
                                // Tends to be less accurate as distance increases.
607
                                ExifData::Distance = ( float ) ConvertAnyFormat ( ValuePtr, Format );
608
                                break;
3685 fschmid 609
 
10911 fschmid 610
                        case TAG_EXPOSURETIME:
611
                                // Simplest way of expressing exposure time, so I trust it most.
612
                                // (overwrite previously computd value if there is one)
613
                                ExifData::ExposureTime = ( float ) ConvertAnyFormat ( ValuePtr, Format );
614
                                break;
3685 fschmid 615
 
10911 fschmid 616
                        case TAG_SHUTTERSPEED:
617
                                // More complicated way of expressing exposure time, so only use
618
                                // this value if we don't already have it from somewhere else.
619
                                if ( ExifData::ExposureTime == 0 )
620
                                {
621
                                        ExifData::ExposureTime
622
                                        = ( float ) ( 1/exp ( ConvertAnyFormat ( ValuePtr, Format ) *log ( 2.0 ) ) );
623
                                }
624
                                break;
3685 fschmid 625
 
10911 fschmid 626
                        case TAG_FLASH:
627
                                ExifData::FlashUsed = ( int ) ConvertAnyFormat ( ValuePtr, Format );
628
                                break;
3685 fschmid 629
 
10911 fschmid 630
                        case TAG_EXIF_IMAGELENGTH:
631
                                ExifImageLength = ( int ) ConvertAnyFormat ( ValuePtr, Format );
632
                                break;
3685 fschmid 633
 
10911 fschmid 634
                        case TAG_EXIF_IMAGEWIDTH:
635
                                ExifImageWidth = ( int ) ConvertAnyFormat ( ValuePtr, Format );
636
                                break;
3685 fschmid 637
 
10911 fschmid 638
                        case TAG_FOCALPLANEXRES:
639
                                FocalplaneXRes = ConvertAnyFormat ( ValuePtr, Format );
640
                                break;
3685 fschmid 641
 
10911 fschmid 642
                        case TAG_FOCALPLANEUNITS:
643
                                switch ( ( int ) ConvertAnyFormat ( ValuePtr, Format ) )
644
                                {
645
                                        case 1: FocalplaneUnits = 25.4; break; // inch
646
                                        case 2:
647
                                                // According to the information I was using, 2 means meters.
648
                                                // But looking at the Cannon powershot's files, inches is the only
649
                                                // sensible value.
650
                                                FocalplaneUnits = 25.4;
651
                                                break;
3685 fschmid 652
 
10911 fschmid 653
                                        case 3: FocalplaneUnits = 10;   break;  // centimeter
654
                                        case 4: FocalplaneUnits = 1;    break;  // milimeter
655
                                        case 5: FocalplaneUnits = .001; break;  // micrometer
656
                                }
657
                                break;
3685 fschmid 658
 
10911 fschmid 659
                                // Remaining cases contributed by: Volker C. Schoech (schoech@gmx.de)
3685 fschmid 660
 
10911 fschmid 661
                        case TAG_EXPOSURE_BIAS:
662
                                ExifData::ExposureBias = ( float ) ConvertAnyFormat ( ValuePtr, Format );
663
                                break;
3685 fschmid 664
 
10911 fschmid 665
                        case TAG_WHITEBALANCE:
666
                                ExifData::Whitebalance = ( int ) ConvertAnyFormat ( ValuePtr, Format );
667
                                break;
3685 fschmid 668
 
10911 fschmid 669
                        case TAG_METERING_MODE:
670
                                ExifData::MeteringMode = ( int ) ConvertAnyFormat ( ValuePtr, Format );
671
                                break;
3685 fschmid 672
 
10911 fschmid 673
                        case TAG_EXPOSURE_PROGRAM:
674
                                ExifData::ExposureProgram = ( int ) ConvertAnyFormat ( ValuePtr, Format );
675
                                break;
3685 fschmid 676
 
10911 fschmid 677
                        case TAG_ISO_EQUIVALENT:
678
                                ExifData::ISOequivalent = ( int ) ConvertAnyFormat ( ValuePtr, Format );
679
                                if ( ExifData::ISOequivalent < 50 ) ExifData::ISOequivalent *= 200;
680
                                break;
3685 fschmid 681
 
10911 fschmid 682
                        case TAG_COMPRESSION_LEVEL:
683
                                ExifData::CompressionLevel = ( int ) ConvertAnyFormat ( ValuePtr, Format );
684
                                break;
3685 fschmid 685
 
10911 fschmid 686
                        case TAG_THUMBNAIL_OFFSET:
687
                                ThumbnailOffset = ( unsigned ) ConvertAnyFormat ( ValuePtr, Format );
688
                                break;
3685 fschmid 689
 
10911 fschmid 690
                        case TAG_THUMBNAIL_LENGTH:
691
                                ThumbnailSize = ( unsigned ) ConvertAnyFormat ( ValuePtr, Format );
692
                                break;
693
                }
3685 fschmid 694
 
10911 fschmid 695
                if ( Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET )
696
                {
697
                        unsigned char * SubdirStart;
698
                        SubdirStart = OffsetBase + Get32u ( ValuePtr );
12898 fschmid 699
                        if ( (SubdirStart < OffsetBase) || (SubdirStart > OffsetBase+ExifLength) )
10911 fschmid 700
                        {
701
                                return ;
3685 fschmid 702
//                throw FatalError("Illegal subdirectory link");
10911 fschmid 703
                        }
704
                        ProcessExifDir ( SubdirStart, OffsetBase, ExifLength );
705
                        recurseLevel--;
706
                        continue;
707
                }
708
        }
3685 fschmid 709
 
10911 fschmid 710
        {
711
                // In addition to linking to subdirectories via exif tags,
712
                // there's also a potential link to another directory at the end of each
713
                // directory.  this has got to be the result of a comitee!
714
                unsigned char * SubdirStart;
715
                unsigned Offset;
3685 fschmid 716
 
10911 fschmid 717
                if ( DIR_ENTRY_ADDR ( DirStart, NumDirEntries ) + 4 <= OffsetBase+ExifLength )
718
                {
719
                        Offset = Get32u ( DIR_ENTRY_ADDR ( DirStart, NumDirEntries ) );
720
                        // There is at least one jpeg from an HP camera having an Offset of almost MAXUINT.
721
                        // Adding OffsetBase to it produces an overflow, so compare with ExifLength here.
722
                        // See http://bugs.kde.org/show_bug.cgi?id=54542
723
                        if ( Offset && Offset < ExifLength )
724
                        {
725
                                SubdirStart = OffsetBase + Offset;
726
                                if ( SubdirStart > OffsetBase+ExifLength )
727
                                {
728
                                        if ( SubdirStart < OffsetBase+ExifLength+20 )
729
                                        {
730
                                                // Jhead 1.3 or earlier would crop the whole directory!
731
                                                // As Jhead produces this form of format incorrectness,
732
                                                // I'll just let it pass silently
11645 fschmid 733
//                                              qDebug ( "Thumbnail removed with Jhead 1.3 or earlier" );
10911 fschmid 734
                                        }
735
                                        else
736
                                        {
737
                                                return ;
738
//                       throw FatalError("Illegal subdirectory link 2");
739
                                        }
740
                                }
741
                                else
742
                                {
743
                                        if ( SubdirStart <= OffsetBase+ExifLength )
744
                                        {
745
                                                ProcessExifDir ( SubdirStart, OffsetBase, ExifLength );
746
                                                recurseLevel--;
747
                                        }
748
                                }
749
                        }
750
                }
751
                else
752
                {
753
                        // The exif header ends before the last next directory pointer.
754
                }
755
        }
3685 fschmid 756
 
10911 fschmid 757
        if ( ThumbnailSize && ThumbnailOffset )
758
        {
759
                if ( ThumbnailSize + ThumbnailOffset <= ExifLength )
760
                {
761
                        // The thumbnail pointer appears to be valid.  Store it.
762
                        Thumbnail.loadFromData ( OffsetBase + ThumbnailOffset, ThumbnailSize, "JPEG" );
763
                }
764
        }
3685 fschmid 765
}
766
 
767
//--------------------------------------------------------------------------
768
// Process a COM marker.  We want to leave the bytes unchanged.  The
769
// progam that displays this text may decide to remove blanks, convert
770
// newlines, or otherwise modify the text.  In particular we want to be
771
// safe for passing utf-8 text.
772
//--------------------------------------------------------------------------
10911 fschmid 773
void ExifData::process_COM ( const uchar * Data, int length )
3685 fschmid 774
{
10911 fschmid 775
        Comment = QString::fromUtf8 ( ( char * ) Data+2, ( length-2 ) );
3685 fschmid 776
}
777
 
778
 
779
//--------------------------------------------------------------------------
780
// Process a SOFn marker.  This is useful for the image dimensions
781
//--------------------------------------------------------------------------
10911 fschmid 782
void ExifData::process_SOFn ( const uchar * Data, int marker )
3685 fschmid 783
{
10911 fschmid 784
        int data_precision, num_components;
3685 fschmid 785
 
10911 fschmid 786
        data_precision = Data[2];
787
        ExifData::Height = Get16m ( Data+3 );
788
        ExifData::Width = Get16m ( Data+5 );
789
        num_components = Data[7];
3685 fschmid 790
 
10911 fschmid 791
        if ( num_components == 3 )
792
                ExifData::IsColor = 1;
793
        else
794
                ExifData::IsColor = 0;
3685 fschmid 795
 
10911 fschmid 796
        ExifData::Process = marker;
3685 fschmid 797
 
798
}
799
 
800
//--------------------------------------------------------------------------
801
// Get 16 bits motorola order (always) for jpeg header stuff.
802
//--------------------------------------------------------------------------
10911 fschmid 803
int ExifData::Get16m ( const void * Short )
3685 fschmid 804
{
10911 fschmid 805
        return ( ( ( uchar * ) Short ) [0] << 8 ) | ( ( uchar * ) Short ) [1];
3685 fschmid 806
}
807
 
808
 
809
//--------------------------------------------------------------------------
810
// Process a EXIF marker
811
// Describes all the drivel that most digital cameras include...
812
//--------------------------------------------------------------------------
10911 fschmid 813
void ExifData::process_EXIF ( unsigned char * CharBuf, unsigned int length )
3685 fschmid 814
{
10911 fschmid 815
        ExifData::FlashUsed = 0; // If it s from a digicam, and it used flash, it says so.
3685 fschmid 816
 
10911 fschmid 817
        FocalplaneXRes = 0;
818
        FocalplaneUnits = 0;
819
        ExifImageWidth = 0;
820
        ExifImageLength = 0;
3685 fschmid 821
 
12898 fschmid 822
// Check the EXIF header component
823
        static const uchar ExifHeader[] = "Exif\0\0";
824
        if ( memcmp ( CharBuf+2, ExifHeader,6 ) )
825
                return ;
3685 fschmid 826
 
10911 fschmid 827
        if ( memcmp ( CharBuf+8,"II",2 ) == 0 )
828
                MotorolaOrder = 0;
829
        else
830
        {
831
                if ( memcmp ( CharBuf+8,"MM",2 ) == 0 )
832
                        MotorolaOrder = 1;
833
                else
834
                        return ;
835
        }
3685 fschmid 836
 
10911 fschmid 837
        // Check the next two values for correctness.
10914 fschmid 838
        if ( Get16u ( CharBuf+10 ) != 0x2a || Get32u ( CharBuf+12 ) != 0x08 )
10911 fschmid 839
                return ;
10914 fschmid 840
        long IFDoffset = Get32u(CharBuf+12);
10911 fschmid 841
        LastExifRefd = CharBuf;
3685 fschmid 842
 
10911 fschmid 843
        // First directory starts 16 bytes in.  Offsets start at 8 bytes in.
10914 fschmid 844
        ProcessExifDir(&CharBuf[8+IFDoffset], CharBuf+8, length-6);
10911 fschmid 845
        recurseLevel--;
846
        // This is how far the interesting (non thumbnail) part of the exif went.
847
        ExifSettingsLength = LastExifRefd - CharBuf;
3685 fschmid 848
 
10911 fschmid 849
        // Compute the CCD width, in milimeters.
850
        if ( FocalplaneXRes != 0 )
851
        {
852
                ExifData::CCDWidth = ( float ) ( ExifImageWidth * FocalplaneUnits / FocalplaneXRes );
853
        }
3685 fschmid 854
}
855
 
856
//--------------------------------------------------------------------------
857
// Convert exif time to Unix time structure
858
//--------------------------------------------------------------------------
10911 fschmid 859
int ExifData::Exif2tm ( struct tm * timeptr, char * ExifTime )
3685 fschmid 860
{
10911 fschmid 861
        int a;
3685 fschmid 862
 
10911 fschmid 863
        timeptr->tm_wday = -1;
3685 fschmid 864
 
10911 fschmid 865
        // Check for format: YYYY:MM:DD HH:MM:SS format.
866
        a = sscanf ( ExifTime, "%d:%d:%d %d:%d:%d",
867
                     &timeptr->tm_year, &timeptr->tm_mon, &timeptr->tm_mday,
868
                     &timeptr->tm_hour, &timeptr->tm_min, &timeptr->tm_sec );
3685 fschmid 869
 
10911 fschmid 870
        if ( a == 6 )
871
        {
872
                timeptr->tm_isdst = -1;
873
                timeptr->tm_mon -= 1;      // Adjust for unix zero-based months
874
                timeptr->tm_year -= 1900;  // Adjust for year starting at 1900
875
                return true; // worked.
876
        }
3685 fschmid 877
 
10911 fschmid 878
        return false; // Wasn't in Exif date format.
3685 fschmid 879
}
880
 
881
//--------------------------------------------------------------------------
882
// Contructor for initialising
883
//--------------------------------------------------------------------------
884
ExifData::ExifData()
885
{
10911 fschmid 886
        ExifData::Whitebalance = -1;
887
        ExifData::MeteringMode = -1;
888
        ExifData::FlashUsed = 0;
889
        Orientation = 0;
890
        Height = 0;
891
        Width = 0;
892
        IsColor = 0;
893
        Process = 0;
894
        FocalLength = 0;
895
        ExposureTime = 0;
896
        ApertureFNumber = 0;
897
        Distance = 0;
898
        CCDWidth = 0;
899
        ExposureBias = 0;
900
        ExposureProgram = 0;
901
        ISOequivalent = 0;
902
        CompressionLevel = 0;
3898 fschmid 903
        exifDataValid = false;
10911 fschmid 904
        recurseLevel = 0;
16438 fschmid 905
        orientationCount = 0;
3685 fschmid 906
}
907
 
908
//--------------------------------------------------------------------------
909
// process a EXIF jpeg file
910
//--------------------------------------------------------------------------
10911 fschmid 911
bool ExifData::scan ( const QString & path )
3685 fschmid 912
{
10911 fschmid 913
        int ret;
3685 fschmid 914
 
10911 fschmid 915
        QFile f ( path );
916
        if ( !f.open ( QIODevice::ReadOnly ) )
917
                return false;
918
        ret = ReadJpegSections ( f, READ_EXIF );
919
        if ( ret == false )
920
        {
921
                f.close();
922
                return false;
923
        }
924
        f.close();
3685 fschmid 925
 
10911 fschmid 926
        //now make the strings clean,
927
        // for exmaple my Casio is a "QV-4000   "
10394 cbradney 928
        CameraMake = CameraMake.trimmed();
929
        CameraModel = CameraModel.trimmed();
930
        UserComment = UserComment.trimmed();
931
        Comment = Comment.trimmed();
10911 fschmid 932
        return true;
3685 fschmid 933
}
934
 
935
//--------------------------------------------------------------------------
936
// Does the embedded thumbnail match the jpeg image?
937
//--------------------------------------------------------------------------
938
#ifndef JPEG_TOL
939
#define JPEG_TOL 0.02
940
#endif
10911 fschmid 941
bool ExifData::isThumbnailSane()
942
{
943
        bool ret = true;
944
        if ( Thumbnail.isNull() )
945
                ret = false;
3685 fschmid 946
 
10911 fschmid 947
        // check whether thumbnail dimensions match the image
948
        // not foolproof, but catches some altered images (jpegtran -rotate)
949
        if ( ExifImageLength != 0 && ExifImageLength != Height )
950
                ret = false;
951
        if ( ExifImageWidth != 0 && ExifImageWidth != Width )
952
                ret = false;
953
        if ( Thumbnail.width() == 0 || Thumbnail.height() == 0 )
954
                ret = false;
955
        if ( Height == 0 || Width == 0 )
956
                ret = false;
957
        double d = ( double ) Height/Width*Thumbnail.width() /Thumbnail.height();
958
        if (!(( 1-JPEG_TOL < d ) && ( d < 1+JPEG_TOL )))
959
                ret = false;
960
        exifDataValid = ret;
961
        return ret;
3685 fschmid 962
}
963
 
964
 
965
//--------------------------------------------------------------------------
966
// return a thumbnail that respects the orientation flag
967
// only if it seems sane
968
//--------------------------------------------------------------------------
10911 fschmid 969
QImage ExifData::getThumbnail()
970
{
16438 fschmid 971
        if ( Thumbnail.isNull() )
972
                return QImage(); // Qt4 NULL->QImage() is it sane?
973
        if (orientationCount > 1)
974
                return Thumbnail;
975
        if ( !Orientation || Orientation == 1 )
976
                return Thumbnail;
10911 fschmid 977
        // now fix orientation
13951 fschmid 978
        QTransform M;
979
        QTransform flip = QTransform ( -1,0,0,1,0,0 );
10911 fschmid 980
        switch ( Orientation )
981
        {  // notice intentional fallthroughs
982
                case 2: M = flip; break;
983
                case 4: M = flip;
984
                case 3: M.rotate ( 180 ); break;
985
                case 5: M = flip;
986
                case 6: M.rotate ( 90 ); break;
987
                case 7: M = flip;
988
                case 8: M.rotate ( 270 ); break;
989
                default: break; // should never happen
990
        }
991
        return Thumbnail.transformed ( M );
3685 fschmid 992
}