From 9f4f3548063f1758389aa5e53ea5dba8383c9cf1 Mon Sep 17 00:00:00 2001 From: dirk Date: Mon, 21 Apr 2014 17:19:03 +0000 Subject: [PATCH] The 8bim profile will be updated when the iptc profile is changed. --- MagickCore/profile.c | 167 +++++++++++++++++++++++++++++++++++++++---- coders/meta.c | 139 ++++++++++------------------------- 2 files changed, 191 insertions(+), 115 deletions(-) diff --git a/MagickCore/profile.c b/MagickCore/profile.c index 304dee009..a7b8408f3 100644 --- a/MagickCore/profile.c +++ b/MagickCore/profile.c @@ -99,7 +99,17 @@ source_type,target_profile,target_type,intent,flags); #define cmsOpenProfileFromMemTHR(context,profile,length) \ cmsOpenProfileFromMem(profile,length) -#endif +#endif + +/* + Forward declarations +*/ +static MagickBooleanType + SetImageProfileInternal(Image *,const char *,const StringInfo *, + const MagickBooleanType,ExceptionInfo *); + +static void + WriteTo8BimProfile(Image *,const char*,const StringInfo *); /* Typedef declarations @@ -204,6 +214,7 @@ MagickExport MagickBooleanType DeleteImageProfile(Image *image,const char *name) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if (image->profiles == (SplayTreeInfo *) NULL) return(MagickFalse); + WriteTo8BimProfile(image,name,(StringInfo *) NULL); return(DeleteNodeFromSplayTree((SplayTreeInfo *) image->profiles,name)); } @@ -1024,6 +1035,7 @@ MagickExport StringInfo *RemoveImageProfile(Image *image,const char *name) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); if (image->profiles == (SplayTreeInfo *) NULL) return((StringInfo *) NULL); + WriteTo8BimProfile(image,name,(StringInfo *) NULL); profile=(StringInfo *) RemoveNodeFromSplayTree((SplayTreeInfo *) image->profiles,name); return(profile); @@ -1134,9 +1146,121 @@ static inline const unsigned char *ReadResourceShort(const unsigned char *p, *quantum=(unsigned short) (*p++ << 8); *quantum|=(unsigned short) (*p++ << 0); return(p); -} - -static MagickBooleanType GetProfilesFromResourceBlock(Image *image, +}static inline void WriteResourceLong(unsigned char *p, + const unsigned int quantum) +{ + unsigned char + buffer[4]; + + buffer[0]=(unsigned char) (quantum >> 24); + buffer[1]=(unsigned char) (quantum >> 16); + buffer[2]=(unsigned char) (quantum >> 8); + buffer[3]=(unsigned char) quantum; + (void) CopyMagickMemory(p,buffer,4); +} + +static void WriteTo8BimProfile(Image *image,const char *name, + const StringInfo *iptc_profile) +{ + + const unsigned char + *datum, + *s; + + register const unsigned char + *p; + + size_t + length; + + StringInfo + *profile; + + ssize_t + count; + + unsigned char + length_byte; + + unsigned int + value; + + unsigned short + id; + + if (LocaleCompare(name,"iptc") != 0) + return; + profile=(StringInfo *)GetValueFromSplayTree((SplayTreeInfo *)image->profiles, + "8bim"); + if (profile == (StringInfo *) NULL) + return; + datum=GetStringInfoDatum(profile); + length=GetStringInfoLength(profile); + for (p=datum; p < (datum+length-16); ) + { + s=p; + if (LocaleNCompare((char *) p,"8BIM",4) != 0) + break; + p+=4; + p=ReadResourceShort(p,&id); + p=ReadResourceByte(p,&length_byte); + p+=length_byte; + if (((length_byte+1) & 0x01) != 0) + p++; + if (p > (datum+length-4)) + break; + p=ReadResourceLong(p,&value); + count=(ssize_t) value; + if ((p > (datum+length-count)) || (count > length)) + break; + if ((count & 0x01) != 0) + count++; + if (id == 0x0404) + { + size_t + offset, + rest; + + ssize_t + new_count; + + StringInfo + *new_profile; + + new_count=0; + rest=(datum+length)-(p+count); + if (iptc_profile == (StringInfo *) NULL) + { + offset=(s-datum); + new_profile=AcquireStringInfo(offset+rest); + (void) CopyMagickMemory(new_profile->datum,datum,offset); + } + else + { + offset=(p-datum); + new_count=iptc_profile->length; + if ((new_count & 0x01) != 0) + new_count++; + new_profile=AcquireStringInfo(offset+new_count+rest); + (void) CopyMagickMemory(new_profile->datum,datum,offset-4); + WriteResourceLong(new_profile->datum+offset-4, + iptc_profile->length); + (void) CopyMagickMemory(new_profile->datum+offset, + iptc_profile->datum,iptc_profile->length); + } + (void) CopyMagickMemory(new_profile->datum+offset+new_count,p+count, + rest); + (void) AddValueToSplayTree((SplayTreeInfo *) image->profiles, + ConstantString("8bim"),CloneStringInfo(new_profile)); + new_profile=DestroyStringInfo(new_profile); + break; + } + else + p+=count; + } +} + +static void GetProfilesFromResourceBlock(Image *image, const StringInfo *resource_block,ExceptionInfo *exception) { const unsigned char @@ -1219,7 +1343,8 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image, */ profile=AcquireStringInfo(count); SetStringInfoDatum(profile,p); - (void) SetImageProfile(image,"iptc",profile,exception); + (void) SetImageProfileInternal(image,"iptc",profile,MagickTrue, + exception); profile=DestroyStringInfo(profile); p+=count; break; @@ -1239,7 +1364,8 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image, */ profile=AcquireStringInfo(count); SetStringInfoDatum(profile,p); - (void) SetImageProfile(image,"icc",profile,exception); + (void) SetImageProfileInternal(image,"icc",profile,MagickTrue, + exception); profile=DestroyStringInfo(profile); p+=count; break; @@ -1251,7 +1377,8 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image, */ profile=AcquireStringInfo(count); SetStringInfoDatum(profile,p); - (void) SetImageProfile(image,"exif",profile,exception); + (void) SetImageProfileInternal(image,"exif",profile,MagickTrue, + exception); profile=DestroyStringInfo(profile); p+=count; break; @@ -1263,7 +1390,8 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image, */ profile=AcquireStringInfo(count); SetStringInfoDatum(profile,p); - (void) SetImageProfile(image,"xmp",profile,exception); + (void) SetImageProfileInternal(image,"xmp",profile,MagickTrue, + exception); profile=DestroyStringInfo(profile); p+=count; break; @@ -1277,11 +1405,11 @@ static MagickBooleanType GetProfilesFromResourceBlock(Image *image, if ((count & 0x01) != 0) p++; } - return(MagickTrue); } -MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name, - const StringInfo *profile,ExceptionInfo *exception) +static MagickBooleanType SetImageProfileInternal(Image *image,const char *name, + const StringInfo *profile,const MagickBooleanType recursive, + ExceptionInfo *exception) { char key[MaxTextExtent], @@ -1298,11 +1426,16 @@ MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name, image->profiles=NewSplayTree(CompareSplayTreeString,RelinquishMagickMemory, DestroyProfile); (void) CopyMagickString(key,name,MaxTextExtent); + LocaleLower(key); status=AddValueToSplayTree((SplayTreeInfo *) image->profiles, ConstantString(key),CloneStringInfo(profile)); - if ((status != MagickFalse) && - ((LocaleCompare(name,"iptc") == 0) || (LocaleCompare(name,"8bim") == 0))) - (void) GetProfilesFromResourceBlock(image,profile,exception); + if (status != MagickFalse) + { + if (LocaleCompare(name,"8bim") == 0) + GetProfilesFromResourceBlock(image,profile,exception); + else if (recursive == MagickFalse) + WriteTo8BimProfile(image,name,profile); + } /* Inject profile into image properties. */ @@ -1310,6 +1443,12 @@ MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name, (void) GetImageProperty(image,property,exception); return(status); } + +MagickExport MagickBooleanType SetImageProfile(Image *image,const char *name, + const StringInfo *profile,ExceptionInfo *exception) +{ + return(SetImageProfileInternal(image,name,profile,MagickFalse,exception)); +} /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/coders/meta.c b/coders/meta.c index 2edf98380..f659ce180 100644 --- a/coders/meta.c +++ b/coders/meta.c @@ -1063,6 +1063,39 @@ static int jpeg_extract(Image *ifile, Image *ofile) } #endif +static inline void CopyBlob(Image *source,Image *destination) +{ + ssize_t + i; + + unsigned char + *buffer; + + ssize_t + count, + length; + + buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent, + sizeof(*buffer)); + if (buffer != (unsigned char *) NULL) + { + i=0; + while ((length=ReadBlob(source,MagickMaxBufferExtent,buffer)) != 0) + { + count=0; + for (i=0; i < (ssize_t) length; i+=count) + { + count=WriteBlob(destination,(size_t) (length-i),buffer+i); + if (count <= 0) + break; + } + if (i < (ssize_t) length) + break; + } + buffer=(unsigned char *) RelinquishMagickMemory(buffer); + } +} + static Image *ReadMETAImage(const ImageInfo *image_info, ExceptionInfo *exception) { @@ -1070,9 +1103,6 @@ static Image *ReadMETAImage(const ImageInfo *image_info, *buff, *image; - int - c; - MagickBooleanType status; @@ -1138,15 +1168,7 @@ static Image *ReadMETAImage(const ImageInfo *image_info, (void) WriteBlobByte(buff,0x0); } else - { - for ( ; ; ) - { - c=ReadBlobByte(image); - if (c == EOF) - break; - (void) WriteBlobByte(buff,(unsigned char) c); - } - } + CopyBlob(image,buff); profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t) GetBlobSize(buff)); if (profile == (StringInfo *) NULL) @@ -1214,48 +1236,7 @@ static Image *ReadMETAImage(const ImageInfo *image_info, } } else - { -#ifdef SLOW_METHOD - for ( ; ; ) - { - /* Really - really slow - FIX ME PLEASE!!!! */ - c=ReadBlobByte(image); - if (c == EOF) - break; - (void) WriteBlobByte(buff,c); - } -#else - ssize_t - i; - - unsigned char - *buffer; - - ssize_t - count, - length; - - buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent, - sizeof(*buffer)); - if (buffer != (unsigned char *) NULL) - { - i=0; - while ((length=ReadBlob(image,MagickMaxBufferExtent,buffer)) != 0) - { - count=0; - for (i=0; i < (ssize_t) length; i+=count) - { - count=WriteBlob(buff,(size_t) (length-i),buffer+i); - if (count <= 0) - break; - } - if (i < (ssize_t) length) - break; - } - buffer=(unsigned char *) RelinquishMagickMemory(buffer); - } -#endif - } + CopyBlob(image,buff); profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t) GetBlobSize(buff)); if (profile == (StringInfo *) NULL) @@ -1281,13 +1262,7 @@ static Image *ReadMETAImage(const ImageInfo *image_info, ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } AttachBlob(buff->blob,blob,length); - for ( ; ; ) - { - c=ReadBlobByte(image); - if (c == EOF) - break; - (void) WriteBlobByte(buff,(unsigned char) c); - } + CopyBlob(image,buff); profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t) GetBlobSize(buff)); if (profile == (StringInfo *) NULL) @@ -1300,9 +1275,6 @@ static Image *ReadMETAImage(const ImageInfo *image_info, } if (LocaleCompare(image_info->magick,"IPTC") == 0) { - register unsigned char - *p; - buff=AcquireImage((ImageInfo *) NULL,exception); if (buff == (Image *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); @@ -1313,40 +1285,11 @@ static Image *ReadMETAImage(const ImageInfo *image_info, ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } AttachBlob(buff->blob,blob,length); - /* write out the header - length field patched below */ - (void) WriteBlob(buff,11,(unsigned char *) "8BIM\04\04\0\0\0\0\0"); - (void) WriteBlobByte(buff,0xc6); - if (LocaleCompare(image_info->magick,"IPTCTEXT") == 0) - { - length=(size_t) parse8BIM(image,buff); - if (length & 1) - (void) WriteBlobByte(buff,0x00); - } - else if (LocaleCompare(image_info->magick,"IPTCWTEXT") == 0) - { - } - else - { - for ( ; ; ) - { - c=ReadBlobByte(image); - if (c == EOF) - break; - (void) WriteBlobByte(buff,(unsigned char) c); - } - } + CopyBlob(image,buff); profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t) GetBlobSize(buff)); if (profile == (StringInfo *) NULL) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); - /* - subtract off the length of the 8BIM stuff. - */ - length=GetStringInfoLength(profile)-12; - p=GetStringInfoDatum(profile); - p[10]=(unsigned char) (length >> 8); - p[11]=(unsigned char) (length & 0xff); - SetStringInfoDatum(profile,GetBlobStreamData(buff)); (void) SetImageProfile(image,"8bim",profile,exception); profile=DestroyStringInfo(profile); blob=DetachBlob(buff->blob); @@ -1365,13 +1308,7 @@ static Image *ReadMETAImage(const ImageInfo *image_info, ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } AttachBlob(buff->blob,blob,length); - for ( ; ; ) - { - c=ReadBlobByte(image); - if (c == EOF) - break; - (void) WriteBlobByte(buff,(unsigned char) c); - } + CopyBlob(image,buff); profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t) GetBlobSize(buff)); if (profile == (StringInfo *) NULL) -- 2.40.0