1 /*
2 * EXIF metadata parser
3 * Copyright (c) 2013 Thilo Borgmann <thilo.borgmann _at_ mail.de>
4 * Copyright (c) 2024-2025 Leo Izen <leo.izen@gmail.com>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * @file
25 * EXIF metadata parser
26 * @author Thilo Borgmann <thilo.borgmann _at_ mail.de>
27 * @author Leo Izen <leo.izen@gmail.com>
28 */
29
30 #include <inttypes.h>
31
32 #include "libavutil/avconfig.h"
37
41
42 #define EXIF_II_LONG 0x49492a00
43 #define EXIF_MM_LONG 0x4d4d002a
44
45 #define BASE_TAG_SIZE 12
46 #define IFD_EXTRA_SIZE 6
47
48 #define EXIF_TAG_NAME_LENGTH 32
49 #define MAKERNOTE_TAG 0x927c
50 #define ORIENTATION_TAG 0x112
51 #define EXIFIFD_TAG 0x8769
52 #define IMAGE_WIDTH_TAG 0x100
53 #define IMAGE_LENGTH_TAG 0x101
54 #define PIXEL_X_TAG 0xa002
55 #define PIXEL_Y_TAG 0xa003
56
60 };
61
63 {"GPSVersionID", 0x00}, // <- Table 12 GPS Attribute Information
64 {"GPSLatitudeRef", 0x01},
65 {"GPSLatitude", 0x02},
66 {"GPSLongitudeRef", 0x03},
67 {"GPSLongitude", 0x04},
68 {"GPSAltitudeRef", 0x05},
69 {"GPSAltitude", 0x06},
70 {"GPSTimeStamp", 0x07},
71 {"GPSSatellites", 0x08},
72 {"GPSStatus", 0x09},
73 {"GPSMeasureMode", 0x0A},
74 {"GPSDOP", 0x0B},
75 {"GPSSpeedRef", 0x0C},
76 {"GPSSpeed", 0x0D},
77 {"GPSTrackRef", 0x0E},
78 {"GPSTrack", 0x0F},
79 {"GPSImgDirectionRef", 0x10},
80 {"GPSImgDirection", 0x11},
81 {"GPSMapDatum", 0x12},
82 {"GPSDestLatitudeRef", 0x13},
83 {"GPSDestLatitude", 0x14},
84 {"GPSDestLongitudeRef", 0x15},
85 {"GPSDestLongitude", 0x16},
86 {"GPSDestBearingRef", 0x17},
87 {"GPSDestBearing", 0x18},
88 {"GPSDestDistanceRef", 0x19},
89 {"GPSDestDistance", 0x1A},
90 {"GPSProcessingMethod", 0x1B},
91 {"GPSAreaInformation", 0x1C},
92 {"GPSDateStamp", 0x1D},
93 {"GPSDifferential", 0x1E},
94 {"ImageWidth", 0x100}, // <- Table 3 TIFF Rev. 6.0 Attribute Information Used in Exif
95 {"ImageLength", 0x101},
96 {"BitsPerSample", 0x102},
97 {"Compression", 0x103},
98 {"PhotometricInterpretation", 0x106},
99 {"Orientation", 0x112},
100 {"SamplesPerPixel", 0x115},
101 {"PlanarConfiguration", 0x11C},
102 {"YCbCrSubSampling", 0x212},
103 {"YCbCrPositioning", 0x213},
104 {"XResolution", 0x11A},
105 {"YResolution", 0x11B},
106 {"ResolutionUnit", 0x128},
107 {"StripOffsets", 0x111},
108 {"RowsPerStrip", 0x116},
109 {"StripByteCounts", 0x117},
110 {"JPEGInterchangeFormat", 0x201},
111 {"JPEGInterchangeFormatLength",0x202},
112 {"TransferFunction", 0x12D},
113 {"WhitePoint", 0x13E},
114 {"PrimaryChromaticities", 0x13F},
115 {"YCbCrCoefficients", 0x211},
116 {"ReferenceBlackWhite", 0x214},
117 {"DateTime", 0x132},
118 {"ImageDescription", 0x10E},
119 {"Make", 0x10F},
120 {"Model", 0x110},
121 {"Software", 0x131},
122 {"Artist", 0x13B},
123 {"Copyright", 0x8298},
124 {"ExifVersion", 0x9000}, // <- Table 4 Exif IFD Attribute Information (1)
125 {"FlashpixVersion", 0xA000},
126 {"ColorSpace", 0xA001},
127 {"ComponentsConfiguration", 0x9101},
128 {"CompressedBitsPerPixel", 0x9102},
129 {"PixelXDimension", 0xA002},
130 {"PixelYDimension", 0xA003},
131 {"MakerNote", 0x927C},
132 {"UserComment", 0x9286},
133 {"RelatedSoundFile", 0xA004},
134 {"DateTimeOriginal", 0x9003},
135 {"DateTimeDigitized", 0x9004},
136 {"SubSecTime", 0x9290},
137 {"SubSecTimeOriginal", 0x9291},
138 {"SubSecTimeDigitized", 0x9292},
139 {"ImageUniqueID", 0xA420},
140 {"ExposureTime", 0x829A}, // <- Table 5 Exif IFD Attribute Information (2)
141 {"FNumber", 0x829D},
142 {"ExposureProgram", 0x8822},
143 {"SpectralSensitivity", 0x8824},
144 {"ISOSpeedRatings", 0x8827},
145 {"OECF", 0x8828},
146 {"ShutterSpeedValue", 0x9201},
147 {"ApertureValue", 0x9202},
148 {"BrightnessValue", 0x9203},
149 {"ExposureBiasValue", 0x9204},
150 {"MaxApertureValue", 0x9205},
151 {"SubjectDistance", 0x9206},
152 {"MeteringMode", 0x9207},
153 {"LightSource", 0x9208},
154 {"Flash", 0x9209},
155 {"FocalLength", 0x920A},
156 {"SubjectArea", 0x9214},
157 {"FlashEnergy", 0xA20B},
158 {"SpatialFrequencyResponse", 0xA20C},
159 {"FocalPlaneXResolution", 0xA20E},
160 {"FocalPlaneYResolution", 0xA20F},
161 {"FocalPlaneResolutionUnit", 0xA210},
162 {"SubjectLocation", 0xA214},
163 {"ExposureIndex", 0xA215},
164 {"SensingMethod", 0xA217},
165 {"FileSource", 0xA300},
166 {"SceneType", 0xA301},
167 {"CFAPattern", 0xA302},
168 {"CustomRendered", 0xA401},
169 {"ExposureMode", 0xA402},
170 {"WhiteBalance", 0xA403},
171 {"DigitalZoomRatio", 0xA404},
172 {"FocalLengthIn35mmFilm", 0xA405},
173 {"SceneCaptureType", 0xA406},
174 {"GainControl", 0xA407},
175 {"Contrast", 0xA408},
176 {"Saturation", 0xA409},
177 {"Sharpness", 0xA40A},
178 {"DeviceSettingDescription", 0xA40B},
179 {"SubjectDistanceRange", 0xA40C},
180
181 /* InteropIFD tags */
182 {"RelatedImageFileFormat", 0x1000},
183 {"RelatedImageWidth", 0x1001},
184 {"RelatedImageLength", 0x1002},
185
186 /* private EXIF tags */
187 {"PrintImageMatching", 0xC4A5}, // <- undocumented meaning
188
189 /* IFD tags */
190 {"ExifIFD", 0x8769}, // <- An IFD pointing to standard Exif metadata
191 {"GPSInfo", 0x8825}, // <- An IFD pointing to GPS Exif Metadata
192 {"InteropIFD", 0xA005}, // <- Table 13 Interoperability IFD Attribute Information
193 {"GlobalParametersIFD", 0x0190},
194 {"ProfileIFD", 0xc6f5},
195 };
196
197 /* same as type_sizes but with string == 1 */
199 [0] = 0,
213 };
214
216 {
220 }
221
223 }
224
226 {
228 return -1;
229
233 }
234
235 return -1;
236 }
237
239 {
240 le ? bytestream2_put_le16(pb,
value) : bytestream2_put_be16(pb,
value);
241 }
242
244 {
245 le ? bytestream2_put_le32(pb,
value) : bytestream2_put_be32(pb,
value);
246 }
247
249 {
250 le ? bytestream2_put_le64(pb,
value) : bytestream2_put_be64(pb,
value);
251 }
252
254 {
255 switch (
entry->type) {
259 break;
263 break;
267 break;
271 break;
275 break;
278 break;
281 break;
285 }
286 if (!
entry->value.ptr)
288 switch (
entry->type) {
290 for (
size_t i = 0;
i <
entry->count;
i++)
292 break;
294 for (
size_t i = 0;
i <
entry->count;
i++)
296 break;
298 for (
size_t i = 0;
i <
entry->count;
i++)
300 break;
302 for (
size_t i = 0;
i <
entry->count;
i++)
304 break;
306 for (
size_t i = 0;
i <
entry->count;
i++)
308 break;
310 for (
size_t i = 0;
i <
entry->count;
i++) {
313 }
314 break;
317 for (
size_t i = 0;
i <
entry->count;
i++) {
321 }
322 break;
325 /* these three fields are aliased to entry->value.ptr via a union */
326 /* and entry->value.ptr will always be nonzero here */
329 break;
333 break;
337 break;
338 }
339
340 return 0;
341 }
342
344 {
345 switch (
entry->type) {
347 for (
size_t i = 0;
i <
entry->count;
i++)
349 break;
351 for (
size_t i = 0;
i <
entry->count;
i++)
353 break;
355 for (
size_t i = 0;
i <
entry->count;
i++)
357 break;
359 for (
size_t i = 0;
i <
entry->count;
i++)
361 break;
363 for (
size_t i = 0;
i <
entry->count;
i++) {
364 const av_alias64
a = { .f64 =
entry->value.dbl[
i] };
366 }
367 break;
369 for (
size_t i = 0;
i <
entry->count;
i++) {
370 const av_alias32
a = { .f32 =
entry->value.dbl[
i] };
372 }
373 break;
376 for (
size_t i = 0;
i <
entry->count;
i++) {
379 }
380 break;
384 break;
387 break;
390 break;
391 }
392 }
393
396 static const uint8_t
foveon_header[] = {
'F',
'O',
'V',
'E',
'O',
'N', 0, 0, };
400 static const uint8_t
olympus2_header[] = {
'O',
'L',
'Y',
'M',
'P',
'U',
'S', 0,
'I',
'I', };
401 static const uint8_t
panasonic_header[] = {
'P',
'a',
'n',
'a',
's',
'o',
'n',
'i',
'c', 0, 0, 0, };
402 static const uint8_t
sigma_header[] = {
'S',
'I',
'G',
'M',
'A', 0, 0, 0, };
403 static const uint8_t
sony_header[] = {
'S',
'O',
'N',
'Y',
' ',
'D',
'S',
'C',
' ', 0, 0, 0, };
404
409 };
410
411 #define MAKERNOTE_STRUCT(h, r) { \
412 .header = (h), \
413 .header_size = sizeof((h)), \
414 .result = (r), \
415 }
416
427 };
428
429 /*
430 * derived from Exiv2 MakerNote's article
431 * https://exiv2.org/makernote.html or archived at
432 * https://web.archive.org/web/20250311155857/https://exiv2.org/makernote.html
433 */
435 {
437 return -1;
438
442 }
443
446 return -1;
448 return -1;
449 return 8;
450 }
451
452 return 0;
453 }
454
457
460 {
461 int ret = 0, makernote_offset = -1,
tell, is_ifd, count;
463 uint32_t payload;
464
465 /* safety check to prevent infinite recursion on malicious IFDs */
466 if (depth > 3)
468
470
475
476 av_log(logctx,
AV_LOG_DEBUG,
"TIFF Tag: id: 0x%04x, type: %d, count: %u, offset: %d, "
477 "payload: %" PRIu32
"\n",
entry->id,
type, count,
tell, payload);
478
479 /* AV_TIFF_IFD is the largest, numerically */
482
484
485 if (is_ifd) {
486 if (!payload)
487 goto end;
489 }
490
493 if (makernote_offset < 0)
494 is_ifd = 0;
495 }
496
497 if (is_ifd) {
500 entry->ifd_offset = makernote_offset > 0 ? makernote_offset : 0;
501 if (
entry->ifd_offset) {
503 if (!
entry->ifd_lead)
506 }
509 /*
510 * we guessed that MakerNote was an IFD
511 * but we were probably incorrect at this
512 * point so we try again as a binary blob
513 */
516 is_ifd = 0;
517 }
518 }
519
520 /* inverted condition instead of else so we can fall through from above */
521 if (!is_ifd) {
523 entry->count = count;
526 }
527
528 end:
530
532 }
533
536 {
537 uint32_t entries;
538 size_t required_size;
540
542
545 "not enough bytes remaining in EXIF buffer: 2 required\n");
547 }
548
552 "not enough bytes remaining in EXIF buffer. entries: %" PRIu32 "\n", entries);
554 }
555 if (entries > 4096) {
556 /* that is a lot of entries, probably an error */
558 "too many entries: %" PRIu32 "\n", entries);
560 }
561
562 ifd->
count = entries;
564
565 /* empty IFD is technically legal but equivalent to no metadata present */
567 goto end;
568
575 }
577
578 /* entries have pointers in them which can cause issues if */
579 /* they are freed or realloc'd when garbage */
580 memset(ifd->
entries, 0, required_size);
581
582 for (uint32_t
i = 0;
i < entries;
i++) {
586 }
587
588 end:
589 /*
590 * at the end of an IFD is an pointer to the next IFD
591 * or zero if there are no more IFDs, which is usually the case
592 */
594 }
595
596 /*
597 * note that this function does not free the entry pointer itself
598 * because it's probably part of a larger array that should be freed
599 * all at once
600 */
602 {
604 return;
607 else
610 }
611
613 {
614 if (!ifd)
615 return;
619 return;
620 }
621 for (
size_t i = 0;
i < ifd->
count;
i++) {
624 }
628 }
629
631 {
632 /* 6 == 4 + 2; 2-byte entry-count at the beginning */
633 /* plus 4-byte next-IFD pointer at the end */
635 for (
size_t i = 0;
i < ifd->
count;
i++) {
639 } else {
641 total_size +=
BASE_TAG_SIZE + (payload_size > 4 ? payload_size : 0);
642 }
643 }
644 return total_size;
645 }
646
648 {
654 for (
size_t i = 0;
i < ifd->
count;
i++) {
656 av_log(logctx,
AV_LOG_DEBUG,
"writing TIFF entry: id: 0x%04" PRIx16
", type: %d, count: %"
657 PRIu32 ", offset: %d, offset value: %d\n",
665 } else {
668 }
673 if (
entry->ifd_offset)
680 } else {
682 if (payload_size > 4) {
689 } else {
690 /* zero uninitialized excess payload values */
694 }
695 }
696 }
697
698 /*
699 * we write 0 if this is the top-level exif IFD
700 * indicating that there are no more IFD pointers
701 */
704 }
705
707 {
709 size_t size, headsize = 8;
712
713 int le = 1;
714
717
719 switch (header_mode) {
721 off = 6;
722 break;
724 off = 4;
725 break;
727 le = 0;
728 headsize = 0;
729 break;
731 le = 1;
732 headsize = 0;
733 break;
734 }
736 if (!buf)
738
744 }
745
747
749 /* these constants are be32 in both cases */
750 /* le == 1 always in this case */
753 }
754
760 }
761
763
764 return 0;
765 }
766
769 {
774 size_t off = 0;
775 switch (header_mode) {
779 off = 6;
780 /* fallthrough */
784 if (!off)
786 /* fallthrough */
788 int ifd_offset;
792 // read TIFF header
797 }
799 break;
800 }
802 le = 1;
804 break;
806 le = 0;
808 break;
809 default:
811 }
812
813 /*
814 * parse IFD0 here. If the return value is positive that tells us
815 * there is subimage metadata, but we don't parse that IFD here
816 */
822 }
823
825 }
826
827 #define COLUMN_SEP(i, c) ((i) ? ((i) % (c) ? ", " : "\n") : "")
828
830 {
831 AVBPrint bp;
835
836 if (!prefix)
837 prefix = "";
838
839 for (uint16_t
i = 0;
i < ifd->
count;
i++) {
843 if (*prefix)
847 else
851 goto end;
853 switch (
entry->type) {
857 goto end;
858 break;
861 for (uint32_t j = 0; j <
entry->count; j++)
863 break;
866 for (uint32_t j = 0; j <
entry->count; j++)
868 break;
871 for (uint32_t j = 0; j <
entry->count; j++)
873 break;
876 for (uint32_t j = 0; j <
entry->count; j++)
878 break;
881 break;
884 for (uint32_t j = 0; j <
entry->count; j++)
886 break;
888 for (uint32_t j = 0; j <
entry->count; j++)
890 break;
891 }
896 goto end;
897 }
900 goto end;
905 goto end;
906 } else {
908 }
909 }
910
911 end:
915 }
916
918 {
920 }
921
922 #if LIBAVCODEC_VERSION_MAJOR < 63
925 {
936 }
937 #endif
938
939 #define EXIF_COPY(fname, srcname) do { \
940 size_t sz; \
941 if (av_size_mult(src->count, sizeof(*(fname)), &sz) < 0) { \
942 ret = AVERROR(ENOMEM); \
943 goto end; \
944 } \
945 (fname) = av_memdup((srcname), sz); \
946 if (!(fname)) { \
947 ret = AVERROR(ENOMEM); \
948 goto end; \
949 } \
950 } while (0)
951
953 {
955
956 memset(
dst, 0,
sizeof(*
dst));
957
961
962 dst->ifd_offset =
src->ifd_offset;
965 if (!
dst->ifd_lead) {
967 goto end;
968 }
969 } else {
971 }
972
976 if (!cloned) {
978 goto end;
979 }
980 dst->value.ifd = *cloned;
982 break;
983 }
987 break;
991 break;
995 break;
999 break;
1003 break;
1006 break;
1009 if (!
dst->value.str) {
1011 goto end;
1012 }
1013 break;
1014 }
1015
1016 return 0;
1017
1018 end:
1022 else
1024 memset(
dst, 0,
sizeof(*
dst));
1025
1027 }
1028
1030 {
1032
1035
1036 for (
size_t i = 0;
i < ifd->
count;
i++) {
1040 }
1042 if (depth < 3) {
1046 }
1048 }
1049 }
1050
1051 return 0;
1052 }
1053
1055 {
1057 }
1058
1060 uint32_t count,
const uint8_t *ifd_lead, uint32_t ifd_offset,
const void *
value)
1061 {
1066
1068 || ifd_lead && !ifd_offset || !ifd_lead && ifd_offset
1071
1075
1078 } else {
1079 size_t required_size;
1088 }
1089
1093 src.ifd_lead = (uint8_t *) ifd_lead;
1094 src.ifd_offset = ifd_offset;
1097 else
1099
1101
1104
1106 }
1107
1109 {
1112
1115
1116 for (
size_t i = 0;
i < ifd->
count;
i++) {
1119 break;
1120 }
1125 }
1126 }
1127
1129 return 0;
1131
1135 return 1;
1136 }
1137
1139
1141 }
1142
1144 {
1146 }
1147
1149 {
1153
1156 size_t required_size;
1162 }
1163
1164 for (
size_t i = 0;
i <
ret->count;
i++) {
1170 }
1171
1173
1178 }
1179
1181 {1, 8, 3, 6}, {4, 7, 2, 5},
1182 };
1183
1185 {
1187 // determinant
1191 return 0;
1192 int rot = (int)(rotation + 0.5);
1193 rot = (((rot % 360) + 360) % 360) / 90;
1195 }
1196
1198 {
1199 switch (orientation) {
1200 case 1:
1202 break;
1203 case 2:
1206 break;
1207 case 3:
1209 break;
1210 case 4:
1213 break;
1214 case 5:
1217 break;
1218 case 6:
1220 break;
1221 case 7:
1224 break;
1225 case 8:
1227 break;
1228 default:
1230 }
1231
1232 return 0;
1233 }
1234
1236 {
1244 uint64_t orientation = 1;
1245 uint64_t
w =
frame->width;
1246 uint64_t
h =
frame->height;
1247 int rewrite = 0;
1248
1250
1251 if (sd_orient)
1253 if (orientation != 1)
1254 av_log(logctx,
AV_LOG_DEBUG,
"matrix contains nontrivial EXIF orientation: %" PRIu64
"\n", orientation);
1255
1256 for (
size_t i = 0;
i < ifd->
count;
i++) {
1260 continue;
1261 }
1264 continue;
1265 }
1268 continue;
1269 }
1272 for (
size_t j = 0; j < exif->
count; j++) {
1275 pw = exifentry;
1276 continue;
1277 }
1280 continue;
1281 }
1282 }
1283 }
1284 }
1285
1286 if (or && or->
value.
uint[0] != orientation) {
1287 rewrite = 1;
1289 }
1291 rewrite = 1;
1293 }
1295 rewrite = 1;
1297 }
1299 rewrite = 1;
1301 }
1302 if (
ph &&
ph->value.uint[0] !=
h) {
1303 rewrite = 1;
1304 ph->value.uint[0] =
h;
1305 }
1306 if (!or && orientation != 1) {
1307 rewrite = 1;
1310 goto end;
1311 }
1313 rewrite = 1;
1316 goto end;
1317 }
1319 rewrite = 1;
1322 goto end;
1323 }
1324 if (!pw &&
w &&
w < 0xFFFFu || !
ph &&
h &&
h < 0xFFFFu) {
1328 rewrite = 1;
1329 if (exif_found < 0)
1330 goto end;
1331 if (exif_found > 0) {
1333 } else {
1338 goto end;
1339 }
1341 }
1342 if (!pw &&
w &&
w < 0xFFFFu) {
1345 goto end;
1346 }
1347 if (!
ph &&
h &&
h < 0xFFFFu) {
1350 goto end;
1351 }
1352 }
1353
1354 return rewrite;
1355
1356 end:
1358 }
1359
1361 {
1366 int rewrite = 0;
1367
1368 if (!buffer_ptr || *buffer_ptr)
1370
1372 if (!sd_exif)
1373 return 0;
1374
1377 goto end;
1378
1380 if (rewrite < 0) {
1382 goto end;
1383 }
1384
1385 if (rewrite) {
1388 goto end;
1389
1391 } else {
1393 if (!*buffer_ptr) {
1395 goto end;
1396 }
1397 }
1398
1400 return rewrite;
1401
1402 end:
1405 }