Skip to content

Commit 1a6e85d

Browse files
committed
fix(exif): Support EXIF 3.0 tags
We were supporting Exif 2.3, but in 2024, Exif 3.0 was published and it adds some more tags for us to recognize. The only part I am not sure about here is that the ExifVersion we output is still marked as 2.3, not 3.0, because I'm worried that if we mark it as 3.0, older software reading the images will reject it. Let's see what happens. If downstream apps care, maybe we can bump to 3.0, or even bump to 3.0 only if any of the 3.0 tags are used (that is more involved). Signed-off-by: Larry Gritz <[email protected]>
1 parent 62be33f commit 1a6e85d

File tree

5 files changed

+90
-3
lines changed

5 files changed

+90
-3
lines changed

src/doc/stdmetadata.rst

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,59 @@ A sum of:
760760
A unique identifier for the image, as 16 ASCII hexadecimal digits
761761
representing a 128-bit number.
762762

763+
.. option:: "Exif:ImageTitle" : string
764+
765+
Title of the image.
766+
767+
.. option:: "Exif:Photographer" : string
768+
769+
The name of the photographer. This may be different from the "Artist"
770+
field.
771+
772+
.. option:: "Exif:ImageEdtor" : string
773+
774+
The name of the main person who edited the image.
775+
776+
.. option:: "Exif:CameraFirmware" : string
777+
778+
The name and version of the firmware of the camera that captured the image.
779+
780+
.. option:: "Exif:RAWDevelopingSoftware" : string
781+
782+
The name and version of the software that developed the RAW image.
783+
784+
.. option:: "Exif:ImageEditingSoftware" : string
785+
786+
The name and version of any image editing software that was used to
787+
process or edit the image.
788+
789+
.. option:: "Exif:MetadataEditingSoftware" : string
790+
791+
The name and version of any image editing software that was used to
792+
edit the image metadata but not the pixels.
793+
794+
.. option:: "Exif:CompositeImage" : int
795+
796+
Indicates whether the recorded image is a composite image (generated
797+
from capturing multiple, tentatively recorded, source images).
798+
799+
=== ==============================================================
800+
0 unknown
801+
1 non-composite image
802+
2 general composite image
803+
3 composite image captured when shooting
804+
=== ==============================================================
805+
806+
.. option:: "Exif:SourceImageNumberOfCompositeImage" : ushort[2]
807+
808+
If a composite image, the first value is the number of source images
809+
captured (at least 2) and the second value is the number of those
810+
source images ultimately used in the comopsite image.
811+
812+
.. option:: "Exif:SourceImageExposureTimesOfCompositeImage"
813+
814+
This is currently unsupported by OpenImageIO.
815+
763816

764817

765818
GPS Exif metadata

src/include/OpenImageIO/tiffutils.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ struct TIFFDirEntry {
4545

4646
OIIO_NAMESPACE_BEGIN
4747

48+
// Exif spec extends TIFFDataType beyond what TIFF or litiff define in
49+
// TIFFDataType.
50+
enum TIFFDataType_Exif3_Extensions {
51+
EXIF_UTF8_TYPE = 129
52+
};
53+
54+
55+
4856
// Define EXIF constants
4957
enum TIFFTAG {
5058
EXIF_EXPOSURETIME = 33434,
@@ -128,6 +136,16 @@ enum TIFFTAG {
128136
EXIF_LENSMODEL = 42036,
129137
EXIF_LENSSERIALNUMBER = 42037,
130138
EXIF_GAMMA = 42240,
139+
EXIF_IMAGETITLE = 42038,
140+
EXIF_PHOTOGRAPHER = 42039,
141+
EXIF_IMAGEEDTOR = 42040,
142+
EXIF_CAMERAFIRMWARE = 42041,
143+
EXIF_RAWDEVELOPINGSOFTWARE = 42042,
144+
EXIF_IMAGEEDITINGSOFTWARE = 42043,
145+
EXIF_METADATAEDITINGSOFTWARE = 42044,
146+
EXIF_COMPOSITEIMAGE = 42080,
147+
EXIF_SOURCEIMAGENUMBEROFCOMPOSITEIMAGE = 42080,
148+
EXIF_SOURCEIMAGEEXPOSURETIMESOFCOMPOSITEIMAGE = 42080,
131149
};
132150

133151
OIIO_NAMESPACE_END

src/libOpenImageIO/exif.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ print_dir_entry(std::ostream& out, const TagMap& tagmap,
260260

261261
switch (dir.tdir_type) {
262262
case TIFF_ASCII:
263+
case EXIF_TIFF_UTF8:
263264
OIIO::print(out, "'{}'", string_view(mydata, dir.tdir_count));
264265
break;
265266
case TIFF_RATIONAL: {
@@ -522,7 +523,17 @@ static const TagInfo exif_tag_table[] = {
522523
{ EXIF_LENSMAKE, "Exif:LensMake", TIFF_ASCII, 0 },
523524
{ EXIF_LENSMODEL, "Exif:LensModel", TIFF_ASCII, 0 },
524525
{ EXIF_LENSSERIALNUMBER, "Exif:LensSerialNumber", TIFF_ASCII, 0 },
525-
{ EXIF_GAMMA, "Exif:Gamma", TIFF_RATIONAL, 0 }
526+
{ EXIF_GAMMA, "Exif:Gamma", TIFF_RATIONAL, 0 },
527+
{ EXIF_IMAGETITLE, "Exif:ImageTitle", TIFF_ASCII, 0 },
528+
{ EXIF_PHOTOGRAPHER, "Exif:Photographer", TIFF_ASCII, 0 },
529+
{ EXIF_IMAGEEDTOR, "Exif:ImageEdtor", TIFF_ASCII, 0 },
530+
{ EXIF_CAMERAFIRMWARE, "Exif:CameraFirmware", TIFF_ASCII, 0 },
531+
{ EXIF_RAWDEVELOPINGSOFTWARE, "Exif:RAWDevelopingSoftware", TIFF_ASCII, 0 },
532+
{ EXIF_IMAGEEDITINGSOFTWARE, "Exif:ImageEditingSoftware", TIFF_ASCII, 0 },
533+
{ EXIF_METADATAEDITINGSOFTWARE, "Exif:MetadataEditingSoftware", TIFF_ASCII, 0 },
534+
{ EXIF_COMPOSITEIMAGE, "Exif:CompositeImage", TIFF_SHORT, 1 },
535+
{ EXIF_SOURCEIMAGENUMBEROFCOMPOSITEIMAGE, "Exif:SourceImageNumberOfCompositeImage", TIFF_SHORT, 2 },
536+
{ EXIF_SOURCEIMAGEEXPOSURETIMESOFCOMPOSITEIMAGE, "Exif:SourceImageExposureTimesOfCompositeImage", TIFF_NOTYPE, 0 },
526537
// clang-format on
527538
};
528539

@@ -742,7 +753,7 @@ add_exif_item_to_spec(ImageSpec& spec, const char* name,
742753
spec.attribute(name, TypeDesc(TypeDesc::FLOAT, int(count)), f);
743754
return;
744755
}
745-
if (dirp->tdir_type == TIFF_ASCII) {
756+
if (dirp->tdir_type == TIFF_ASCII || dirp->tdir_type == EXIF_UTF8_TYPE) {
746757
size_t len = tiff_data_size(*dirp);
747758
cspan<uint8_t> dspan = pvt::dataspan<char>(*dirp, buf,
748759
offset_adjustment, len);
@@ -1393,6 +1404,8 @@ encode_exif(const ImageSpec& spec, std::vector<char>& blob,
13931404
// Add some required Exif tags that wouldn't be in the spec
13941405
append_tiff_dir_entry(exifdirs, blob, EXIF_EXIFVERSION, TIFF_UNDEFINED,
13951406
4, as_bytes("0230", 4), tiffstart, 0, endianreq);
1407+
// NOTE: We are still saying we write Exif 2.3 even though we support
1408+
// the additional 3.0 tags.
13961409
append_tiff_dir_entry(exifdirs, blob, EXIF_FLASHPIXVERSION,
13971410
TIFF_UNDEFINED, 4, as_bytes("0100", 4), tiffstart,
13981411
0, endianreq);

src/libOpenImageIO/exif.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#define DEBUG_EXIF_UNHANDLED 0
2323

2424

25+
// Exif Documentation:
26+
// - https://archive.org/details/exif-specs-3.0-dc-008-translation-2023-e
27+
2528

2629
OIIO_NAMESPACE_BEGIN
2730
namespace pvt {

src/libOpenImageIO/xmp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ add_attrib(ImageSpec& spec, string_view xmlname, string_view xmlvalue,
317317
&& count == 1) {
318318
oiiotype = TypeDesc::FLOAT;
319319
special = Rational;
320-
} else if (tifftype == TIFF_ASCII)
320+
} else if (tifftype == TIFF_ASCII || tifftype == EXIF_UTF8_TYPE)
321321
oiiotype = TypeDesc::STRING;
322322
else if (tifftype == TIFF_BYTE && count == 1)
323323
oiiotype = TypeDesc::INT;

0 commit comments

Comments
 (0)