From: dirk Date: Mon, 22 Aug 2016 21:30:07 +0000 (+0200) Subject: Some of the additional layer information will be preserved when converting from PSD... X-Git-Tag: 7.0.2-10~9 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6661998e7693ff84516ebb520a8db0f262b2444b;p=imagemagick Some of the additional layer information will be preserved when converting from PSD to PSD. --- diff --git a/coders/psd.c b/coders/psd.c index 2a9d6a776..9879dd9ed 100644 --- a/coders/psd.c +++ b/coders/psd.c @@ -84,6 +84,7 @@ */ #define MaxPSDChannels 56 #define PSDQuantum(x) (((ssize_t) (x)+1) & -2) +#define PSDAdditionalInfo "PSDInfo" /* Enumerated declaractions. @@ -165,6 +166,9 @@ typedef struct _LayerInfo unsigned short channels; + + StringInfo + *info; } LayerInfo; /* @@ -544,6 +548,8 @@ static inline LayerInfo *DestroyLayerInfo(LayerInfo *layer_info, layer_info[i].image=DestroyImage(layer_info[i].image); if (layer_info[i].mask.image != (Image *) NULL) layer_info[i].mask.image=DestroyImage(layer_info[i].mask.image); + if (layer_info[i].info != (StringInfo *) NULL) + layer_info[i].info=DestroyStringInfo(layer_info[i].info); } return (LayerInfo *) RelinquishMagickMemory(layer_info); @@ -1557,7 +1563,7 @@ ModuleExport MagickBooleanType ReadPSDLayers(Image *image, /* We read it, but don't use it... */ - for (j=0; j < (ssize_t) (length); j+=8) + for (j=0; j < (ssize_t) length; j+=8) { size_t blend_source=ReadBlobLong(image); size_t blend_dest=ReadBlobLong(image); @@ -1570,7 +1576,7 @@ ModuleExport MagickBooleanType ReadPSDLayers(Image *image, /* Layer name. */ - length=(size_t) ReadBlobByte(image); + length=(MagickSizeType) ReadBlobByte(image); combined_length+=length+1; if (length > 0) (void) ReadBlob(image,(size_t) length++,layer_info[i].name); @@ -1578,19 +1584,25 @@ ModuleExport MagickBooleanType ReadPSDLayers(Image *image, if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), " layer name: %s",layer_info[i].name); - /* - Skip the rest of the variable data until we support it. - */ - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " unsupported data: length=%.20g",(double) - ((MagickOffsetType) (size-combined_length))); - if (DiscardBlobBytes(image,(MagickSizeType) (size-combined_length)) == MagickFalse) + length=(length+(4-(length % 4)))-length; + combined_length+=length; + /* Skip over the padding of the layer name */ + if (DiscardBlobBytes(image,length) == MagickFalse) { layer_info=DestroyLayerInfo(layer_info,number_layers); ThrowBinaryException(CorruptImageError, "UnexpectedEndOfFile",image->filename); } + length=(MagickSizeType) size-combined_length; + if (length > 0) + { + unsigned char + *info; + + layer_info[i].info=AcquireStringInfo((const size_t) length); + info=GetStringInfoDatum(layer_info[i].info); + (void) ReadBlob(image,(const size_t) length,info); + } } } @@ -1619,6 +1631,13 @@ ModuleExport MagickBooleanType ReadPSDLayers(Image *image, ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", image->filename); } + + if (layer_info[i].info != (StringInfo *) NULL) + { + (void) SetImageProfile(layer_info[i].image,PSDAdditionalInfo, + layer_info[i].info,exception); + layer_info[i].info=DestroyStringInfo(layer_info[i].info); + } } if (image_info->ping == MagickFalse) @@ -2634,14 +2653,109 @@ static void RemoveResolutionFromResourceBlock(StringInfo *bim_profile) } } +static const StringInfo *FilterAdditionalLayerInformation(Image *image, + ExceptionInfo *exception) +{ +#define PSDKeySize 5 +#define PSDAllowedLength 36 + + char + key[PSDKeySize]; + + /* Whitelist of keys from: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/ */ + const char + allowed[PSDAllowedLength][PSDKeySize] = { + "blnc", "blwh", "brit", "brst", "clbl", "clrL", "curv", "expA", "FMsk", + "GdFl", "grdm", "hue ", "hue2", "infx", "knko", "lclr", "levl", "lnsr", + "lfx2", "luni", "lrFX", "lspf", "lyid", "lyvr", "mixr", "nvrt", "phfl", + "post", "PtFl", "selc", "shpa", "sn2P", "SoCo", "thrs", "tsly", "vibA" + }; + + const StringInfo + *info; + + MagickBooleanType + found; + + register size_t + i; + + size_t + remaining_length, + length; + + StringInfo + *profile; + + unsigned char + *p; + + unsigned int + size; + + info=GetImageProfile(image,PSDAdditionalInfo); + if (info == (const StringInfo *) NULL) + return((const StringInfo *) NULL); + length=GetStringInfoLength(info); + p=GetStringInfoDatum(info); + remaining_length=length; + length=0; + while (remaining_length >= 12) + { + /* skip over signature */ + p+=4; + key[0]=(*p++); + key[1]=(*p++); + key[2]=(*p++); + key[3]=(*p++); + key[4]='\0'; + size=(unsigned int) (*p++) << 24; + size|=(unsigned int) (*p++) << 16; + size|=(unsigned int) (*p++) << 8; + size|=(unsigned int) (*p++); + size=size & 0xffffffff; + remaining_length-=12; + if ((size_t) size > remaining_length) + return((const StringInfo *) NULL); + found=MagickFalse; + for (i=0; i < PSDAllowedLength; i++) + { + if (LocaleNCompare(key,allowed[i],PSDKeySize) != 0) + continue; + + found=MagickTrue; + break; + } + remaining_length-=(size_t) size; + if (found == MagickFalse) + { + if (remaining_length > 0) + p=(unsigned char *) CopyMagickMemory(p-12,p+size,remaining_length); + continue; + } + length+=(size_t) size+12; + p+=size; + } + profile=RemoveImageProfile(image,PSDAdditionalInfo); + if (length == 0) + return(DestroyStringInfo(profile)); + SetStringInfoLength(profile,(const size_t) length); + SetImageProfile(image,PSDAdditionalInfo,info,exception); + return(profile); +} + static MagickBooleanType WritePSDImage(const ImageInfo *image_info, Image *image,ExceptionInfo *exception) { + char + layer_name[MagickPathExtent]; + const char *property; const StringInfo - *icc_profile; + *icc_profile, + *info; Image *base_image, @@ -2662,6 +2776,7 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info, layer_count, layer_info_size, length, + name_length, num_channels, packet_size, rounded_layer_info_size; @@ -2840,6 +2955,9 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info, layer_length=strlen(property); layer_info_size+=8+layer_length+(4-(layer_length % 4)); } + info=FilterAdditionalLayerInformation(next_image,exception); + if (info != (const StringInfo *) NULL) + layer_info_size+=GetStringInfoLength(info); layer_count++; next_image=GetNextImageInList(next_image); } @@ -2931,31 +3049,24 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info, (void) WriteBlobByte(image,next_image->compose==NoCompositeOp ? 1 << 0x02 : 1); /* layer properties - visible, etc. */ (void) WriteBlobByte(image,0); + info=GetImageProfile(next_image,PSDAdditionalInfo); property=(const char *) GetImageProperty(next_image,"label",exception); if (property == (const char *) NULL) { - char - layer_name[MagickPathExtent]; - - (void) WriteBlobMSBLong(image,16); - (void) WriteBlobMSBLong(image,0); - (void) WriteBlobMSBLong(image,0); - (void) FormatLocaleString(layer_name,MagickPathExtent,"L%04ld",(long) - layer_count++); - WritePascalString(image,layer_name,4); - } - else - { - size_t - label_length; - - label_length=strlen(property); - (void) WriteBlobMSBLong(image,(unsigned int) (label_length+(4- - (label_length % 4))+8)); - (void) WriteBlobMSBLong(image,0); - (void) WriteBlobMSBLong(image,0); - WritePascalString(image,property,4); + (void) FormatLocaleString(layer_name,MagickPathExtent,"L%.20g", + (double) layer_count++); + property=layer_name; } + name_length=strlen(property); + name_length+=(4-(name_length % 4)); + if (info != (const StringInfo *) NULL) + name_length+=GetStringInfoLength(info); + (void) WriteBlobMSBLong(image,(unsigned int)name_length+8); + (void) WriteBlobMSBLong(image,0); + (void) WriteBlobMSBLong(image,0); + WritePascalString(image,property,4); + if (info != (const StringInfo *) NULL) + (void) WriteBlob(image,GetStringInfoLength(info),GetStringInfoDatum(info)); next_image=GetNextImageInList(next_image); } /*