3
gaia_exif.c -- Gaia EXIF support
5
version 3.0, 2011 July 20
7
Author: Sandro Furieri a.furieri@lqt.it
9
------------------------------------------------------------------------------
11
Version: MPL 1.1/GPL 2.0/LGPL 2.1
13
The contents of this file are subject to the Mozilla Public License Version
14
1.1 (the "License"); you may not use this file except in compliance with
15
the License. You may obtain a copy of the License at
16
http://www.mozilla.org/MPL/
18
Software distributed under the License is distributed on an "AS IS" basis,
19
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20
for the specific language governing rights and limitations under the
23
The Original Code is the SpatiaLite library
25
The Initial Developer of the Original Code is Alessandro Furieri
27
Portions created by the Initial Developer are Copyright (C) 2008
28
the Initial Developer. All Rights Reserved.
32
Alternatively, the contents of this file may be used under the terms of
33
either the GNU General Public License Version 2 or later (the "GPL"), or
34
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
35
in which case the provisions of the GPL or the LGPL are applicable instead
36
of those above. If you wish to allow use of your version of this file only
37
under the terms of either the GPL or the LGPL, and not to allow others to
38
use your version of this file under the terms of the MPL, indicate your
39
decision by deleting the provisions above and replace them with the notice
40
and other provisions required by the GPL or the LGPL. If you do not delete
41
the provisions above, a recipient may use your version of this file under
42
the terms of any one of the MPL, the GPL or the LGPL.
46
#include <sys/types.h>
54
#ifdef SPL_AMALGAMATION /* spatialite-amalgamation */
55
#include <spatialite/sqlite3ext.h>
57
#include <sqlite3ext.h>
60
#include <spatialite/gaiageo.h>
61
#include <spatialite/gaiaexif.h>
62
#include <spatialite.h>
65
#define strcasecmp _stricmp
66
#endif /* not WIN32 */
69
exifTagName (char gps, unsigned short tag_id, char *str, int len)
71
/* returns the canonical name corresponding to an EXIF TAG ID */
73
char *name = "UNKNOWN";
79
name = "GPSVersionID";
82
name = "GPSLatitudeRef";
88
name = "GPSLongitudeRef";
91
name = "GPSLongitude";
94
name = "GPSAltitudeRef";
100
name = "GPSTimeStamp";
103
name = "GPSSatellites";
109
name = "GPSMeasureMode";
115
name = "GPSSpeedRef";
121
name = "GPSTrackRef";
127
name = "GPSImgDirectionRef";
130
name = "GPSImgDirection";
133
name = "GPSMapDatum";
136
name = "GPSDestLatitudeRef";
139
name = "GPSDestLatitude";
142
name = "GPSDestLongitudeRef";
145
name = "GPSDestLongitude";
148
name = "GPSDestBearingRef";
151
name = "GPSDestBearing";
154
name = "GPSDestDistanceRef";
157
name = "GPSDestDistance";
160
name = "GPSProcessingMethod";
163
name = "GPSAreaInformation";
166
name = "GPSDateStamp";
169
name = "GPSDifferential";
190
name = "ImageLength";
193
name = "BitsPerSample";
196
name = "Compression";
199
name = "PhotometricInterpretation";
205
name = "DocumentName";
208
name = "ImageDescription";
217
name = "StripOffsets";
220
name = "Orientation";
223
name = "SamplesPerPixel";
226
name = "RowsPerStrip";
229
name = "StripByteCounts";
232
name = "MinSampleValue";
235
name = "MaxSampleValue";
238
name = "XResolution";
241
name = "YResolution";
244
name = "PlanarConfiguration";
256
name = "FreeOffsets";
259
name = "FreeByteCounts";
262
name = "GrayResponseUnit";
265
name = "GrayResponseCurve";
274
name = "ResolutionUnit";
280
name = "TransferFunction";
292
name = "HostComputer";
301
name = "PrimaryChromaticities";
307
name = "HalfToneHints";
316
name = "TileOffsets";
319
name = "TileByteCounts";
331
name = "NumberOfInks";
337
name = "TargetPrinter";
340
name = "ExtraSample";
343
name = "SampleFormat";
346
name = "SMinSampleValue";
349
name = "SMaxSampleValue";
352
name = "TransferRange";
358
name = "XClipPathUnits";
361
name = "YClipPathUnits";
376
name = "JPEGInterchangeFormat";
379
name = "JPEGInterchangeFormatLength";
382
name = "JPEGRestartInterval";
385
name = "JPEGLosslessPredictors";
388
name = "JPEGPointTransforms";
391
name = "JPEGQTables";
394
name = "JPEGDCTables";
397
name = "JPEGACTables";
400
name = "YCbCrCoefficients";
403
name = "YCbCrSubSampling";
406
name = "YCbCrPositioning";
409
name = "ReferenceBlackWhite";
412
name = "ExtensibleMetadataPlatform";
418
name = "ICCProfileDescriptor";
421
name = "SRGBRenderingIntent";
427
name = "ResolutionXUnit";
430
name = "ResolutionYUnit";
433
name = "ResolutionXLengthUnit";
436
name = "ResolutionYLengthUnit";
442
name = "PrintFlagsVersion";
445
name = "PrintFlagsCrop";
448
name = "PrintFlagsBleedWidth";
451
name = "PrintFlagsBleedWidthScale";
454
name = "HalftoneLPI";
457
name = "HalftoneLPIUnit";
460
name = "HalftoneDegree";
463
name = "HalftoneShape";
466
name = "HalftoneMisc";
469
name = "HalftoneScreen";
472
name = "JPEGQuality";
478
name = "ThumbnailFormat";
481
name = "ThumbnailWidth";
484
name = "ThumbnailHeight";
487
name = "ThumbnailColorDepth";
490
name = "ThumbnailPlanes";
493
name = "ThumbnailRawBytes";
496
name = "ThumbnailSize";
499
name = "ThumbnailCompressedSize";
502
name = "ColorTransferFunction";
505
name = "ThumbnailData";
508
name = "ThumbnailImageWidth";
511
name = "ThumbnailImageHeight";
514
name = "ThumbnailBitsPerSample";
517
name = "ThumbnailCompression";
520
name = "ThumbnailPhotometricInterp";
523
name = "ThumbnailImageDescription";
526
name = "ThumbnailEquipMake";
529
name = "ThumbnailEquipModel";
532
name = "ThumbnailStripOffsets";
535
name = "ThumbnailOrientation";
538
name = "ThumbnailSamplesPerPixel";
541
name = "ThumbnailRowsPerStrip";
544
name = "ThumbnailStripBytesCount";
547
name = "ThumbnailResolutionX";
550
name = "ThumbnailResolutionY";
553
name = "ThumbnailPlanarConfig";
556
name = "ThumbnailResolutionUnit";
559
name = "ThumbnailTransferFunction";
562
name = "ThumbnailSoftwareUsed";
565
name = "ThumbnailDateTime";
568
name = "ThumbnailArtist";
571
name = "ThumbnailWhitePoint";
574
name = "ThumbnailPrimaryChromaticities";
577
name = "ThumbnailYCbCrCoefficients";
580
name = "ThumbnailYCbCrSubsampling";
583
name = "ThumbnailYCbCrPositioning";
586
name = "ThumbnailRefBlackWhite";
589
name = "ThumbnailCopyRight";
592
name = "LuminanceTable";
595
name = "ChrominanceTable";
607
name = "PixelPerUnitX";
610
name = "PixelPerUnitY";
613
name = "PaletteHistogram";
616
name = "RelatedImageFileFormat";
634
name = "CFARepeatPatternDim";
640
name = "BatteryLevel";
646
name = "ExposureTime";
655
name = "IT8RasterPadding";
658
name = "IT8ColorTable";
661
name = "ImageResourceInformation";
664
name = "Exif IFD Pointer";
667
name = "ICC_Profile";
670
name = "ExposureProgram";
673
name = "SpectralSensitivity";
676
name = "GPSInfo IFD Pointer";
679
name = "ISOSpeedRatings";
685
name = "ExifVersion";
688
name = "DateTimeOriginal";
691
name = "DateTimeDigitized";
694
name = "ComponentsConfiguration";
697
name = "CompressedBitsPerPixel";
700
name = "ShutterSpeedValue";
703
name = "ApertureValue";
706
name = "BrightnessValue";
709
name = "ExposureBiasValue";
712
name = "MaxApertureValue";
715
name = "SubjectDistance";
718
name = "MeteringMode";
721
name = "LightSource";
727
name = "FocalLength";
731
name = "FlashEnergy";
735
name = "SpatialFrequencyResponse";
742
name = "FocalPlaneXResolution";
746
name = "FocalPlaneYResolution";
750
name = "FocalPlaneResolutionUnit";
753
name = "ImageNumber";
756
name = "SecurityClassification";
759
name = "ImageHistory";
763
name = "SubjectLocation";
767
name = "ExposureIndex";
770
name = "TIFF/EPStandardID";
774
name = "SensingMethod";
783
name = "UserComment";
789
name = "SubSecTimeOriginal";
792
name = "SubSecTimeDigitized";
795
name = "FlashpixVersion";
801
name = "ExifImageWidth";
804
name = "ExifImageLength";
807
name = "RelatedSoundFile";
810
name = "Interoperability IFD Pointer";
816
name = "ImageNumber";
819
name = "SecurityClassification";
822
name = "ImageHistory";
825
name = "TIFF/EPStandardID";
837
name = "CustomRendered";
840
name = "ExposureMode";
843
name = "WhiteBalance";
846
name = "DigitalZoomRatio";
849
name = "FocalLengthIn35mmFilm";
852
name = "SceneCaptureType";
855
name = "GainControl";
867
name = "DeviceSettingDescription";
870
name = "SubjectDistanceRange";
873
name = "ImageUniqueID";
882
memset (str, '\0', len);
883
memcpy (str, name, len - 1);
887
static unsigned short
888
exifImportU16 (const unsigned char *p, int little_endian,
889
int little_endian_arch)
891
/* fetches an unsigned 16bit int from BLOB respecting declared endiannes */
894
unsigned char byte[2];
895
unsigned short short_value;
897
if (little_endian_arch)
899
/* Litte-Endian architecture [e.g. x86] */
902
/* Big Endian data */
903
convert.byte[0] = *(p + 1);
904
convert.byte[1] = *(p + 0);
908
/* Little Endian data */
909
convert.byte[0] = *(p + 0);
910
convert.byte[1] = *(p + 1);
915
/* Big Endian architecture [e.g. PPC] */
918
/* Big Endian data */
919
convert.byte[0] = *(p + 0);
920
convert.byte[1] = *(p + 1);
924
/* Little Endian data */
925
convert.byte[0] = *(p + 1);
926
convert.byte[1] = *(p + 0);
929
return convert.short_value;
933
exifImportU32 (const unsigned char *p, int little_endian,
934
int little_endian_arch)
936
/* fetches an unsigned 32bit int from BLOB respecting declared endiannes */
939
unsigned char byte[4];
940
unsigned int int_value;
942
if (little_endian_arch)
944
/* Litte-Endian architecture [e.g. x86] */
947
/* Big Endian data */
948
convert.byte[0] = *(p + 3);
949
convert.byte[1] = *(p + 2);
950
convert.byte[2] = *(p + 1);
951
convert.byte[3] = *(p + 0);
955
/* Little Endian data */
956
convert.byte[0] = *(p + 0);
957
convert.byte[1] = *(p + 1);
958
convert.byte[2] = *(p + 2);
959
convert.byte[3] = *(p + 3);
964
/* Big Endian architecture [e.g. PPC] */
967
/* Big Endian data */
968
convert.byte[0] = *(p + 0);
969
convert.byte[1] = *(p + 1);
970
convert.byte[2] = *(p + 2);
971
convert.byte[3] = *(p + 3);
975
/* Little Endian data */
976
convert.byte[0] = *(p + 3);
977
convert.byte[1] = *(p + 2);
978
convert.byte[2] = *(p + 1);
979
convert.byte[3] = *(p + 0);
982
return convert.int_value;
986
exifImportFloat32 (const unsigned char *p, int little_endian,
987
int little_endian_arch)
989
/* fetches a 32bit FLOAT from BLOB respecting declared endiannes */
992
unsigned char byte[4];
995
if (little_endian_arch)
997
/* Litte-Endian architecture [e.g. x86] */
1000
/* Big Endian data */
1001
convert.byte[0] = *(p + 3);
1002
convert.byte[1] = *(p + 2);
1003
convert.byte[2] = *(p + 1);
1004
convert.byte[3] = *(p + 0);
1008
/* Little Endian data */
1009
convert.byte[0] = *(p + 0);
1010
convert.byte[1] = *(p + 1);
1011
convert.byte[2] = *(p + 2);
1012
convert.byte[3] = *(p + 3);
1017
/* Big Endian architecture [e.g. PPC] */
1020
/* Big Endian data */
1021
convert.byte[0] = *(p + 0);
1022
convert.byte[1] = *(p + 1);
1023
convert.byte[2] = *(p + 2);
1024
convert.byte[3] = *(p + 3);
1028
/* Little Endian data */
1029
convert.byte[0] = *(p + 3);
1030
convert.byte[1] = *(p + 2);
1031
convert.byte[2] = *(p + 1);
1032
convert.byte[3] = *(p + 0);
1035
return convert.float_value;
1039
exifSetTagValue (gaiaExifTagPtr tag, const unsigned char *blob, int endian_mode,
1040
int endian_arch, int app1_offset)
1042
/* setting the TAG value */
1045
unsigned int offset;
1046
const unsigned char *ptr;
1047
unsigned short short_value;
1048
unsigned int int_value;
1049
short sign_short_value;
1052
double double_value;
1053
if (tag->Type == 1 || tag->Type == 2 || tag->Type == 6 || tag->Type == 7)
1055
if (tag->Type == 3 || tag->Type == 8)
1056
sz = tag->Count * 2;
1057
if (tag->Type == 4 || tag->Type == 9 || tag->Type == 11)
1058
sz = tag->Count * 4;
1059
if (tag->Type == 5 || tag->Type == 10 || tag->Type == 12)
1060
sz = tag->Count * 8;
1063
/* TAG values is stored within the offset */
1064
ptr = tag->TagOffset;
1068
/* jumping to offset */
1069
offset = exifImportU32 (tag->TagOffset, endian_mode, endian_arch);
1070
offset += app1_offset + 10;
1071
ptr = blob + offset;
1073
if (tag->Type == 1 || tag->Type == 6 || tag->Type == 7)
1076
tag->ByteValue = malloc (tag->Count);
1077
memcpy (tag->ByteValue, ptr, tag->Count);
1082
tag->StringValue = malloc (tag->Count);
1083
memcpy (tag->StringValue, ptr, tag->Count);
1088
tag->ShortValues = malloc (tag->Count * sizeof (unsigned short));
1089
for (i = 0; i < tag->Count; i++)
1092
exifImportU16 (ptr + (i * 2), endian_mode, endian_arch);
1093
*(tag->ShortValues + i) = short_value;
1099
tag->LongValues = malloc (tag->Count * sizeof (unsigned int));
1100
for (i = 0; i < tag->Count; i++)
1103
exifImportU32 (ptr + (i * 4), endian_mode, endian_arch);
1104
*(tag->LongValues + i) = int_value;
1110
tag->LongRationals1 = malloc (tag->Count * sizeof (unsigned int));
1111
tag->LongRationals2 = malloc (tag->Count * sizeof (unsigned int));
1112
for (i = 0; i < tag->Count; i++)
1115
exifImportU32 (ptr + (i * 8), endian_mode, endian_arch);
1116
*(tag->LongRationals1 + i) = int_value;
1118
exifImportU32 (ptr + (i * 8) + 4, endian_mode, endian_arch);
1119
*(tag->LongRationals2 + i) = int_value;
1125
tag->SignedShortValues = malloc (tag->Count * sizeof (short));
1126
for (i = 0; i < tag->Count; i++)
1129
gaiaImport16 (ptr + (i * 2), endian_mode, endian_arch);
1130
*(tag->SignedShortValues + i) = sign_short_value;
1135
/* SIGNED LONG type */
1136
tag->SignedLongValues = malloc (tag->Count * sizeof (int));
1137
for (i = 0; i < tag->Count; i++)
1140
gaiaImport32 (ptr + (i * 4), endian_mode, endian_arch);
1141
*(tag->SignedLongValues + i) = sign_int_value;
1144
if (tag->Type == 10)
1146
/* SIGNED RATIONAL type */
1147
tag->SignedLongRationals1 = malloc (tag->Count * sizeof (int));
1148
tag->SignedLongRationals2 = malloc (tag->Count * sizeof (int));
1149
for (i = 0; i < tag->Count; i++)
1152
gaiaImport32 (ptr + (i * 8), endian_mode, endian_arch);
1153
*(tag->SignedLongRationals1 + i) = sign_int_value;
1155
gaiaImport32 (ptr + (i * 8) + 4, endian_mode, endian_arch);
1156
*(tag->SignedLongRationals2 + i) = sign_int_value;
1159
if (tag->Type == 11)
1162
tag->FloatValues = malloc (tag->Count * sizeof (float));
1163
for (i = 0; i < tag->Count; i++)
1166
exifImportFloat32 (ptr + (i * 4), endian_mode, endian_arch);
1167
*(tag->FloatValues + i) = float_value;
1170
if (tag->Type == 12)
1173
tag->DoubleValues = malloc (tag->Count * sizeof (double));
1174
for (i = 0; i < tag->Count; i++)
1177
gaiaImport64 (ptr + (i * 8), endian_mode, endian_arch);
1178
*(tag->DoubleValues + i) = double_value;
1184
exifParseTag (const unsigned char *blob, unsigned int offset, int endian_mode,
1185
int endian_arch, gaiaExifTagListPtr list, int gps,
1188
/* parsing some TAG and inserting into the list */
1189
unsigned short tag_id;
1190
unsigned short type;
1193
tag_id = exifImportU16 (blob + offset, endian_mode, endian_arch);
1194
type = exifImportU16 (blob + offset + 2, endian_mode, endian_arch);
1195
count = exifImportU32 (blob + offset + 4, endian_mode, endian_arch);
1196
tag = malloc (sizeof (gaiaExifTag));
1197
tag->Gps = (char) gps;
1198
tag->TagId = tag_id;
1200
tag->Count = (unsigned short) count;
1201
memcpy (tag->TagOffset, blob + offset + 8, 4);
1202
tag->ByteValue = NULL;
1203
tag->StringValue = NULL;
1204
tag->ShortValues = NULL;
1205
tag->LongValues = NULL;
1206
tag->LongRationals1 = NULL;
1207
tag->LongRationals2 = NULL;
1208
tag->SignedShortValues = NULL;
1209
tag->SignedLongValues = NULL;
1210
tag->SignedLongRationals1 = NULL;
1211
tag->SignedLongRationals2 = NULL;
1212
tag->FloatValues = NULL;
1213
tag->DoubleValues = NULL;
1214
exifSetTagValue (tag, blob, endian_mode, endian_arch, app1_offset);
1219
(list->Last)->Next = tag;
1225
exifExpandIFD (gaiaExifTagListPtr list, const unsigned char *blob,
1226
int endian_mode, int endian_arch, int app1_offset)
1228
/* trying to expand the EXIF-IFD */
1229
unsigned int offset;
1230
unsigned short items;
1238
if (tag->TagId == 34665)
1240
/* ok, this one is an IFD pointer */
1242
exifImportU32 (tag->TagOffset, endian_mode, endian_arch);
1243
offset += app1_offset + 10;
1244
items = exifImportU16 (blob + offset, endian_mode, endian_arch);
1246
for (i = 0; i < items; i++)
1248
/* fetching the TAGs */
1249
exifParseTag (blob, offset, endian_mode, endian_arch,
1250
list, 0, app1_offset);
1259
exifExpandGPS (gaiaExifTagListPtr list, const unsigned char *blob,
1260
int endian_mode, int endian_arch, int app1_offset)
1262
/* trying to expand the EXIF-GPS */
1263
unsigned int offset;
1264
unsigned short items;
1272
if (tag->TagId == 34853)
1274
/* ok, this one is a GPSinfo-IFD pointer */
1276
exifImportU32 (tag->TagOffset, endian_mode, endian_arch);
1277
offset += app1_offset + 10;
1278
items = exifImportU16 (blob + offset, endian_mode, endian_arch);
1280
for (i = 0; i < items; i++)
1282
/* fetching the TAGs */
1283
exifParseTag (blob, offset, endian_mode, endian_arch,
1284
list, 1, app1_offset);
1292
GAIAEXIF_DECLARE gaiaExifTagListPtr
1293
gaiaGetExifTags (const unsigned char *blob, int size)
1295
/* trying to parse a BLOB as an EXIF photo */
1296
gaiaExifTagListPtr list;
1297
int endian_arch = gaiaEndianArch ();
1299
unsigned short app1_size;
1300
unsigned int offset;
1301
unsigned short items;
1305
int app1_marker = 0;
1311
/* cecking for SOI [Start Of Image] */
1312
if (*(blob + 0) == 0xff && *(blob + 1) == 0xd8)
1317
for (x = 2; x < size; x++)
1319
/* retrieving the APP1 Marker */
1320
if (*(blob + x) == 0xff)
1322
if (*(blob + x) == 0xe1)
1326
app1_offset = x - 1;
1333
/* checking for APP1 Marker */
1334
if (*(blob + app1_offset) == 0xff && *(blob + app1_offset + 1) == 0xe1)
1338
/* checking for EXIF identifier */
1339
if (memcmp (blob + app1_offset + 4, "Exif", 4) == 0)
1343
/* checking for Pad */
1344
if (*(blob + app1_offset + 8) == 0x00 && *(blob + app1_offset + 9) == 0x00)
1348
if (memcmp (blob + app1_offset + 10, "II", 2) == 0)
1349
endian_mode = GAIA_LITTLE_ENDIAN;
1350
else if (memcmp (blob + app1_offset + 10, "MM", 2) == 0)
1351
endian_mode = GAIA_BIG_ENDIAN;
1354
/* OK: this BLOB seems to contain a valid EXIF */
1356
exifImportU16 (blob + app1_offset + 2, endian_mode, endian_arch);
1357
if ((app1_size + app1_offset + 4) > size)
1359
/* checking for marker */
1360
if (endian_mode == GAIA_BIG_ENDIAN)
1362
if (*(blob + app1_offset + 12) == 0x00
1363
&& *(blob + app1_offset + 13) == 0x2a)
1370
if (*(blob + app1_offset + 12) == 0x2a
1371
&& *(blob + app1_offset + 13) == 0x00)
1376
/* allocating an EXIF TAG LIST */
1377
list = malloc (sizeof (gaiaExifTagList));
1381
list->TagsArray = NULL;
1382
offset = exifImportU32 (blob + app1_offset + 14, endian_mode, endian_arch);
1383
offset += app1_offset + 10;
1384
/* jump to offset */
1385
items = exifImportU16 (blob + offset, endian_mode, endian_arch);
1387
for (i = 0; i < items; i++)
1389
/* fetching the EXIF TAGs */
1390
exifParseTag (blob, offset, endian_mode, endian_arch, list, 0,
1394
/* expanding the IFD and GPS tags */
1395
exifExpandIFD (list, blob, endian_mode, endian_arch, app1_offset);
1396
exifExpandGPS (list, blob, endian_mode, endian_arch, app1_offset);
1399
/* organizing the EXIF TAGS as an Array */
1400
list->TagsArray = malloc (sizeof (gaiaExifTagPtr) * list->NumTags);
1405
*(list->TagsArray + i++) = pT;
1414
GAIAEXIF_DECLARE void
1415
gaiaExifTagsFree (gaiaExifTagListPtr p)
1417
/* memory cleanup; freeing the EXIF TAG list */
1427
free (pT->ByteValue);
1428
if (pT->StringValue)
1429
free (pT->StringValue);
1430
if (pT->ShortValues)
1431
free (pT->ShortValues);
1433
free (pT->LongValues);
1434
if (pT->LongRationals1)
1435
free (pT->LongRationals1);
1436
if (pT->LongRationals2)
1437
free (pT->LongRationals2);
1438
if (pT->SignedShortValues)
1439
free (pT->SignedShortValues);
1440
if (pT->SignedLongValues)
1441
free (pT->SignedLongValues);
1442
if (pT->SignedLongRationals1)
1443
free (pT->SignedLongRationals1);
1444
if (pT->SignedLongRationals2)
1445
free (pT->SignedLongRationals2);
1446
if (pT->FloatValues)
1447
free (pT->FloatValues);
1448
if (pT->DoubleValues)
1449
free (pT->DoubleValues);
1454
free (p->TagsArray);
1458
GAIAEXIF_DECLARE int
1459
gaiaGetExifTagsCount (gaiaExifTagListPtr tag_list)
1461
/* returns the # TAGSs into this list */
1462
return tag_list->NumTags;
1465
GAIAEXIF_DECLARE gaiaExifTagPtr
1466
gaiaGetExifTagByPos (gaiaExifTagListPtr tag_list, const int pos)
1468
/* returns the Nth TAG from this list */
1469
if (pos >= 0 && pos < tag_list->NumTags)
1470
return *(tag_list->TagsArray + pos);
1474
GAIAEXIF_DECLARE gaiaExifTagPtr
1475
gaiaGetExifTagById (const gaiaExifTagListPtr tag_list,
1476
const unsigned short tag_id)
1478
/* returns a not-GPS TAG identified by its ID */
1479
gaiaExifTagPtr pT = tag_list->First;
1482
if (!(pT->Gps) && pT->TagId == tag_id)
1489
GAIAEXIF_DECLARE gaiaExifTagPtr
1490
gaiaGetExifGpsTagById (const gaiaExifTagListPtr tag_list,
1491
const unsigned short tag_id)
1493
/* returns a GPS TAG identified by its ID */
1494
gaiaExifTagPtr pT = tag_list->First;
1497
if (pT->Gps && pT->TagId == tag_id)
1504
GAIAEXIF_DECLARE gaiaExifTagPtr
1505
gaiaGetExifTagByName (const gaiaExifTagListPtr tag_list, const char *tag_name)
1507
/* returns a TAG identified by its Name */
1509
gaiaExifTagPtr pT = tag_list->First;
1512
exifTagName (pT->Gps, pT->TagId, name, 128);
1513
if (strcasecmp (name, tag_name) == 0)
1520
GAIAEXIF_DECLARE unsigned short
1521
gaiaExifTagGetId (const gaiaExifTagPtr tag)
1523
/* returns the TAG ID */
1527
GAIAEXIF_DECLARE int
1528
gaiaIsExifGpsTag (const gaiaExifTagPtr tag)
1530
/* checks if this one is a GPS tag */
1534
GAIAEXIF_DECLARE void
1535
gaiaExifTagGetName (const gaiaExifTagPtr tag, char *str, int len)
1537
/* returns the TAG symbolic Name */
1538
exifTagName (tag->Gps, tag->TagId, str, len);
1541
GAIAEXIF_DECLARE unsigned short
1542
gaiaExifTagGetValueType (const gaiaExifTagPtr tag)
1544
/* returns the TAG value Type */
1548
GAIAEXIF_DECLARE unsigned short
1549
gaiaExifTagGetNumValues (const gaiaExifTagPtr tag)
1551
/* returns the # TAG Values */
1555
GAIAEXIF_DECLARE unsigned char
1556
gaiaExifTagGetByteValue (const gaiaExifTagPtr tag, const int ind, int *ok)
1558
/* returns the Nth Byte value */
1561
tag->Count && (tag->Type == 1 || tag->Type == 6 || tag->Type == 7))
1564
return *(tag->ByteValue + ind);
1570
GAIAEXIF_DECLARE void
1571
gaiaExifTagGetStringValue (const gaiaExifTagPtr tag, char *str, int len,
1574
/* returns the String value */
1579
l = strlen (tag->StringValue);
1581
strcpy (str, tag->StringValue);
1584
memset (str, '\0', len);
1585
memcpy (str, tag->StringValue, len - 1);
1592
GAIAEXIF_DECLARE unsigned short
1593
gaiaExifTagGetShortValue (const gaiaExifTagPtr tag, const int ind, int *ok)
1595
/* returns the Nth Short value */
1596
if (ind >= 0 && ind < tag->Count && tag->Type == 3)
1599
return *(tag->ShortValues + ind);
1605
GAIAEXIF_DECLARE unsigned int
1606
gaiaExifTagGetLongValue (const gaiaExifTagPtr tag, const int ind, int *ok)
1608
/* returns the Nth Long value */
1609
if (ind >= 0 && ind < tag->Count && tag->Type == 4)
1612
return *(tag->LongValues + ind);
1618
GAIAEXIF_DECLARE unsigned int
1619
gaiaExifTagGetRational1Value (const gaiaExifTagPtr tag, const int ind, int *ok)
1621
/* returns the Nth Rational (1) value */
1622
if (ind >= 0 && ind < tag->Count && tag->Type == 5)
1625
return *(tag->LongRationals1 + ind);
1631
GAIAEXIF_DECLARE unsigned int
1632
gaiaExifTagGetRational2Value (const gaiaExifTagPtr tag, const int ind, int *ok)
1634
/* returns the Nth Rational (2) value */
1635
if (ind >= 0 && ind < tag->Count && tag->Type == 5)
1638
return *(tag->LongRationals2 + ind);
1644
GAIAEXIF_DECLARE double
1645
gaiaExifTagGetRationalValue (const gaiaExifTagPtr tag, const int ind, int *ok)
1647
/* returns the Nth Rational value as Double */
1650
&& ind < tag->Count && tag->Type == 5 && *(tag->LongRationals2 + ind))
1653
x = (double) (*(tag->LongRationals1 + ind)) /
1654
(double) (*(tag->LongRationals2 + ind));
1661
GAIAEXIF_DECLARE short
1662
gaiaExifTagGetSignedShortValue (const gaiaExifTagPtr tag, const int ind,
1665
/* returns the Nth Signed Short value */
1666
if (ind >= 0 && ind < tag->Count && tag->Type == 8)
1669
return *(tag->SignedShortValues + ind);
1675
GAIAEXIF_DECLARE int
1676
gaiaExifTagGetSignedLongValue (const gaiaExifTagPtr tag, const int ind, int *ok)
1678
/* returns the Nth Signed Long value */
1679
if (ind >= 0 && ind < tag->Count && tag->Type == 9)
1682
return *(tag->SignedLongValues + ind);
1688
GAIAEXIF_DECLARE int
1689
gaiaExifTagGetSignedRational1Value (const gaiaExifTagPtr tag, const int ind,
1692
/* returns the Nth Signed Rational (1) value */
1693
if (ind >= 0 && ind < tag->Count && tag->Type == 10)
1696
return *(tag->SignedLongRationals1 + ind);
1702
GAIAEXIF_DECLARE int
1703
gaiaExifTagGetSignedRational2Value (const gaiaExifTagPtr tag, const int ind,
1706
/* returns the Nth Signed Rational (2) value */
1707
if (ind >= 0 && ind < tag->Count && tag->Type == 10)
1710
return *(tag->SignedLongRationals2 + ind);
1716
GAIAEXIF_DECLARE double
1717
gaiaExifTagGetSignedRationalValue (const gaiaExifTagPtr tag, const int ind,
1720
/* returns the Nth Signed Rational value as Double */
1724
tag->Count && tag->Type == 10 && *(tag->SignedLongRationals2 + ind))
1727
x = (double) (*(tag->SignedLongRationals1 + ind)) /
1728
(double) (*(tag->SignedLongRationals2 + ind));
1735
GAIAEXIF_DECLARE float
1736
gaiaExifTagGetFloatValue (const gaiaExifTagPtr tag, const int ind, int *ok)
1738
/* returns the Nth Float value */
1739
if (ind >= 0 && ind < tag->Count && tag->Type == 11)
1742
return *(tag->FloatValues + ind);
1748
GAIAEXIF_DECLARE double
1749
gaiaExifTagGetDoubleValue (const gaiaExifTagPtr tag, const int ind, int *ok)
1751
/* returns the Nth Double value */
1752
if (ind >= 0 && ind < tag->Count && tag->Type == 12)
1755
return *(tag->DoubleValues + ind);
1761
GAIAEXIF_DECLARE void
1762
gaiaExifTagGetHumanReadable (const gaiaExifTagPtr tag, char *str, int len,
1765
/* returns the Human Readable value */
1773
case 0x0128: /* ResolutionUnit */
1774
if (tag->Type == 3 && tag->Count == 1)
1776
switch (*(tag->ShortValues + 0))
1782
human = "Centimeters";
1787
case 0x8822: /* ExposureProgram */
1788
if (tag->Type == 3 && tag->Count == 1)
1790
switch (*(tag->ShortValues + 0))
1793
human = "Not defined";
1799
human = "Normal program";
1802
human = "Aperture priority";
1805
human = "Shutter priority";
1808
human = "Creative program (biased toward depth of field)";
1812
"Action program (biased toward fast shutter speed)";
1816
"Portrait mode (for closeup photos with the background out of focus)";
1820
"Landscape mode (for landscape photos with the background in focus)";
1825
case 0xA402: /* ExposureMode */
1826
if (tag->Type == 3 && tag->Count == 1)
1828
switch (*(tag->ShortValues + 0))
1831
human = "Auto exposure";
1834
human = "Manual exposure";
1837
human = "Auto bracket";
1842
case 0x0112: /* Orientation */
1843
if (tag->Type == 3 && tag->Count == 1)
1845
switch (*(tag->ShortValues + 0))
1854
human = "Upsidedown";
1857
human = "Upsidedown Mirrored";
1860
human = "90 deg Clockwise Mirrored";
1863
human = "90 deg Counterclocwise";
1866
human = "90 deg Counterclocwise Mirrored";
1869
human = "90 deg Mirrored";
1874
case 0x9207: /* MeteringMode */
1875
if (tag->Type == 3 && tag->Count == 1)
1877
switch (*(tag->ShortValues + 0))
1883
human = "Center Weighted Average";
1889
human = "MultiSpot";
1892
human = "MultiSegment";
1903
case 0xA403: /* WhiteBalance */
1904
if (tag->Type == 3 && tag->Count == 1)
1906
switch (*(tag->ShortValues + 0))
1921
human = "Fluorescent";
1935
case 0x9209: /* Flash */
1936
if (tag->Type == 3 && tag->Count == 1)
1938
switch (*(tag->ShortValues + 0))
1950
human = "Flash, strobe return light not detected";
1953
human = "Flash, strobe return light detected";
1956
human = "Compulsory Flash";
1959
human = "Compulsory Flash, Return light not detected";
1962
human = "Compulsory Flash, Return light detected";
1965
human = "Flash, Auto-Mode";
1968
human = "Flash, Auto-Mode, Return light not detected";
1971
human = "Flash, Auto-Mode, Return light detected";
1977
human = "Red Eye, Return light not detected";
1980
human = "Red Eye, Return light detected";
1983
human = "Red Eye, Compulsory Flash";
1987
"Red Eye, Compulsory Flash, Return light not detected";
1991
"Red Eye, Compulsory Flash, Return light detected";
1994
human = "Red Eye, Auto-Mode";
1997
human = "Red Eye, Auto-Mode, Return light not detected";
2000
human = "Red Eye, Auto-Mode, Return light detected";
2005
case 0xA217: /* SensingMethod */
2006
if (tag->Type == 3 && tag->Count == 1)
2008
switch (*(tag->ShortValues + 0))
2011
human = "Not defined";
2014
human = "One Chip Color Area Sensor";
2017
human = "Two Chip Color Area Sensor";
2020
human = "Three Chip Color Area Sensor";
2023
human = "Color Sequential Area Sensor";
2026
human = "Trilinear Sensor";
2029
human = "Color Sequential Linear Sensor";
2034
case 0xA406: /* SceneCaptureType */
2035
if (tag->Type == 3 && tag->Count == 1)
2037
switch (*(tag->ShortValues + 0))
2043
human = "Landscape";
2049
human = "Night scene";
2054
case 0xA407: /* GainControl */
2055
if (tag->Type == 3 && tag->Count == 1)
2057
switch (*(tag->ShortValues + 0))
2063
human = "Low gain up";
2066
human = "High gain up";
2069
human = "Low gain down";
2072
human = "High gain down";
2077
case 0xA408: /* Contrast */
2078
if (tag->Type == 3 && tag->Count == 1)
2080
switch (*(tag->ShortValues + 0))
2094
case 0xA409: /* Saturation */
2095
if (tag->Type == 3 && tag->Count == 1)
2097
switch (*(tag->ShortValues + 0))
2103
human = "Low saturation";
2106
human = "High saturation";
2111
case 0xA40A: /* Sharpness */
2112
if (tag->Type == 3 && tag->Count == 1)
2114
switch (*(tag->ShortValues + 0))
2128
case 0xA40C: /* SubjectDistanceRange */
2129
if (tag->Type == 3 && tag->Count == 1)
2131
switch (*(tag->ShortValues + 0))
2140
human = "Close view";
2143
human = "Distant view";
2148
case 0x9208: /* LightSource */
2149
if (tag->Type == 3 && tag->Count == 1)
2151
switch (*(tag->ShortValues + 0))
2160
human = "Fluorescent";
2163
human = "Tungsten (incandescent light)";
2169
human = "Fine weather";
2172
human = "Cloudy weather";
2177
human = "Daylight fluorescent (D 5700 � 7100K)";
2180
human = "Day white fluorescent (N 4600 � 5400K)";
2183
human = "Cool white fluorescent (W 3900 � 4500K)";
2185
human = "White fluorescent (WW 3200 � 3700K)";
2188
human = "Standard light A";
2191
human = "Standard light B";
2194
human = "Standard light C";
2209
human = "ISO studio tungsten";
2212
human = "other light source";
2217
case 0xA001: /* ColorSpace */
2218
if (tag->Type == 3 && tag->Count == 1)
2220
switch (*(tag->ShortValues + 0))
2226
human = "Uncalibrated";
2231
case 0x8827: /* ISOSpeedRatings */
2232
if (tag->Type == 3 && tag->Count == 1)
2234
sprintf (dummy, "%u ISO", *(tag->ShortValues + 0));
2238
case 0xA002: /* ExifImageWidth */
2239
case 0xA003: /* ExifImageLength */
2240
if (tag->Type == 3 && tag->Count == 1)
2242
sprintf (dummy, "%u pixels", *(tag->ShortValues + 0));
2245
else if (tag->Type == 4 && tag->Count == 1)
2247
sprintf (dummy, "%u pixels", *(tag->LongValues + 0));
2251
case 0x829A: /* ExposureTime */
2252
if (tag->Type == 5 && tag->Count == 1)
2254
dblval = gaiaExifTagGetRationalValue (tag, 0, &xok);
2259
dblval = 1.0 / dblval;
2260
sprintf (dummy, "1/%1.0f sec", dblval);
2265
sprintf (dummy, "%1.0f sec", dblval);
2271
case 0x9201: /* ShutterSpeedValue */
2272
if (tag->Type == 10 && tag->Count == 1)
2274
dblval = gaiaExifTagGetSignedRationalValue (tag, 0, &xok);
2277
dblval = exp (dblval * log (2));
2279
dblval = floor (dblval);
2282
dblval = math_round (1.0 / dblval);
2283
sprintf (dummy, "%1.0f sec", dblval);
2288
sprintf (dummy, "1/%1.0f sec", dblval);
2294
case 0x829D: /* FNumber */
2295
if (tag->Type == 5 && tag->Count == 1)
2297
dblval = gaiaExifTagGetRationalValue (tag, 0, &xok);
2300
sprintf (dummy, "F %1.1f", dblval);
2305
case 0x9202: /* ApertureValue */
2306
case 0x9205: /* MaxApertureValue */
2307
if (tag->Type == 5 && tag->Count == 1)
2309
dblval = gaiaExifTagGetRationalValue (tag, 0, &xok);
2312
dblval = exp ((dblval * log (2)) / 2.0);
2313
sprintf (dummy, "F %1.1f", dblval);
2318
case 0x920A: /* FocalLength */
2319
if (tag->Type == 5 && tag->Count == 1)
2321
dblval = gaiaExifTagGetRationalValue (tag, 0, &xok);
2324
sprintf (dummy, "%1.1f mm", dblval);
2329
case 0xA405: /* FocalLengthIn35mmFilm */
2330
if (tag->Type == 3 && tag->Count == 1)
2332
sprintf (dummy, "%u mm", *(tag->ShortValues + 0));
2336
case 0x9204: /* ExposureBiasValue */
2337
if (tag->Type == 10 && tag->Count == 1)
2339
dblval = gaiaExifTagGetSignedRationalValue (tag, 0, &xok);
2342
sprintf (dummy, "%1.2f EV", dblval);
2352
strcpy (str, human);
2355
memset (str, '\0', len);
2356
memcpy (str, human, len - 1);
2364
GAIAEXIF_DECLARE int
2365
gaiaGuessBlobType (const unsigned char *blob, int size)
2367
/* returns the BLOB content type */
2372
gaiaExifTagListPtr exif_list;
2374
unsigned char jpeg1_signature[2];
2375
unsigned char jpeg2_signature[2];
2376
unsigned char jpeg3_signature[4];
2377
unsigned char jfif_signature[4];
2378
unsigned char exif_signature[4];
2379
unsigned char png_signature[8];
2380
unsigned char zip_signature[4];
2381
unsigned char tiff_signature_little[4];
2382
unsigned char tiff_signature_big[4];
2383
jpeg1_signature[0] = 0xff;
2384
jpeg1_signature[1] = 0xd8;
2385
jpeg2_signature[0] = 0xff;
2386
jpeg2_signature[1] = 0xd9;
2387
jpeg3_signature[0] = 0xff;
2388
jpeg3_signature[1] = 0xd8;
2389
jpeg3_signature[2] = 0xff;
2390
jpeg3_signature[3] = 0xe0;
2391
jfif_signature[0] = 0x4a;
2392
jfif_signature[1] = 0x46;
2393
jfif_signature[2] = 0x49;
2394
jfif_signature[3] = 0x46;
2395
exif_signature[0] = 0x45;
2396
exif_signature[1] = 0x78;
2397
exif_signature[2] = 0x69;
2398
exif_signature[3] = 0x66;
2399
png_signature[0] = 0x89;
2400
png_signature[1] = 0x50;
2401
png_signature[2] = 0x4e;
2402
png_signature[3] = 0x47;
2403
png_signature[4] = 0x0d;
2404
png_signature[5] = 0x0a;
2405
png_signature[6] = 0x1a;
2406
png_signature[7] = 0x0a;
2407
zip_signature[0] = 0x50;
2408
zip_signature[1] = 0x4b;
2409
zip_signature[2] = 0x03;
2410
zip_signature[3] = 0x04;
2411
tiff_signature_little[0] = 'I';
2412
tiff_signature_little[1] = 'I';
2413
tiff_signature_little[2] = 0x2a;
2414
tiff_signature_little[3] = 0x00;
2415
tiff_signature_big[0] = 'M';
2416
tiff_signature_big[1] = 'M';
2417
tiff_signature_big[2] = 0x00;
2418
tiff_signature_big[3] = 0x2a;
2419
if (size < 1 || !blob)
2420
return GAIA_HEX_BLOB;
2423
if (memcmp (blob, tiff_signature_big, 4) == 0)
2424
return GAIA_TIFF_BLOB;
2425
if (memcmp (blob, tiff_signature_little, 4) == 0)
2426
return GAIA_TIFF_BLOB;
2430
if (strncmp ((char *) blob, "%PDF-", 5) == 0)
2431
return GAIA_PDF_BLOB;
2435
if (memcmp (blob, zip_signature, 4) == 0)
2436
return GAIA_ZIP_BLOB;
2440
if (strncmp ((char *) blob, "GIF87a", 6) == 0
2441
|| strncmp ((char *) blob, "GIF89a", 6) == 0)
2442
return GAIA_GIF_BLOB;
2446
if (memcmp (blob, png_signature, 8) == 0)
2447
return GAIA_PNG_BLOB;
2451
if (memcmp (blob, jpeg1_signature, 2) == 0
2452
&& memcmp (blob + size - 2, jpeg2_signature, 2) == 0)
2453
jpeg = 1; /* this one is the standard JPEG signature */
2454
if (memcmp (blob, jpeg3_signature, 4) == 0)
2455
jpeg = 1; /* another common JPEG signature */
2459
if (memcmp (blob + 6, jfif_signature, 4) == 0)
2460
jpeg = 1; /* standard JFIF signature */
2461
if (memcmp (blob + 6, exif_signature, 4) == 0)
2462
jpeg = 1; /* standard EXIF signature */
2466
exif_list = gaiaGetExifTags (blob, size);
2470
pT = exif_list->First;
2480
gaiaExifTagsFree (exif_list);
2483
if (jpeg && exif && exif_gps)
2484
return GAIA_EXIF_GPS_BLOB;
2486
return GAIA_EXIF_BLOB;
2488
return GAIA_JPEG_BLOB;
2489
/* testing for GEOMETRY */
2494
if (*(blob + 0) != GAIA_MARK_START)
2496
if (*(blob + (size - 1)) != GAIA_MARK_END)
2498
if (*(blob + 38) != GAIA_MARK_MBR)
2500
if (*(blob + 1) == 0 || *(blob + 1) == 1)
2506
return GAIA_GEOMETRY_BLOB;
2507
return GAIA_HEX_BLOB;
2510
GAIAEXIF_DECLARE int
2511
gaiaGetGpsCoords (const unsigned char *blob, int size, double *longitude,
2514
/* returns the ExifGps coords, if they exists */
2515
gaiaExifTagListPtr exif_list;
2517
char lat_ref = '\0';
2518
char long_ref = '\0';
2519
double lat_degs = -DBL_MAX;
2520
double lat_mins = -DBL_MAX;
2521
double lat_secs = -DBL_MAX;
2522
double long_degs = -DBL_MAX;
2523
double long_mins = -DBL_MAX;
2524
double long_secs = -DBL_MAX;
2528
if (size < 1 || !blob)
2530
exif_list = gaiaGetExifTags (blob, size);
2533
pT = exif_list->First;
2536
if (pT->Gps && pT->TagId == 0x01)
2538
/* ok, this one is the GPSLatitudeRef tag */
2540
lat_ref = *(pT->StringValue);
2542
if (pT->Gps && pT->TagId == 0x03)
2544
/* ok, this one is the GPSLongitudeRef tag */
2546
long_ref = *(pT->StringValue);
2548
if (pT->Gps && pT->TagId == 0x02)
2550
/* ok, this one is the GPSLatitude tag */
2551
if (pT->Type == 5 && pT->Count == 3)
2553
dblval = gaiaExifTagGetRationalValue (pT, 0, &ok);
2556
dblval = gaiaExifTagGetRationalValue (pT, 1, &ok);
2559
dblval = gaiaExifTagGetRationalValue (pT, 2, &ok);
2564
if (pT->Gps && pT->TagId == 0x04)
2566
/* ok, this one is the GPSLongitude tag */
2567
if (pT->Type == 5 && pT->Count == 3)
2569
dblval = gaiaExifTagGetRationalValue (pT, 0, &ok);
2572
dblval = gaiaExifTagGetRationalValue (pT, 1, &ok);
2575
dblval = gaiaExifTagGetRationalValue (pT, 2, &ok);
2582
gaiaExifTagsFree (exif_list);
2583
if ((lat_ref == 'N' || lat_ref == 'S' || long_ref == 'E'
2584
|| long_ref == 'W') && lat_degs != -DBL_MAX
2585
&& lat_mins != -DBL_MAX && lat_secs != -DBL_MAX
2586
&& long_degs != -DBL_MAX && long_mins != -DBL_MAX
2587
&& long_secs != -DBL_MAX)
2593
lat_degs = math_round (lat_degs * 1000000.0);
2594
lat_mins = math_round (lat_mins * 1000000.0);
2595
lat_secs = math_round (lat_secs * 1000000.0);
2597
math_round (lat_degs + (lat_mins / 60.0) +
2598
(lat_secs / 3600.0)) * (sign / 1000000.0);
2600
if (long_ref == 'W')
2604
long_degs = math_round (long_degs * 1000000.0);
2605
long_mins = math_round (long_mins * 1000000.0);
2606
long_secs = math_round (long_secs * 1000000.0);
2608
math_round (long_degs + (long_mins / 60.0) +
2609
(long_secs / 3600.0)) * (sign / 1000000.0);
2610
*longitude = dblval;
2617
GAIAEXIF_DECLARE int
2618
gaiaGetGpsLatLong (const unsigned char *blob, int size, char *latlong,
2621
/* returns the ExifGps Latitude and Longitude, if they exists */
2622
gaiaExifTagListPtr exif_list;
2624
char lat_ref = '\0';
2625
char long_ref = '\0';
2626
double lat_degs = -DBL_MAX;
2627
double lat_mins = -DBL_MAX;
2628
double lat_secs = -DBL_MAX;
2629
double long_degs = -DBL_MAX;
2630
double long_mins = -DBL_MAX;
2631
double long_secs = -DBL_MAX;
2637
if (size < 1 || !blob)
2639
exif_list = gaiaGetExifTags (blob, size);
2642
pT = exif_list->First;
2645
if (pT->Gps && pT->TagId == 0x01)
2647
/* ok, this one is the GPSLatitudeRef tag */
2649
lat_ref = *(pT->StringValue);
2651
if (pT->Gps && pT->TagId == 0x03)
2653
/* ok, this one is the GPSLongitudeRef tag */
2655
long_ref = *(pT->StringValue);
2657
if (pT->Gps && pT->TagId == 0x02)
2659
/* ok, this one is the GPSLatitude tag */
2660
if (pT->Type == 5 && pT->Count == 3)
2662
dblval = gaiaExifTagGetRationalValue (pT, 0, &ok);
2665
dblval = gaiaExifTagGetRationalValue (pT, 1, &ok);
2668
dblval = gaiaExifTagGetRationalValue (pT, 2, &ok);
2673
if (pT->Gps && pT->TagId == 0x04)
2675
/* ok, this one is the GPSLongitude tag */
2676
if (pT->Type == 5 && pT->Count == 3)
2678
dblval = gaiaExifTagGetRationalValue (pT, 0, &ok);
2681
dblval = gaiaExifTagGetRationalValue (pT, 1, &ok);
2684
dblval = gaiaExifTagGetRationalValue (pT, 2, &ok);
2691
gaiaExifTagsFree (exif_list);
2692
if ((lat_ref == 'N' || lat_ref == 'S' || long_ref == 'E'
2693
|| long_ref == 'W') && lat_degs != -DBL_MAX
2694
&& lat_mins != -DBL_MAX && lat_secs != -DBL_MAX
2695
&& long_degs != -DBL_MAX && long_mins != -DBL_MAX
2696
&& long_secs != -DBL_MAX)
2699
"%c %1.2f %1.2f %1.2f / %c %1.2f %1.2f %1.2f",
2700
lat_ref, lat_degs, lat_mins, lat_secs, long_ref,
2701
long_degs, long_mins, long_secs);
2704
strcpy (latlong, ll);
2707
memcpy (latlong, ll, ll_size - 1);
2708
latlong[ll_size] = '\0';