% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
-% https://www.imagemagick.org/script/license.php %
+% https://imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
+% Photoshop spec @ https://www.adobe.com/devnet-apps/photoshop/fileformatashtml
%
*/
\f
return(MagickFalse);
}
+static void AttachPSDLayers(Image *image,LayerInfo *layer_info,
+ ssize_t number_layers)
+{
+ register ssize_t
+ i;
+
+ ssize_t
+ j;
+
+ for (i=0; i < number_layers; i++)
+ {
+ if (layer_info[i].image == (Image *) NULL)
+ {
+ for (j=i; j < number_layers - 1; j++)
+ layer_info[j] = layer_info[j+1];
+ number_layers--;
+ i--;
+ }
+ }
+ if (number_layers == 0)
+ {
+ layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
+ return;
+ }
+ for (i=0; i < number_layers; i++)
+ {
+ if (i > 0)
+ layer_info[i].image->previous=layer_info[i-1].image;
+ if (i < (number_layers-1))
+ layer_info[i].image->next=layer_info[i+1].image;
+ layer_info[i].image->page=layer_info[i].page;
+ }
+ image->next=layer_info[0].image;
+ layer_info[0].image->previous=image;
+ layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
+}
+
+static inline MagickBooleanType PSDSkipImage(const ImageInfo *image_info,
+ const size_t index)
+{
+ if (image_info->number_scenes == 0)
+ return(MagickFalse);
+ if (index < image_info->scene)
+ return(MagickTrue);
+ if (index > image_info->scene+image_info->number_scenes-1)
+ return(MagickTrue);
+ return(MagickFalse);
+}
+
static MagickBooleanType ReadPSDLayersInternal(Image *image,
const ImageInfo *image_info,const PSDInfo *psd_info,
const MagickBooleanType skip_layers,ExceptionInfo *exception)
return(MagickTrue);
}
}
- status=MagickTrue;
- if (size != 0)
- {
- layer_info=(LayerInfo *) NULL;
- number_layers=(ssize_t) ReadBlobSignedShort(image);
+ if (size == 0)
+ return(MagickTrue);
- if (number_layers < 0)
- {
- /*
- The first alpha channel in the merged result contains the
- transparency data for the merged result.
- */
- number_layers=MagickAbsoluteValue(number_layers);
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " negative layer count corrected for");
- image->alpha_trait=BlendPixelTrait;
- }
+ layer_info=(LayerInfo *) NULL;
+ number_layers=(ssize_t) ReadBlobSignedShort(image);
+ if (number_layers < 0)
+ {
/*
- We only need to know if the image has an alpha channel
+ The first alpha channel in the merged result contains the
+ transparency data for the merged result.
*/
- if (skip_layers != MagickFalse)
- return(MagickTrue);
+ number_layers=MagickAbsoluteValue(number_layers);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " negative layer count corrected for");
+ image->alpha_trait=BlendPixelTrait;
+ }
+ /*
+ We only need to know if the image has an alpha channel
+ */
+ if (skip_layers != MagickFalse)
+ return(MagickTrue);
+
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " image contains %.20g layers",(double) number_layers);
+
+ if (number_layers == 0)
+ ThrowBinaryException(CorruptImageError,"InvalidNumberOfLayers",
+ image->filename);
+
+ layer_info=(LayerInfo *) AcquireQuantumMemory((size_t) number_layers,
+ sizeof(*layer_info));
+ if (layer_info == (LayerInfo *) NULL)
+ {
if (image->debug != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " image contains %.20g layers",(double) number_layers);
+ " allocation of LayerInfo failed");
+ ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
+ image->filename);
+ }
+ (void) memset(layer_info,0,(size_t) number_layers*sizeof(*layer_info));
- if (number_layers == 0)
- ThrowBinaryException(CorruptImageError,"InvalidNumberOfLayers",
- image->filename);
+ for (i=0; i < number_layers; i++)
+ {
+ ssize_t
+ x,
+ y;
- layer_info=(LayerInfo *) AcquireQuantumMemory((size_t) number_layers,
- sizeof(*layer_info));
- if (layer_info == (LayerInfo *) NULL)
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " reading layer #%.20g",(double) i+1);
+ layer_info[i].page.y=(ssize_t) ReadBlobSignedLong(image);
+ layer_info[i].page.x=(ssize_t) ReadBlobSignedLong(image);
+ y=(ssize_t) ReadBlobSignedLong(image);
+ x=(ssize_t) ReadBlobSignedLong(image);
+ layer_info[i].page.width=(size_t) (x-layer_info[i].page.x);
+ layer_info[i].page.height=(size_t) (y-layer_info[i].page.y);
+ layer_info[i].channels=ReadBlobShort(image);
+ if (layer_info[i].channels > MaxPSDChannels)
+ {
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
+ ThrowBinaryException(CorruptImageError,"MaximumChannelsExceeded",
+ image->filename);
+ }
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " offset(%.20g,%.20g), size(%.20g,%.20g), channels=%.20g",
+ (double) layer_info[i].page.x,(double) layer_info[i].page.y,
+ (double) layer_info[i].page.height,(double)
+ layer_info[i].page.width,(double) layer_info[i].channels);
+ for (j=0; j < (ssize_t) layer_info[i].channels; j++)
+ {
+ layer_info[i].channel_info[j].type=(short) ReadBlobShort(image);
+ if ((layer_info[i].channel_info[j].type < -4) ||
+ (layer_info[i].channel_info[j].type > 4))
{
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " allocation of LayerInfo failed");
- ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
+ ThrowBinaryException(CorruptImageError,"NoSuchImageChannel",
image->filename);
}
- (void) memset(layer_info,0,(size_t) number_layers*sizeof(*layer_info));
-
- for (i=0; i < number_layers; i++)
+ layer_info[i].channel_info[j].size=(size_t) GetPSDSize(psd_info,
+ image);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " channel[%.20g]: type=%.20g, size=%.20g",(double) j,
+ (double) layer_info[i].channel_info[j].type,
+ (double) layer_info[i].channel_info[j].size);
+ }
+ if (CheckPSDChannels(psd_info,&layer_info[i]) == MagickFalse)
+ {
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
+ ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
+ image->filename);
+ }
+ count=ReadBlob(image,4,(unsigned char *) type);
+ if (count == 4)
+ ReversePSDString(image,type,4);
+ if ((count != 4) || (LocaleNCompare(type,"8BIM",4) != 0))
{
- ssize_t
- x,
- y;
-
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " reading layer #%.20g",(double) i+1);
- layer_info[i].page.y=(ssize_t) ReadBlobSignedLong(image);
- layer_info[i].page.x=(ssize_t) ReadBlobSignedLong(image);
- y=(ssize_t) ReadBlobSignedLong(image);
- x=(ssize_t) ReadBlobSignedLong(image);
- layer_info[i].page.width=(size_t) (x-layer_info[i].page.x);
- layer_info[i].page.height=(size_t) (y-layer_info[i].page.y);
- layer_info[i].channels=ReadBlobShort(image);
- if (layer_info[i].channels > MaxPSDChannels)
- {
- layer_info=DestroyLayerInfo(layer_info,number_layers);
- ThrowBinaryException(CorruptImageError,"MaximumChannelsExceeded",
- image->filename);
- }
if (image->debug != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " offset(%.20g,%.20g), size(%.20g,%.20g), channels=%.20g",
- (double) layer_info[i].page.x,(double) layer_info[i].page.y,
- (double) layer_info[i].page.height,(double)
- layer_info[i].page.width,(double) layer_info[i].channels);
- for (j=0; j < (ssize_t) layer_info[i].channels; j++)
- {
- layer_info[i].channel_info[j].type=(short) ReadBlobShort(image);
- if ((layer_info[i].channel_info[j].type < -4) ||
- (layer_info[i].channel_info[j].type > 4))
- {
- layer_info=DestroyLayerInfo(layer_info,number_layers);
- ThrowBinaryException(CorruptImageError,"NoSuchImageChannel",
- image->filename);
- }
- layer_info[i].channel_info[j].size=(size_t) GetPSDSize(psd_info,
- image);
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " channel[%.20g]: type=%.20g, size=%.20g",(double) j,
- (double) layer_info[i].channel_info[j].type,
- (double) layer_info[i].channel_info[j].size);
- }
- if (CheckPSDChannels(psd_info,&layer_info[i]) == MagickFalse)
- {
- layer_info=DestroyLayerInfo(layer_info,number_layers);
- ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
- image->filename);
- }
- count=ReadBlob(image,4,(unsigned char *) type);
- if (count == 4)
- ReversePSDString(image,type,4);
- if ((count != 4) || (LocaleNCompare(type,"8BIM",4) != 0))
- {
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " layer type was %.4s instead of 8BIM", type);
- layer_info=DestroyLayerInfo(layer_info,number_layers);
- ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
- image->filename);
- }
- count=ReadBlob(image,4,(unsigned char *) layer_info[i].blendkey);
- if (count != 4)
- {
- layer_info=DestroyLayerInfo(layer_info,number_layers);
- ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
- image->filename);
- }
- ReversePSDString(image,layer_info[i].blendkey,4);
- layer_info[i].opacity=(Quantum) ScaleCharToQuantum((unsigned char)
- ReadBlobByte(image));
- layer_info[i].clipping=(unsigned char) ReadBlobByte(image);
- layer_info[i].flags=(unsigned char) ReadBlobByte(image);
- layer_info[i].visible=!(layer_info[i].flags & 0x02);
+ " layer type was %.4s instead of 8BIM", type);
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
+ ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
+ image->filename);
+ }
+ count=ReadBlob(image,4,(unsigned char *) layer_info[i].blendkey);
+ if (count != 4)
+ {
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
+ ThrowBinaryException(CorruptImageError,"ImproperImageHeader",
+ image->filename);
+ }
+ ReversePSDString(image,layer_info[i].blendkey,4);
+ layer_info[i].opacity=(Quantum) ScaleCharToQuantum((unsigned char)
+ ReadBlobByte(image));
+ layer_info[i].clipping=(unsigned char) ReadBlobByte(image);
+ layer_info[i].flags=(unsigned char) ReadBlobByte(image);
+ layer_info[i].visible=!(layer_info[i].flags & 0x02);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " blend=%.4s, opacity=%.20g, clipping=%s, flags=%d, visible=%s",
+ layer_info[i].blendkey,(double) layer_info[i].opacity,
+ layer_info[i].clipping ? "true" : "false",layer_info[i].flags,
+ layer_info[i].visible ? "true" : "false");
+ (void) ReadBlobByte(image); /* filler */
+
+ size=ReadBlobLong(image);
+ if (size != 0)
+ {
+ MagickSizeType
+ combined_length,
+ length;
+
if (image->debug != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " blend=%.4s, opacity=%.20g, clipping=%s, flags=%d, visible=%s",
- layer_info[i].blendkey,(double) layer_info[i].opacity,
- layer_info[i].clipping ? "true" : "false",layer_info[i].flags,
- layer_info[i].visible ? "true" : "false");
- (void) ReadBlobByte(image); /* filler */
-
- size=ReadBlobLong(image);
- if (size != 0)
+ " layer contains additional info");
+ length=ReadBlobLong(image);
+ combined_length=length+4;
+ if (length != 0)
{
- MagickSizeType
- combined_length,
- length;
-
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " layer contains additional info");
- length=ReadBlobLong(image);
- combined_length=length+4;
- if (length != 0)
- {
- /*
- Layer mask info.
- */
- layer_info[i].mask.page.y=(ssize_t) ReadBlobSignedLong(image);
- layer_info[i].mask.page.x=(ssize_t) ReadBlobSignedLong(image);
- layer_info[i].mask.page.height=(size_t)
- (ReadBlobSignedLong(image)-layer_info[i].mask.page.y);
- layer_info[i].mask.page.width=(size_t) (
- ReadBlobSignedLong(image)-layer_info[i].mask.page.x);
- layer_info[i].mask.background=(unsigned char) ReadBlobByte(
- image);
- layer_info[i].mask.flags=(unsigned char) ReadBlobByte(image);
- if (!(layer_info[i].mask.flags & 0x01))
- {
- layer_info[i].mask.page.y=layer_info[i].mask.page.y-
- layer_info[i].page.y;
- layer_info[i].mask.page.x=layer_info[i].mask.page.x-
- layer_info[i].page.x;
- }
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " layer mask: offset(%.20g,%.20g), size(%.20g,%.20g), length=%.20g",
- (double) layer_info[i].mask.page.x,(double)
- layer_info[i].mask.page.y,(double)
- layer_info[i].mask.page.width,(double)
- layer_info[i].mask.page.height,(double) ((MagickOffsetType)
- length)-18);
- /*
- Skip over the rest of the layer mask information.
- */
- if (DiscardBlobBytes(image,(MagickSizeType) (length-18)) == MagickFalse)
- {
- layer_info=DestroyLayerInfo(layer_info,number_layers);
- ThrowBinaryException(CorruptImageError,
- "UnexpectedEndOfFile",image->filename);
- }
- }
- length=ReadBlobLong(image);
- combined_length+=length+4;
- if (length != 0)
- {
- /*
- Layer blending ranges info.
- */
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " layer blending ranges: length=%.20g",(double)
- ((MagickOffsetType) length));
- if (DiscardBlobBytes(image,length) == MagickFalse)
- {
- layer_info=DestroyLayerInfo(layer_info,number_layers);
- ThrowBinaryException(CorruptImageError,
- "UnexpectedEndOfFile",image->filename);
- }
- }
/*
- Layer name.
+ Layer mask info.
*/
- length=(MagickSizeType) (unsigned char) ReadBlobByte(image);
- combined_length+=length+1;
- if (length > 0)
- (void) ReadBlob(image,(size_t) length++,layer_info[i].name);
- layer_info[i].name[length]='\0';
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " layer name: %s",layer_info[i].name);
- if ((length % 4) != 0)
+ layer_info[i].mask.page.y=(ssize_t) ReadBlobSignedLong(image);
+ layer_info[i].mask.page.x=(ssize_t) ReadBlobSignedLong(image);
+ layer_info[i].mask.page.height=(size_t)
+ (ReadBlobSignedLong(image)-layer_info[i].mask.page.y);
+ layer_info[i].mask.page.width=(size_t) (
+ ReadBlobSignedLong(image)-layer_info[i].mask.page.x);
+ layer_info[i].mask.background=(unsigned char) ReadBlobByte(
+ image);
+ layer_info[i].mask.flags=(unsigned char) ReadBlobByte(image);
+ if (!(layer_info[i].mask.flags & 0x01))
{
- length=4-(length % 4);
- 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);
- }
+ layer_info[i].mask.page.y=layer_info[i].mask.page.y-
+ layer_info[i].page.y;
+ layer_info[i].mask.page.x=layer_info[i].mask.page.x-
+ layer_info[i].page.x;
}
- length=(MagickSizeType) size-combined_length;
- if (length > 0)
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " layer mask: offset(%.20g,%.20g), size(%.20g,%.20g), length=%.20g",
+ (double) layer_info[i].mask.page.x,(double)
+ layer_info[i].mask.page.y,(double)
+ layer_info[i].mask.page.width,(double)
+ layer_info[i].mask.page.height,(double) ((MagickOffsetType)
+ length)-18);
+ /*
+ Skip over the rest of the layer mask information.
+ */
+ if (DiscardBlobBytes(image,(MagickSizeType) (length-18)) == MagickFalse)
{
- unsigned char
- *info;
-
- if (length > GetBlobSize(image))
- {
- layer_info=DestroyLayerInfo(layer_info,number_layers);
- ThrowBinaryException(CorruptImageError,
- "InsufficientImageDataInFile",image->filename);
- }
- layer_info[i].info=AcquireStringInfo((const size_t) length);
- info=GetStringInfoDatum(layer_info[i].info);
- (void) ReadBlob(image,(const size_t) length,info);
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
+ ThrowBinaryException(CorruptImageError,
+ "UnexpectedEndOfFile",image->filename);
}
}
- }
-
- for (i=0; i < number_layers; i++)
- {
- if ((layer_info[i].page.width == 0) || (layer_info[i].page.height == 0))
+ length=ReadBlobLong(image);
+ combined_length+=length+4;
+ if (length != 0)
{
+ /*
+ Layer blending ranges info.
+ */
if (image->debug != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " layer data is empty");
- if (layer_info[i].info != (StringInfo *) NULL)
- layer_info[i].info=DestroyStringInfo(layer_info[i].info);
- continue;
+ " layer blending ranges: length=%.20g",(double)
+ ((MagickOffsetType) length));
+ if (DiscardBlobBytes(image,length) == MagickFalse)
+ {
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
+ ThrowBinaryException(CorruptImageError,
+ "UnexpectedEndOfFile",image->filename);
+ }
}
-
/*
- Allocate layered image.
+ Layer name.
*/
- layer_info[i].image=CloneImage(image,layer_info[i].page.width,
- layer_info[i].page.height,MagickFalse,exception);
- if (layer_info[i].image == (Image *) NULL)
- {
- layer_info=DestroyLayerInfo(layer_info,number_layers);
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " allocation of image for layer %.20g failed",(double) i);
- ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
- image->filename);
- }
- if (layer_info[i].info != (StringInfo *) NULL)
- {
- (void) SetImageProfile(layer_info[i].image,"psd:additional-info",
- layer_info[i].info,exception);
- layer_info[i].info=DestroyStringInfo(layer_info[i].info);
- }
- }
-
- if (image_info->ping == MagickFalse)
- {
- for (i=0; i < number_layers; i++)
+ length=(MagickSizeType) (unsigned char) ReadBlobByte(image);
+ combined_length+=length+1;
+ if (length > 0)
+ (void) ReadBlob(image,(size_t) length++,layer_info[i].name);
+ layer_info[i].name[length]='\0';
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " layer name: %s",layer_info[i].name);
+ if ((length % 4) != 0)
{
- if (layer_info[i].image == (Image *) NULL)
+ length=4-(length % 4);
+ combined_length+=length;
+ /* Skip over the padding of the layer name */
+ if (DiscardBlobBytes(image,length) == MagickFalse)
{
- for (j=0; j < (ssize_t) layer_info[i].channels; j++)
- {
- if (DiscardBlobBytes(image,(MagickSizeType)
- layer_info[i].channel_info[j].size) == MagickFalse)
- {
- layer_info=DestroyLayerInfo(layer_info,number_layers);
- ThrowBinaryException(CorruptImageError,
- "UnexpectedEndOfFile",image->filename);
- }
- }
- continue;
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
+ ThrowBinaryException(CorruptImageError,
+ "UnexpectedEndOfFile",image->filename);
}
-
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " reading data for layer %.20g",(double) i);
-
- status=ReadPSDLayer(image,image_info,psd_info,&layer_info[i],
- exception);
- if (status == MagickFalse)
- break;
-
- status=SetImageProgress(image,LoadImagesTag,(MagickOffsetType) i,
- (MagickSizeType) number_layers);
- if (status == MagickFalse)
- break;
}
- }
-
- if (status != MagickFalse)
- {
- for (i=0; i < number_layers; i++)
+ length=(MagickSizeType) size-combined_length;
+ if (length > 0)
{
- if (layer_info[i].image == (Image *) NULL)
+ unsigned char
+ *info;
+
+ if (length > GetBlobSize(image))
{
- for (j=i; j < number_layers - 1; j++)
- layer_info[j] = layer_info[j+1];
- number_layers--;
- i--;
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
+ ThrowBinaryException(CorruptImageError,
+ "InsufficientImageDataInFile",image->filename);
}
+ layer_info[i].info=AcquireStringInfo((const size_t) length);
+ info=GetStringInfoDatum(layer_info[i].info);
+ (void) ReadBlob(image,(const size_t) length,info);
}
+ }
+ }
+
+ for (i=0; i < number_layers; i++)
+ {
+ if ((layer_info[i].page.width == 0) || (layer_info[i].page.height == 0))
+ {
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " layer data is empty");
+ if (layer_info[i].info != (StringInfo *) NULL)
+ layer_info[i].info=DestroyStringInfo(layer_info[i].info);
+ continue;
+ }
- if (number_layers > 0)
+ /*
+ Allocate layered image.
+ */
+ layer_info[i].image=CloneImage(image,layer_info[i].page.width,
+ layer_info[i].page.height,MagickFalse,exception);
+ if (layer_info[i].image == (Image *) NULL)
+ {
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " allocation of image for layer %.20g failed",(double) i);
+ ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
+ image->filename);
+ }
+ if (layer_info[i].info != (StringInfo *) NULL)
+ {
+ (void) SetImageProfile(layer_info[i].image,"psd:additional-info",
+ layer_info[i].info,exception);
+ layer_info[i].info=DestroyStringInfo(layer_info[i].info);
+ }
+ }
+ if (image_info->ping != MagickFalse)
+ {
+ AttachPSDLayers(image,layer_info,number_layers);
+ return(MagickTrue);
+ }
+ status=MagickTrue;
+ for (i=0; i < number_layers; i++)
+ {
+ if ((layer_info[i].image == (Image *) NULL) ||
+ (PSDSkipImage(image_info,i) != MagickFalse))
+ {
+ for (j=0; j < (ssize_t) layer_info[i].channels; j++)
+ {
+ if (DiscardBlobBytes(image,(MagickSizeType)
+ layer_info[i].channel_info[j].size) == MagickFalse)
{
- for (i=0; i < number_layers; i++)
- {
- if (i > 0)
- layer_info[i].image->previous=layer_info[i-1].image;
- if (i < (number_layers-1))
- layer_info[i].image->next=layer_info[i+1].image;
- layer_info[i].image->page=layer_info[i].page;
- }
- image->next=layer_info[0].image;
- layer_info[0].image->previous=image;
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
+ ThrowBinaryException(CorruptImageError,
+ "UnexpectedEndOfFile",image->filename);
}
- layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
}
- else
- layer_info=DestroyLayerInfo(layer_info,number_layers);
- }
+ continue;
+ }
+
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " reading data for layer %.20g",(double) i);
+
+ status=ReadPSDLayer(image,image_info,psd_info,&layer_info[i],
+ exception);
+ if (status == MagickFalse)
+ break;
+
+ status=SetImageProgress(image,LoadImagesTag,(MagickOffsetType) i,
+ (MagickSizeType) number_layers);
+ if (status == MagickFalse)
+ break;
+ }
+
+ if (status != MagickFalse)
+ AttachPSDLayers(image,layer_info,number_layers);
+ else
+ layer_info=DestroyLayerInfo(layer_info,number_layers);
return(status);
}
register ssize_t
i;
+ if ((image_info->number_scenes != 0) && (image_info->scene != 0))
+ return(MagickTrue);
compression=(PSDCompressionType) ReadBlobMSBShort(image);
image->compression=ConvertPSDCompression(compression);
{
psd_info.min_channels=4;
(void) SetImageColorspace(image,CMYKColorspace,exception);
- if (psd_info.channels > 4)
- (void) SetImageAlphaChannel(image,ActivateAlphaChannel,exception);
}
else if ((psd_info.mode == BitmapMode) || (psd_info.mode == GrayscaleMode) ||
(psd_info.mode == DuotoneMode))
}
psd_info.min_channels=1;
(void) SetImageColorspace(image,GRAYColorspace,exception);
- if (psd_info.channels > 1)
- (void) SetImageAlphaChannel(image,ActivateAlphaChannel,exception);
}
- else
- if (psd_info.channels > 3)
- (void) SetImageAlphaChannel(image,ActivateAlphaChannel,exception);
if (psd_info.channels < psd_info.min_channels)
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
/*
}
if (profile != (StringInfo *) NULL)
{
- (void) SetImageProfile(image,GetStringInfoName(profile),profile,
- exception);
+ Image
+ *next;
+
+ i=0;
+ next=image;
+ while (next != (Image *) NULL)
+ {
+ if (PSDSkipImage(image_info,i++) == MagickFalse)
+ (void) SetImageProfile(next,GetStringInfoName(profile),profile,
+ exception);
+ next=next->next;
+ }
profile=DestroyStringInfo(profile);
}
(void) CloseBlob(image);