*/
#define MaxPSDChannels 56
#define PSDQuantum(x) (((ssize_t) (x)+1) & -2)
+#define PSDAdditionalInfo "PSDInfo"
\f
/*
Enumerated declaractions.
unsigned short
channels;
+
+ StringInfo
+ *info;
} LayerInfo;
/*
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);
/*
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);
/*
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);
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);
+ }
}
}
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)
}
}
+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,
layer_count,
layer_info_size,
length,
+ name_length,
num_channels,
packet_size,
rounded_layer_info_size;
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);
}
(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);
}
/*