GraphicsMagick: coders/tiff.c Attempt to store EXIF inside TIFF ...
GraphicsMagick Commits <[email protected]> Sat, 16 Dec 2023 05:23:44 -0600
| Newsgroups | gmane.comp.video.graphicsmagick.cvs |
|---|---|
| Message-ID | <mailman.7808.1702725842.7803.graphicsmagick-commit@lists.sourceforge.net> |
changeset 382000be3396 in /hg/GraphicsMagick details: http://hg.GraphicsMagick.org/hg/GraphicsMagick?cmd=changeset;node=382000be3396 summary: coders/tiff.c Attempt to store EXIF inside TIFF image. diffstat: ChangeLog | 4 + coders/tiff.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 0 deletions(-) diffs (180 lines): diff -r aec67d608efc -r 382000be3396 ChangeLog --- a/ChangeLog Thu Dec 14 08:48:32 2023 -0600 +++ b/ChangeLog Sat Dec 16 12:23:21 2023 +0100 @@ -1,3 +1,7 @@ +2023-12-16 Fojtik Jaroslav <[email protected]> + + * coders/tiff.c Attempt to store EXIF inside TIFF image. + 2023-12-11 Fojtik Jaroslav <[email protected]> * coders/wpg.c Fix for oss-fuzz issue 64935: diff -r aec67d608efc -r 382000be3396 coders/tiff.c --- a/coders/tiff.c Thu Dec 14 08:48:32 2023 -0600 +++ b/coders/tiff.c Sat Dec 16 12:23:21 2023 +0100 @@ -4396,6 +4396,132 @@ #endif /* defined(HasTIFF) */ #if defined(HasTIFF) + +#if TIFFLIB_VERSION >= 20120922 + +#ifndef EXIFTAG_SECURITYCLASSIFICATION + #define EXIFTAG_SECURITYCLASSIFICATION 37394 +#endif +#ifndef EXIFTAG_IMAGEHISTORY + #define EXIFTAG_IMAGEHISTORY 37395 +#endif + +uint32_t LD_UINT32_LO(const unsigned char *Mem) +{ + return (uint32_t)Mem[0] | ((uint32_t)Mem[1] << 8) | ((uint32_t)Mem[2] << 16) | ((uint32_t)Mem[3] << 24); +} + +uint32_t LD_UINT32_HI(const unsigned char *Mem) +{ + return ((uint32_t)Mem[0]<<24) | ((uint32_t)Mem[1] << 16) | ((uint32_t)Mem[2] << 8) | ((uint32_t)Mem[3]); +} + +uint16_t LD_UINT16_LO(const unsigned char *Mem) +{ + return (uint32_t)Mem[0] | ((uint32_t)Mem[1] << 8); +} + +uint16_t LD_UINT16_HI(const unsigned char *Mem) +{ + return ((uint32_t)Mem[0] << 8) | ((uint32_t)Mem[1]); +} + + +int AddExifFields(TIFF *tiff, const unsigned char *profile_data, size_t profile_length) +{ +const char EXIF[6] = {'E','x','i','f',0,0}; +uint32_t val, IFDpos, NewIFDpos; +uint16_t EntryNum; +uint16_t Tag, Field; +uint32_t Long2, Value; +int FieldCount = 0; +uint32_t(*LD_UINT32)(const unsigned char *Mem); +uint16_t(*LD_UINT16)(const unsigned char *Mem); + + if(profile_data==NULL || profile_length<12+8) return 0; + if(memcmp(EXIF,profile_data,6)==0) + { + profile_data+=6; + profile_length-=6; + if(profile_length<12+8) return 0; + } + + if(profile_data[0]=='I' && profile_data[1]=='I') + { + LD_UINT32 = LD_UINT32_LO; + LD_UINT16 = LD_UINT16_LO; + } + else + { + if(profile_data[0]=='M' && profile_data[1]=='M') + { + LD_UINT32 = LD_UINT32_HI; + LD_UINT16 = LD_UINT16_HI; + } + else + return 0; + } + + IFDpos = 4; + do + { + Value = LD_UINT32(profile_data+IFDpos); + if(Value<=IFDpos || Value<8) return FieldCount; // 0 means stop; IFDPOS should progress. + IFDpos = Value; + + EntryNum = LD_UINT16(profile_data+IFDpos); + IFDpos += 2; + while(EntryNum>0) + { + Tag = LD_UINT16(profile_data+IFDpos); + Field = LD_UINT16(profile_data+IFDpos+2); + Long2 = LD_UINT32(profile_data+IFDpos+4); + Value = LD_UINT32(profile_data+IFDpos+8); + + if(Tag != EXIFTAG_SECURITYCLASSIFICATION && + Tag != EXIFTAG_IMAGEHISTORY && + Tag != EXIFTAG_ISOSPEEDRATINGS) /* libtiff doesn't understand these */ + { + switch(Field) + { + case TIFF_ASCII: if(Value>=profile_length-1) break; + TIFFSetField(tiff, Tag, profile_data+Value); + FieldCount++; + break; + case TIFF_SHORT: + case TIFF_LONG: TIFFSetField(tiff, Tag, Value); + FieldCount++; + break; +/* + { + ok = TIFFSetField (m_tif, tag, *(char**)p.data()); + } else if ((tifftype == TIFF_SHORT || tifftype == TIFF_LONG) && + p.type() == TypeDesc::SHORT) { + ok = TIFFSetField (m_tif, tag, (int)*(short *)p.data()); + } else if ((tifftype == TIFF_SHORT || tifftype == TIFF_LONG) && + p.type() == TypeDesc::INT) { + ok = TIFFSetField (m_tif, tag, *(int *)p.data()); + } else if ((tifftype == TIFF_RATIONAL || tifftype == TIFF_SRATIONAL) && + p.type() == TypeDesc::FLOAT) { + ok = TIFFSetField (m_tif, tag, *(float *)p.data()); + } else if ((tifftype == TIFF_RATIONAL || tifftype == TIFF_SRATIONAL) && + p.type() == TypeDesc::DOUBLE) { + ok = TIFFSetField (m_tif, tag, *(double *)p.data()); + } +*/ + } + } + IFDpos += 12; // Go to a next direntry. + if(IFDpos+12>=profile_length) return FieldCount; + EntryNum--; + } + } while(IFDpos+4 < profile_length); + + return FieldCount; +} + +#endif + /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % @@ -6472,6 +6598,32 @@ (void) LogMagickEvent(CoderEvent,GetMagickModule(), "TIFFWriteDirectory returns failed status!"); } + +#if TIFFLIB_VERSION >= 20120922 + if(status!=MagickFail) + { + const unsigned char *profile_data; + size_t profile_length; + if((profile_data=GetImageProfile(image,"Exif",&profile_length)) != 0) + { + if(AddExifFields(tiff,profile_data,profile_length) > 0) + { /* Now write the directory of Exif data */ + uint64_t dir_offset = 0; + if(!TIFFWriteCustomDirectory(tiff, &dir_offset)) + { + LogMagickEvent(CoderEvent,GetMagickModule(),"failed TIFFWriteCustomDirectory() of the Exif data"); + } + else + { /* Go back to the first directory, and add the EXIFIFD pointer. + std::cout << "diffdir = " << tiffdir << "\n"; */ + TIFFSetDirectory(tiff, 0); + TIFFSetField(tiff, TIFFTAG_EXIFIFD, dir_offset); + } + } + } + } +#endif + if (image->next == (Image *) NULL) break; image=SyncNextImageInList(image);