X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=coders%2Fpsd.c;h=4c89e28ed6b46d964f392f2a70c287a9dca2d1a9;hb=3d9f5ba107b160e1819bb6baeeb3a9f521e9f450;hp=6b9d8fe6e8232a123667edc52ade711494f77137;hpb=8889c64483ea638b8d5715436e3114c1615c3571;p=imagemagick diff --git a/coders/psd.c b/coders/psd.c index 6b9d8fe6e..4c89e28ed 100644 --- a/coders/psd.c +++ b/coders/psd.c @@ -18,7 +18,7 @@ % July 1992 % % % % % -% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization % +% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % % dedicated to making software imaging solutions freely available. % % % % You may not use this file except in compliance with the License. You may % @@ -40,30 +40,34 @@ /* Include declarations. */ -#include "magick/studio.h" -#include "magick/artifact.h" -#include "magick/blob.h" -#include "magick/blob-private.h" -#include "magick/cache.h" -#include "magick/colormap.h" -#include "magick/colorspace.h" -#include "magick/constitute.h" -#include "magick/enhance.h" -#include "magick/exception.h" -#include "magick/exception-private.h" -#include "magick/image.h" -#include "magick/image-private.h" -#include "magick/list.h" -#include "magick/log.h" -#include "magick/magick.h" -#include "magick/memory_.h" -#include "magick/module.h" -#include "magick/monitor-private.h" -#include "magick/profile.h" -#include "magick/property.h" -#include "magick/quantum-private.h" -#include "magick/static.h" -#include "magick/string_.h" +#include "MagickCore/studio.h" +#include "MagickCore/artifact.h" +#include "MagickCore/attribute.h" +#include "MagickCore/blob.h" +#include "MagickCore/blob-private.h" +#include "MagickCore/cache.h" +#include "MagickCore/colormap.h" +#include "MagickCore/colorspace.h" +#include "MagickCore/colorspace-private.h" +#include "MagickCore/constitute.h" +#include "MagickCore/enhance.h" +#include "MagickCore/exception.h" +#include "MagickCore/exception-private.h" +#include "MagickCore/image.h" +#include "MagickCore/image-private.h" +#include "MagickCore/list.h" +#include "MagickCore/log.h" +#include "MagickCore/magick.h" +#include "MagickCore/memory_.h" +#include "MagickCore/module.h" +#include "MagickCore/monitor-private.h" +#include "MagickCore/pixel.h" +#include "MagickCore/pixel-accessor.h" +#include "MagickCore/profile.h" +#include "MagickCore/property.h" +#include "MagickCore/quantum-private.h" +#include "MagickCore/static.h" +#include "MagickCore/string_.h" /* Define declaractions. @@ -139,6 +143,7 @@ typedef struct _PSDInfo unsigned short channels, + color_channels, version; unsigned char @@ -157,7 +162,7 @@ typedef struct _PSDInfo Forward declarations. */ static MagickBooleanType - WritePSDImage(const ImageInfo *,Image *); + WritePSDImage(const ImageInfo *,Image *,ExceptionInfo *); /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -256,12 +261,12 @@ static ssize_t DecodePSDPixels(const size_t number_compact_pixels, i, j; - ssize_t - packets; - size_t length; + ssize_t + packets; + packets=(ssize_t) number_compact_pixels; for (i=0; (packets > 1) && (i < (ssize_t) number_pixels); ) { @@ -402,7 +407,7 @@ static const char *ModeToString(PSDImageType type) } static MagickBooleanType ParseImageResourceBlocks(Image *image, - const unsigned char *blocks,size_t length) + const unsigned char *blocks,size_t length,ExceptionInfo *exception) { const unsigned char *p; @@ -420,9 +425,9 @@ static MagickBooleanType ParseImageResourceBlocks(Image *image, if (length < 16) return(MagickFalse); - profile=AcquireStringInfo(length); + profile=BlobToStringInfo((const void *) NULL,length); SetStringInfoDatum(profile,blocks); - (void) SetImageProfile(image,"8bim",profile); + (void) SetImageProfile(image,"8bim",profile,exception); profile=DestroyStringInfo(profile); for (p=blocks; (p >= blocks) && (p < (blocks+length-16)); ) { @@ -446,16 +451,16 @@ static MagickBooleanType ParseImageResourceBlocks(Image *image, Resolution info. */ p=PushShortPixel(MSBEndian,p,&resolution); - image->x_resolution=(double) resolution; - (void) FormatMagickString(value,MaxTextExtent,"%g",image->x_resolution); - (void) SetImageProperty(image,"tiff:XResolution",value); + image->resolution.x=(double) resolution; + (void) FormatLocaleString(value,MaxTextExtent,"%g",image->resolution.x); + (void) SetImageProperty(image,"tiff:XResolution",value,exception); p=PushShortPixel(MSBEndian,p,&short_sans); p=PushShortPixel(MSBEndian,p,&short_sans); p=PushShortPixel(MSBEndian,p,&short_sans); p=PushShortPixel(MSBEndian,p,&resolution); - image->y_resolution=(double) resolution; - (void) FormatMagickString(value,MaxTextExtent,"%g",image->y_resolution); - (void) SetImageProperty(image,"tiff:YResolution",value); + image->resolution.y=(double) resolution; + (void) FormatLocaleString(value,MaxTextExtent,"%g",image->resolution.y); + (void) SetImageProperty(image,"tiff:YResolution",value,exception); p=PushShortPixel(MSBEndian,p,&short_sans); p=PushShortPixel(MSBEndian,p,&short_sans); p=PushShortPixel(MSBEndian,p,&short_sans); @@ -517,29 +522,27 @@ static CompositeOperator PSDBlendModeToCompositeOperator(const char *mode) static MagickBooleanType ReadPSDLayer(Image *image,const size_t channels, const ssize_t type,const MagickOffsetType *offsets,ExceptionInfo *exception) { - ssize_t - y; + ColorspaceType + colorspace; Quantum pixel; - register IndexPacket - *indexes; - - register ssize_t - x; + register const unsigned char + *p; - register PixelPacket + register Quantum *q; - register const unsigned char - *p; + register ssize_t + x; size_t packet_size; ssize_t - count; + count, + y; unsigned char *compact_pixels, @@ -583,24 +586,42 @@ static MagickBooleanType ReadPSDLayer(Image *image,const size_t channels, image->filename); (void) ResetMagickMemory(compact_pixels,0,length*sizeof(*compact_pixels)); } + colorspace=image->colorspace; for (y=0; y < (ssize_t) image->rows; y++) { - if (image->compression != RLECompression) - count=ReadBlob(image,packet_size*image->columns,pixels); + if (image->depth == 1) + { + if (image->compression != RLECompression) + count=ReadBlob(image,(image->columns+7)/8,pixels); + else + { + count=ReadBlob(image,(size_t) offsets[y],compact_pixels); + if (count != (ssize_t) offsets[y]) + break; + count=DecodePSDPixels((size_t) offsets[y],compact_pixels, + (ssize_t) 123456,(size_t) ((image->columns+7)/8),pixels); + } + if (count < (ssize_t) ((image->columns+7)/8)) + break; + } else { - count=ReadBlob(image,(size_t) offsets[y],compact_pixels); - if (count != (ssize_t) offsets[y]) + if (image->compression != RLECompression) + count=ReadBlob(image,packet_size*image->columns,pixels); + else + { + count=ReadBlob(image,(size_t) offsets[y],compact_pixels); + if (count != (ssize_t) offsets[y]) + break; + count=DecodePSDPixels((size_t) offsets[y],compact_pixels, + (ssize_t) image->depth,packet_size*image->columns,pixels); + } + if (count < (ssize_t) (packet_size*image->columns)) break; - count=DecodePSDPixels((size_t) offsets[y],compact_pixels, - (ssize_t) image->depth,packet_size*image->columns,pixels); } - if (count < (ssize_t) (packet_size*image->columns)) - break; q=GetAuthenticPixels(image,0,y,image->columns,1,exception); - if (q == (PixelPacket *) NULL) + if (q == (Quantum *) NULL) break; - indexes=GetAuthenticIndexQueue(image); p=pixels; for (x=0; x < (ssize_t) image->columns; x++) { @@ -615,64 +636,89 @@ static MagickBooleanType ReadPSDLayer(Image *image,const size_t channels, { case -1: { - q->opacity=(Quantum) (QuantumRange-pixel); + SetPixelAlpha(image,pixel,q); break; } case 0: { - q->red=pixel; + SetPixelRed(image,pixel,q); if (channels == 1) - { - q->green=q->red; - q->blue=q->red; - } + SetPixelGray(image,pixel,q); + else + SetPixelRed(image,pixel,q); if (image->storage_class == PseudoClass) { if (packet_size == 1) - indexes[x]=(IndexPacket) ScaleQuantumToChar(pixel); + SetPixelIndex(image,ScaleQuantumToChar(pixel),q); else - indexes[x]=(IndexPacket) ScaleQuantumToShort(pixel); - *q=image->colormap[(ssize_t) indexes[x]]; - q->red=image->colormap[(ssize_t) indexes[x]].red; - q->green=image->colormap[(ssize_t) indexes[x]].green; - q->blue=image->colormap[(ssize_t) indexes[x]].blue; + SetPixelIndex(image,ScaleQuantumToShort(pixel),q); + SetPixelInfoPixel(image,image->colormap+(ssize_t) + GetPixelIndex(image,q),q); + if (image->depth == 1) + { + ssize_t + bit, + number_bits; + + number_bits=image->columns-x; + if (number_bits > 8) + number_bits=8; + for (bit=0; bit < number_bits; bit++) + { + SetPixelIndex(image,(((unsigned char) pixel) & + (0x01 << (7-bit))) != 0 ? 0 : 255,q); + SetPixelInfoPixel(image,image->colormap+(ssize_t) + GetPixelIndex(image,q),q); + q+=GetPixelChannels(image); + x++; + } + } } break; } case 1: { if (image->storage_class == PseudoClass) - q->opacity=(Quantum) (QuantumRange-pixel); + SetPixelAlpha(image,pixel,q); else - q->green=pixel; + SetPixelGreen(image,pixel,q); break; } case 2: { - q->blue=pixel; + if (image->storage_class == PseudoClass) + SetPixelAlpha(image,pixel,q); + else + SetPixelBlue(image,pixel,q); break; } case 3: { if (image->colorspace == CMYKColorspace) - indexes[x]=(IndexPacket) pixel; + SetPixelBlack(image,pixel,q); else - q->opacity=(Quantum) (QuantumRange-pixel); + if (image->matte != MagickFalse) + SetPixelAlpha(image,pixel,q); break; } case 4: { - q->opacity=(Quantum) (QuantumRange-pixel); + if ((IssRGBCompatibleColorspace(image->colorspace) != MagickFalse) && + (channels > 3)) + break; + if (image->matte != MagickFalse) + SetPixelAlpha(image,pixel,q); break; } default: break; } - q++; + q+=GetPixelChannels(image); } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; } + image->colorspace=colorspace; if (image->compression == RLECompression) compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels); pixels=(unsigned char *) RelinquishMagickMemory(pixels); @@ -688,18 +734,11 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) Image *image; - IndexPacket - *indexes; - LayerInfo *layer_info; - ssize_t - j, - number_layers, - y; - MagickBooleanType + check_background, status; MagickOffsetType @@ -714,15 +753,22 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) PSDInfo psd_info; + register Quantum + *q; + register ssize_t i, x; - register PixelPacket - *q; + size_t + mask_size, + skip_first_alpha = 0; ssize_t - count; + count, + j, + number_layers, + y; unsigned char *data; @@ -730,10 +776,6 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) unsigned short compression; - size_t - mask_size, - skip_first_alpha = 0; - /* Open image file. */ @@ -744,7 +786,7 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); - image=AcquireImage(image_info); + image=AcquireImage(image_info,exception); status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); if (status == MagickFalse) { @@ -761,6 +803,7 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); count=ReadBlob(image,6,psd_info.reserved); psd_info.channels=ReadBlobMSBShort(image); + psd_info.color_channels=psd_info.channels; if (psd_info.channels > MaxPSDChannels) ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded"); psd_info.rows=ReadBlobMSBLong(image); @@ -774,44 +817,44 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) psd_info.mode=ReadBlobMSBShort(image); if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Image is %lu x %lu with channels=%lu, depth=%lu, mode=%s", - (unsigned long) psd_info.columns,(unsigned long) psd_info.rows, - (unsigned long) psd_info.channels,(unsigned long) psd_info.depth, - ModeToString((PSDImageType) psd_info.mode)); + " Image is %.20g x %.20g with channels=%.20g, depth=%.20g, mode=%s", + (double) psd_info.columns,(double) psd_info.rows,(double) + psd_info.channels,(double) psd_info.depth,ModeToString((PSDImageType) + psd_info.mode)); /* Initialize image. */ image->depth=psd_info.depth; image->columns=psd_info.columns; image->rows=psd_info.rows; - if (SetImageBackgroundColor(image) == MagickFalse) + if (SetImageBackgroundColor(image,exception) == MagickFalse) { - InheritException(exception,&image->exception); image=DestroyImageList(image); return((Image *) NULL); } image->matte=psd_info.channels >= 4 ? MagickTrue : MagickFalse; if (psd_info.mode == LabMode) - image->colorspace=LabColorspace; + SetImageColorspace(image,LabColorspace,exception); + psd_info.color_channels=3; if (psd_info.mode == CMYKMode) { - image->colorspace=CMYKColorspace; + psd_info.color_channels=4; + SetImageColorspace(image,CMYKColorspace,exception); image->matte=psd_info.channels >= 5 ? MagickTrue : MagickFalse; } if ((psd_info.mode == BitmapMode) || (psd_info.mode == GrayscaleMode) || (psd_info.mode == DuotoneMode)) { - if (AcquireImageColormap(image,256) == MagickFalse) + psd_info.color_channels=1; + if (AcquireImageColormap(image,256,exception) == MagickFalse) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); image->matte=psd_info.channels >= 2 ? MagickTrue : MagickFalse; if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " ImageColorMap allocated"); - image->colorspace=GRAYColorspace; + " Image colormap allocated"); + SetImageColorspace(image,GRAYColorspace,exception); } - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - image->matte ? " image has matte" : " image has no matte"); + image->matte=MagickFalse; /* Read PSD raster colormap only present for indexed and duotone images. */ @@ -838,7 +881,7 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) /* Read PSD raster colormap. */ - if (AcquireImageColormap(image,(size_t) (length/3)) == MagickFalse) + if (AcquireImageColormap(image,(size_t) (length/3),exception) == MagickFalse) ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); for (i=0; i < (ssize_t) image->colors; i++) image->colormap[i].red=ScaleCharToQuantum((unsigned char) @@ -849,7 +892,7 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) for (i=0; i < (ssize_t) image->colors; i++) image->colormap[i].blue=ScaleCharToQuantum((unsigned char) ReadBlobByte(image)); - image->matte=psd_info.channels >= 2 ? MagickTrue : MagickFalse; + image->matte=MagickFalse; } } length=ReadBlobMSBLong(image); @@ -863,7 +906,8 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) */ if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " reading image resource blocks - %lu bytes",(unsigned long) length); + " reading image resource blocks - %.20g bytes",(double) + ((MagickOffsetType) length)); blocks=(unsigned char *) AcquireQuantumMemory((size_t) length, sizeof(*blocks)); if (blocks == (unsigned char *) NULL) @@ -875,17 +919,10 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) blocks=(unsigned char *) RelinquishMagickMemory(blocks); ThrowReaderException(CorruptImageError,"ImproperImageHeader"); } - (void) ParseImageResourceBlocks(image,blocks,(size_t) length); + (void) ParseImageResourceBlocks(image,blocks,(size_t) length, + exception); blocks=(unsigned char *) RelinquishMagickMemory(blocks); } - /* - If we are only "pinging" the image, then we're done - so return. - */ - if (image_info->ping != MagickFalse) - { - (void) CloseBlob(image); - return(GetFirstImageInList(image)); - } /* Layer and mask block. */ @@ -897,14 +934,14 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) length=ReadBlobMSBLong(image); length=ReadBlobMSBLong(image); } + check_background=MagickFalse; if ((image_info->number_scenes == 1) && (image_info->scene == 0)) - for ( ; length != 0; length--) - if (ReadBlobByte(image) == EOF) - { - ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", - image->filename); - break; - } + { + if (image->debug != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " read composite only"); + check_background=MagickTrue; + } if (length == 0) { if (image->debug != MagickFalse) @@ -920,29 +957,56 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) size_t quantum; + unsigned long + tag; + /* Skip layers & masks. */ quantum=psd_info.version == 1 ? 4UL : 8UL; - for (j=0; j < (ssize_t) (length-quantum); j++) - (void) ReadBlobByte(image); + tag=ReadBlobMSBLong(image); + (void) tag; + count=ReadBlob(image,4,(unsigned char *) type); + if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0)) + { + if (DiscardBlobBytes(image,length-quantum-8) == MagickFalse) + ThrowFileException(exception,CorruptImageError, + "UnexpectedEndOfFile",image->filename); + } + else + { + count=ReadBlob(image,4,(unsigned char *) type); + if ((count != 0) && (LocaleNCompare(type,"Lr16",4) == 0)) + size=GetPSDSize(&psd_info,image); + else + if (DiscardBlobBytes(image,length-quantum-12) == MagickFalse) + ThrowFileException(exception,CorruptImageError, + "UnexpectedEndOfFile",image->filename); + } } - else + if (size != 0) { MagickOffsetType layer_offset; + image->matte=psd_info.channels > psd_info.color_channels ? MagickTrue : MagickFalse; + + if (image->debug != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + image->matte ? " image has matte" : " image has no matte"); + layer_offset=offset+length; number_layers=(short) ReadBlobMSBShort(image); if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " image contains %ld layers",(long) number_layers); + " image contains %.20g layers",(double) number_layers); if (number_layers < 0) { /* Weird hack in PSD format to ignore first alpha channel. */ skip_first_alpha=1; + (void) skip_first_alpha; number_layers=MagickAbsoluteValue(number_layers); if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), @@ -961,28 +1025,41 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) sizeof(*layer_info)); for (i=0; i < number_layers; i++) { + int + x, + y; + if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " reading layer #%ld",(long) i+1); - layer_info[i].page.y=(ssize_t) ReadBlobMSBLong(image); - layer_info[i].page.x=(ssize_t) ReadBlobMSBLong(image); - layer_info[i].page.height=(size_t) - (ReadBlobMSBLong(image)-layer_info[i].page.y); - layer_info[i].page.width=(size_t) - (ReadBlobMSBLong(image)-layer_info[i].page.x); - if (layer_info[i].page.height > 300000) - layer_info[i].page.height+=4294967295UL; - if (layer_info[i].page.width > 300000) - layer_info[i].page.width+=4294967295UL; + " reading layer #%.20g",(double) i+1); + layer_info[i].page.y=(int) ReadBlobMSBLong(image); + layer_info[i].page.x=(int) ReadBlobMSBLong(image); + y=(int) ReadBlobMSBLong(image); + x=(int) ReadBlobMSBLong(image); + layer_info[i].page.width=(ssize_t) (x-layer_info[i].page.x); + layer_info[i].page.height=(ssize_t) (y-layer_info[i].page.y); layer_info[i].channels=ReadBlobMSBShort(image); + if (check_background == MagickTrue) + { + size_t + quantum; + + if (layer_info[i].channels == psd_info.color_channels) + image->matte=MagickFalse; + quantum=psd_info.version == 1 ? 4UL : 8UL; + if (DiscardBlobBytes(image,length-20-quantum) == MagickFalse) + ThrowFileException(exception,CorruptImageError, + "UnexpectedEndOfFile",image->filename); + break; + } if (layer_info[i].channels > MaxPSDChannels) ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded"); if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " offset(%ld,%ld), size(%ld,%ld), channels=%ld", - (long) layer_info[i].page.x,(long) layer_info[i].page.y, - (long) layer_info[i].page.height,(long) - layer_info[i].page.width,(long) layer_info[i].channels); + " 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) @@ -991,9 +1068,9 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) GetPSDSize(&psd_info,image); if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " channel[%ld]: type=%ld, size=%ld",(long) j, - (long) layer_info[i].channel_info[j].type, - (long) layer_info[i].channel_info[j].size); + " channel[%.20g]: type=%.20g, size=%.20g",(double) j, + (double) layer_info[i].channel_info[j].type, + (double) layer_info[i].channel_info[j].size); } count=ReadBlob(image,4,(unsigned char *) type); if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0)) @@ -1004,15 +1081,15 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) ThrowReaderException(CorruptImageError,"ImproperImageHeader"); } count=ReadBlob(image,4,(unsigned char *) layer_info[i].blendkey); - layer_info[i].opacity=(Quantum) (QuantumRange-ScaleCharToQuantum( - (unsigned char) ReadBlobByte(image))); + 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=%lu, clipping=%s, flags=%d, visible=%s", - layer_info[i].blendkey,(long) layer_info[i].opacity, + " 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 */ @@ -1029,27 +1106,25 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) /* Layer mask info. */ - layer_info[i].mask.y=(ssize_t) ReadBlobMSBLong(image); - layer_info[i].mask.x=(ssize_t) ReadBlobMSBLong(image); + layer_info[i].mask.y=(int) ReadBlobMSBLong(image); + layer_info[i].mask.x=(int) ReadBlobMSBLong(image); layer_info[i].mask.height=(size_t) (ReadBlobMSBLong(image)-layer_info[i].mask.y); layer_info[i].mask.width=(size_t) (ReadBlobMSBLong(image)-layer_info[i].mask.x); - if (layer_info[i].mask.height > 300000) - layer_info[i].mask.height+=4294967295UL; - if (layer_info[i].mask.width > 300000) - layer_info[i].mask.width+=4294967295UL; if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " layer mask: offset(%ld,%ld), size(%ld,%ld), length=%ld", - (long) layer_info[i].mask.x,(long) layer_info[i].mask.y, - (long) layer_info[i].mask.width,(long) - layer_info[i].mask.height,(long) length-16); + " layer mask: offset(%.20g,%.20g), size(%.20g,%.20g), length=%.20g", + (double) layer_info[i].mask.x,(double) layer_info[i].mask.y, + (double) layer_info[i].mask.width,(double) + layer_info[i].mask.height,(double) + ((MagickOffsetType) length-16)); /* Skip over the rest of the layer mask information. */ - for (j=0; j < (ssize_t) (length-16); j++) - (void) ReadBlobByte(image); + if (DiscardBlobBytes(image,length-16) == MagickFalse) + ThrowFileException(exception,CorruptImageError, + "UnexpectedEndOfFile",image->filename); } combinedlength+=length+4; /* +4 for length */ length=ReadBlobMSBLong(image); @@ -1060,8 +1135,8 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) */ if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " layer blending ranges: length=%ld",(long) - length); + " layer blending ranges: length=%.20g",(double) + ((MagickOffsetType) length)); /* We read it, but don't use it... */ @@ -1093,14 +1168,13 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) Adjustment layers and other stuff... */ { - char alsig[4], - alkey[4]; + char alsig[4], alkey[4]; count=ReadBlob(image,4,alsig); if ((count == 0) || (LocaleNCompare(alsig,"8BIM",4) != 0)) { if (debug != MagickFalse) { - if (image->debug != MagickFalse) + if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule()," adjustment layer type was %.4s instead of 8BIM", alsig); } ThrowReaderException(CorruptImageError,"ImproperImageHeader"); @@ -1109,10 +1183,10 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) length=ReadBlobMSBLong(image); if (debug != MagickFalse) { - if (image->debug != MagickFalse) + if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " adjustment layer key: %.4s, data length=%ld", - alkey, length); + " adjustment layer key: %.4s, data length=%.20g", + alkey, (double) length); } if ( length ) { @@ -1129,219 +1203,226 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) */ if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " unsupported data: length=%ld",(long) - (size-combinedlength)); - for (j=0; j < (ssize_t) (size-combinedlength); j++) - (void) ReadBlobByte(image); + " unsupported data: length=%.20g",(double) + ((MagickOffsetType) (size-combinedlength))); + if (DiscardBlobBytes(image,size-combinedlength) == MagickFalse) + ThrowFileException(exception,CorruptImageError, + "UnexpectedEndOfFile",image->filename); } /* Allocate layered image. */ layer_info[i].image=CloneImage(image,layer_info[i].page.width, - layer_info[i].page.height,MagickFalse,&image->exception); + layer_info[i].page.height == ~0U ? 1 : layer_info[i].page.height, + MagickFalse,exception); if (layer_info[i].image == (Image *) NULL) { for (j=0; j < i; j++) layer_info[j].image=DestroyImage(layer_info[j].image); if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " allocation of image for layer %ld failed",(long) i); + " allocation of image for layer %.20g failed",(double) i); ThrowReaderException(ResourceLimitError, "MemoryAllocationFailed"); } if (image->debug != MagickFalse) (void) LogMagickEvent(CoderEvent,GetMagickModule(), " setting up new layer image"); - (void) SetImageBackgroundColor(layer_info[i].image); + if (image_info->ping != MagickFalse) + (void) SetImageBackgroundColor(layer_info[i].image,exception); layer_info[i].image->compose= PSDBlendModeToCompositeOperator(layer_info[i].blendkey); if (layer_info[i].visible == MagickFalse) layer_info[i].image->compose=NoCompositeOp; if (psd_info.mode == CMYKMode) - layer_info[i].image->colorspace=CMYKColorspace; + SetImageColorspace(layer_info[i].image,CMYKColorspace,exception); if ((psd_info.mode == BitmapMode) || (psd_info.mode == GrayscaleMode) || (psd_info.mode == DuotoneMode)) - layer_info[i].image->colorspace=GRAYColorspace; + SetImageColorspace(layer_info[i].image,GRAYColorspace,exception); for (j=0; j < (ssize_t) layer_info[i].channels; j++) if (layer_info[i].channel_info[j].type == -1) layer_info[i].image->matte=MagickTrue; /* Set up some hidden attributes for folks that need them. */ - (void) FormatMagickString(message,MaxTextExtent,"%ld", - (long) layer_info[i].page.x); + (void) FormatLocaleString(message,MaxTextExtent,"%.20gld", + (double) layer_info[i].page.x); (void) SetImageArtifact(layer_info[i].image,"psd:layer.x",message); - (void) FormatMagickString(message,MaxTextExtent,"%ld", - (long) layer_info[i].page.y); + (void) FormatLocaleString(message,MaxTextExtent,"%.20g", + (double) layer_info[i].page.y); (void) SetImageArtifact(layer_info[i].image,"psd:layer.y",message); - (void) FormatMagickString(message,MaxTextExtent,"%lu", - (unsigned long) layer_info[i].opacity); + (void) FormatLocaleString(message,MaxTextExtent,"%.20g", + (double) layer_info[i].opacity); (void) SetImageArtifact(layer_info[i].image,"psd:layer.opacity", message); (void) SetImageProperty(layer_info[i].image,"label",(char *) - layer_info[i].name); + layer_info[i].name,exception); } - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " reading image data for layers"); - /* - Read pixel data for each layer. - */ - for (i=0; i < number_layers; i++) - { - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " reading data for layer %ld",(long) i); - for (j=0; j < (ssize_t) layer_info[i].channels; j++) - { - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " reading data for channel %ld",(long) j); -#if 1 - if (layer_info[i].channel_info[j].size <= (2*layer_info[i].image->rows)) - { - ssize_t - k; - - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " layer data is empty"); - /* - A layer without data. - */ - for (k=0; k < (ssize_t) layer_info[i].channel_info[j].size; k++) - (void) ReadBlobByte(layer_info[i].image); - continue; - } + if (check_background == MagickFalse) + { + if (image->debug != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " reading image data for layers"); + /* + Read pixel data for each layer. + */ + for (i=0; i < number_layers; i++) + { + if (image->debug != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " reading data for layer %.20g",(double) i); + for (j=0; j < (ssize_t) layer_info[i].channels; j++) + { + if (image->debug != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " reading data for channel %.20g",(double) j); +#if 1 + if (layer_info[i].channel_info[j].size <= (2*layer_info[i].image->rows)) + { + ssize_t + k; + + if (image->debug != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " layer data is empty"); + /* + A layer without data. + */ + for (k=0; k < (ssize_t) layer_info[i].channel_info[j].size; k++) + (void) ReadBlobByte(layer_info[i].image); + continue; + } #endif - offsets=(MagickOffsetType *) NULL; - layer_info[i].image->compression=NoCompression; - compression=ReadBlobMSBShort(layer_info[i].image); - if ((layer_info[i].page.height != 0) && - (layer_info[i].page.width != 0)) + offsets=(MagickOffsetType *) NULL; + layer_info[i].image->compression=NoCompression; + compression=ReadBlobMSBShort(layer_info[i].image); + if ((layer_info[i].page.height != 0) && + (layer_info[i].page.width != 0)) + { + if (compression == 1) + { + /* + Read RLE compressed data. + */ + layer_info[i].image->compression=RLECompression; + if (image->debug != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " layer data is RLE compressed"); + offsets=(MagickOffsetType *) AcquireQuantumMemory( + layer_info[i].image->rows,sizeof(*offsets)); + if (offsets == (MagickOffsetType *) NULL) + ThrowReaderException(ResourceLimitError, + "MemoryAllocationFailed"); + for (y=0; y < (ssize_t) layer_info[i].image->rows; y++) + offsets[y]=GetPSDOffset(&psd_info, + layer_info[i].image); + } + status=ReadPSDLayer(layer_info[i].image, + layer_info[i].channels, + layer_info[i].channel_info[j].type,offsets,exception); + if (compression == 1) + offsets=(MagickOffsetType *) RelinquishMagickMemory( + offsets); + if (status == MagickFalse) + break; + } + } + if (layer_info[i].opacity != OpaqueAlpha) + { + /* + Correct for opacity level. + */ + for (y=0; y < (ssize_t) layer_info[i].image->rows; y++) + { + q=GetAuthenticPixels(layer_info[i].image,0,y, + layer_info[i].image->columns,1,exception); + if (q == (Quantum *) NULL) + break; + for (x=0; x < (ssize_t) layer_info[i].image->columns; x++) + { + SetPixelAlpha(layer_info[i].image,(Quantum) + (QuantumScale*(GetPixelAlpha(layer_info[i].image,q))* + layer_info[i].opacity),q); + q+=GetPixelChannels(layer_info[i].image); + } + if (SyncAuthenticPixels(layer_info[i].image,exception) == MagickFalse) + break; + } + } + if (layer_info[i].image->colorspace == CMYKColorspace) + (void) NegateImage(layer_info[i].image,MagickFalse,exception); + status=SetImageProgress(image,LoadImagesTag,i,(MagickSizeType) + number_layers); + if (status == MagickFalse) + break; + } + /* added by palf -> invisible group layer make layer of this group + invisible I consider that all layer with width and height null are + layer for group layer */ + { + short inside_layer = 0; + short layer_visible = 0; + for (i=number_layers-1; i >=0; i--) + { + if ((layer_info[i].page.width == 0) || + (layer_info[i].page.height == 0)) { - if (compression == 1) + if (inside_layer == 0) { - /* - Read RLE compressed data. - */ - layer_info[i].image->compression=RLECompression; - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " layer data is RLE compressed"); - offsets=(MagickOffsetType *) AcquireQuantumMemory( - layer_info[i].image->rows,sizeof(*offsets)); - if (offsets == (MagickOffsetType *) NULL) - ThrowReaderException(ResourceLimitError, - "MemoryAllocationFailed"); - for (y=0; y < (ssize_t) layer_info[i].image->rows; y++) - offsets[y]=GetPSDOffset(&psd_info,layer_info[i].image); + inside_layer=1; + layer_visible=(short int) layer_info[i].visible; + } + else + { + inside_layer = 0; } - status=ReadPSDLayer(layer_info[i].image, - layer_info[i].channels,layer_info[i].channel_info[j].type, - offsets,exception); - if (compression == 1) - offsets=(MagickOffsetType *) RelinquishMagickMemory( - offsets); - if (status == MagickFalse) - break; } - } - if (layer_info[i].opacity != OpaqueOpacity) - { - /* - Correct for opacity level. - */ - for (y=0; y < (ssize_t) layer_info[i].image->rows; y++) - { - q=GetAuthenticPixels(layer_info[i].image,0,y, - layer_info[i].image->columns,1,exception); - if (q == (PixelPacket *) NULL) - break; - indexes=GetAuthenticIndexQueue(layer_info[i].image); - for (x=0; x < (ssize_t) layer_info[i].image->columns; x++) + else + if ((inside_layer == 1) && (layer_visible == 0)) { - q->opacity=(Quantum) (QuantumRange-(Quantum) (QuantumScale* - ((QuantumRange-q->opacity)*(QuantumRange- - layer_info[i].opacity)))); - q++; + layer_info[i].visible=(unsigned char) layer_visible; + layer_info[i].image->compose=NoCompositeOp; } - if (SyncAuthenticPixels(layer_info[i].image,exception) == MagickFalse) - break; - } - } - if (layer_info[i].image->colorspace == CMYKColorspace) - (void) NegateImage(layer_info[i].image,MagickFalse); - status=SetImageProgress(image,LoadImagesTag,i,(MagickSizeType) - number_layers); - if (status == MagickFalse) - break; + } } - /* added by palf -> invisible group layer make layer of this group - invisible I consider that all layer with width and height null are - layer for group layer */ - { - short inside_layer = 0; - short layer_visible = 0; - for (i=number_layers-1; i >=0; i--) - { - if ((layer_info[i].page.width == 0) || - (layer_info[i].page.height == 0)) + /* added by palf -> suppression of empty layer */ + /* I consider that all layer with width and height null are layer for group layer */ + for (i=0; i < number_layers; i++) + { + if ((layer_info[i].page.width == 0) || + (layer_info[i].page.height == 0)) + { + if (layer_info[i].image != (Image *) NULL) + layer_info[i].image=DestroyImage(layer_info[i].image); + for (j=i; j < number_layers - 1; j++) + layer_info[j] = layer_info[j+1]; + number_layers--; + i--; + } + } + mask_size = ReadBlobMSBLong(image); /* global mask size: currently ignored */ + (void) mask_size; + if (number_layers > 0) { - if (inside_layer == 0) - { - inside_layer=1; - layer_visible=(short int) layer_info[i].visible; - } - else - { - inside_layer = 0; - } - } - else - if ((inside_layer == 1) && (layer_visible == 0)) + if (image->debug != MagickFalse) + (void) LogMagickEvent(CoderEvent,GetMagickModule(), + " putting layers into image list"); + for (i=0; i < number_layers; i++) { - layer_info[i].visible=(unsigned char) layer_visible; - layer_info[i].image->compose=NoCompositeOp; + 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); + } + layer_offset-=TellBlob(image); + offset=SeekBlob(image,layer_offset,SEEK_CUR); } - } - /* added by palf -> suppression of empty layer */ - /* I consider that all layer with width and height null are layer for group layer */ - for (i=0; i < number_layers; i++) - { - if ((layer_info[i].page.width == 0) || - (layer_info[i].page.height == 0)) - { - if (layer_info[i].image != (Image *) NULL) - layer_info[i].image=DestroyImage(layer_info[i].image); - for (j=i; j < number_layers - 1; j++) - layer_info[j] = layer_info[j+1]; - number_layers--; - i--; - } - } - mask_size = ReadBlobMSBLong(image); /* global mask size: currently ignored */ - if (number_layers > 0) - { - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " putting layers into image list"); - 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); - } - layer_offset-=TellBlob(image); - offset=SeekBlob(image,layer_offset,SEEK_CUR); } } /* @@ -1379,7 +1460,7 @@ static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception) if (compression == 1) offsets=(MagickOffsetType *) RelinquishMagickMemory(offsets); if (image->colorspace == CMYKColorspace) - (void) NegateImage(image,MagickFalse); + (void) NegateImage(image,MagickFalse,exception); (void) CloseBlob(image); return(GetFirstImageInList(image)); } @@ -1416,6 +1497,7 @@ ModuleExport size_t RegisterPSDImage(void) entry->decoder=(DecodeImageHandler *) ReadPSDImage; entry->encoder=(EncodeImageHandler *) WritePSDImage; entry->magick=(IsImageFormatHandler *) IsPSD; + entry->seekable_stream=MagickTrue; entry->description=ConstantString("Adobe Large Document Format"); entry->module=ConstantString("PSD"); (void) RegisterMagickInfo(entry); @@ -1423,6 +1505,7 @@ ModuleExport size_t RegisterPSDImage(void) entry->decoder=(DecodeImageHandler *) ReadPSDImage; entry->encoder=(EncodeImageHandler *) WritePSDImage; entry->magick=(IsImageFormatHandler *) IsPSD; + entry->seekable_stream=MagickTrue; entry->description=ConstantString("Adobe Photoshop bitmap"); entry->module=ConstantString("PSD"); (void) RegisterMagickInfo(entry); @@ -1469,7 +1552,8 @@ ModuleExport void UnregisterPSDImage(void) % % The format of the WritePSDImage method is: % -% MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image) +% MagickBooleanType WritePSDImage(const ImageInfo *image_info, +% Image *image,ExceptionInfo *exception) % % A description of each parameter follows. % @@ -1477,6 +1561,7 @@ ModuleExport void UnregisterPSDImage(void) % % o image: The image. % +% o exception: return any errors or warnings in this structure. % */ @@ -1497,7 +1582,8 @@ static inline ssize_t SetPSDSize(const PSDInfo *psd_info,Image *image, } static size_t PSDPackbitsEncodeImage(Image *image,const size_t length, - const unsigned char *pixels,unsigned char *compact_pixels) + const unsigned char *pixels,unsigned char *compact_pixels, + ExceptionInfo *exception) { int count; @@ -1606,44 +1692,50 @@ static size_t PSDPackbitsEncodeImage(Image *image,const size_t length, } static void WritePackbitsLength(const PSDInfo *psd_info, - const ImageInfo *image_info,Image *image,Image *tmp_image, - unsigned char *pixels,unsigned char *compact_pixels, - const QuantumType quantum_type) + const ImageInfo *image_info,Image *image,Image *next_image, + unsigned char *compact_pixels,const QuantumType quantum_type, + ExceptionInfo *exception) { - int - y; - QuantumInfo *quantum_info; - register const PixelPacket + register const Quantum *p; size_t length, packet_size; - if (tmp_image->depth > 8) - tmp_image->depth=16; - packet_size=tmp_image->depth > 8UL ? 2UL : 1UL; + ssize_t + y; + + unsigned char + *pixels; + + if (next_image->depth > 8) + next_image->depth=16; + packet_size=next_image->depth > 8UL ? 2UL : 1UL; + (void) packet_size; quantum_info=AcquireQuantumInfo(image_info,image); - for (y=0; y < (ssize_t) tmp_image->rows; y++) + pixels=GetQuantumPixels(quantum_info); + for (y=0; y < (ssize_t) next_image->rows; y++) { - p=GetVirtualPixels(tmp_image,0,y,tmp_image->columns,1,&image->exception); - if (p == (const PixelPacket *) NULL) + p=GetVirtualPixels(next_image,0,y,next_image->columns,1,exception); + if (p == (const Quantum *) NULL) break; - length=ExportQuantumPixels(tmp_image,(CacheView *) NULL,quantum_info, - quantum_type,pixels,&image->exception); - length=PSDPackbitsEncodeImage(image,length,pixels,compact_pixels); + length=ExportQuantumPixels(next_image,(CacheView *) NULL,quantum_info, + quantum_type,pixels,exception); + length=PSDPackbitsEncodeImage(image,length,pixels,compact_pixels, + exception); (void) SetPSDOffset(psd_info,image,length); } quantum_info=DestroyQuantumInfo(quantum_info); } static void WriteOneChannel(const PSDInfo *psd_info,const ImageInfo *image_info, - Image *image,Image *tmp_image,unsigned char *pixels, - unsigned char *compact_pixels,const QuantumType quantum_type, - const MagickBooleanType compression_flag) + Image *image,Image *next_image,unsigned char *compact_pixels, + const QuantumType quantum_type,const MagickBooleanType compression_flag, + ExceptionInfo *exception) { int y; @@ -1654,7 +1746,7 @@ static void WriteOneChannel(const PSDInfo *psd_info,const ImageInfo *image_info, QuantumInfo *quantum_info; - register const PixelPacket + register const Quantum *p; register ssize_t @@ -1664,30 +1756,37 @@ static void WriteOneChannel(const PSDInfo *psd_info,const ImageInfo *image_info, length, packet_size; + unsigned char + *pixels; + (void) psd_info; if ((compression_flag != MagickFalse) && - (tmp_image->compression != RLECompression)) + (next_image->compression != RLECompression)) (void) WriteBlobMSBShort(image,0); - if (tmp_image->depth > 8) - tmp_image->depth=16; - monochrome=IsMonochromeImage(image,&image->exception); - packet_size=tmp_image->depth > 8UL ? 2UL : 1UL; + if (next_image->depth > 8) + next_image->depth=16; + monochrome=IsImageMonochrome(image,exception) && (image->depth == 1) ? + MagickTrue : MagickFalse; + packet_size=next_image->depth > 8UL ? 2UL : 1UL; + (void) packet_size; quantum_info=AcquireQuantumInfo(image_info,image); - for (y=0; y < (ssize_t) tmp_image->rows; y++) + pixels=GetQuantumPixels(quantum_info); + for (y=0; y < (ssize_t) next_image->rows; y++) { - p=GetVirtualPixels(tmp_image,0,y,tmp_image->columns,1,&image->exception); - if (p == (const PixelPacket *) NULL) + p=GetVirtualPixels(next_image,0,y,next_image->columns,1,exception); + if (p == (const Quantum *) NULL) break; - length=ExportQuantumPixels(tmp_image,(CacheView *) NULL,quantum_info, - quantum_type,pixels,&image->exception); + length=ExportQuantumPixels(next_image,(CacheView *) NULL,quantum_info, + quantum_type,pixels,exception); if (monochrome != MagickFalse) for (i=0; i < (ssize_t) length; i++) pixels[i]=(~pixels[i]); - if (tmp_image->compression != RLECompression) + if (next_image->compression != RLECompression) (void) WriteBlob(image,length,pixels); else { - length=PSDPackbitsEncodeImage(image,length,pixels,compact_pixels); + length=PSDPackbitsEncodeImage(image,length,pixels,compact_pixels, + exception); (void) WriteBlob(image,length,compact_pixels); } } @@ -1695,8 +1794,8 @@ static void WriteOneChannel(const PSDInfo *psd_info,const ImageInfo *image_info, } static MagickBooleanType WriteImageChannels(const PSDInfo *psd_info, - const ImageInfo *image_info,Image *image,Image *tmp_image, - const MagickBooleanType separate) + const ImageInfo *image_info,Image *image,Image *next_image, + const MagickBooleanType separate,ExceptionInfo *exception) { int i; @@ -1706,153 +1805,146 @@ static MagickBooleanType WriteImageChannels(const PSDInfo *psd_info, packet_size; unsigned char - *compact_pixels, - *pixels; + *compact_pixels; /* Write uncompressed pixels as separate planes. */ channels=1; - packet_size=tmp_image->depth > 8UL ? 2UL : 1UL; - pixels=(unsigned char *) AcquireQuantumMemory(channels*tmp_image->columns, - packet_size*sizeof(*pixels)); - compact_pixels=(unsigned char *) AcquireQuantumMemory(2*channels* - tmp_image->columns,packet_size*sizeof(*pixels)); - if ((pixels == (unsigned char *) NULL) || - (compact_pixels == (unsigned char *) NULL)) + packet_size=next_image->depth > 8UL ? 2UL : 1UL; + compact_pixels=(unsigned char *) NULL; + if (next_image->compression == RLECompression) { - if (pixels != (unsigned char *) NULL) - pixels=(unsigned char *) RelinquishMagickMemory(pixels); - if (compact_pixels != (unsigned char *) NULL) - compact_pixels=(unsigned char *) - RelinquishMagickMemory(compact_pixels); - ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); + compact_pixels=(unsigned char *) AcquireQuantumMemory(2*channels* + next_image->columns,packet_size*sizeof(*compact_pixels)); + if (compact_pixels == (unsigned char *) NULL) + ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); } i=0; - if (IsGrayImage(tmp_image,&tmp_image->exception) != MagickFalse) + if (IsImageGray(next_image,exception) != MagickFalse) { - if (tmp_image->compression == RLECompression) + if (next_image->compression == RLECompression) { /* Packbits compression. */ (void) WriteBlobMSBShort(image,1); - if (tmp_image->matte != MagickFalse) - WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,AlphaQuantum); - WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,GrayQuantum); + WritePackbitsLength(psd_info,image_info,image,next_image, + compact_pixels,GrayQuantum,exception); + if (next_image->matte != MagickFalse) + WritePackbitsLength(psd_info,image_info,image,next_image, + compact_pixels,AlphaQuantum,exception); } - if (tmp_image->matte != MagickFalse) - WriteOneChannel(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,AlphaQuantum,(i++ == 0) || - (separate != MagickFalse) ? MagickTrue : MagickFalse); - WriteOneChannel(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,GrayQuantum,(i++ == 0) || - (separate != MagickFalse) ? MagickTrue : MagickFalse); + WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels, + GrayQuantum,(i++ == 0) || (separate != MagickFalse) ? MagickTrue : + MagickFalse,exception); + if (next_image->matte != MagickFalse) + WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels, + AlphaQuantum,(i++ == 0) || (separate != MagickFalse) ? MagickTrue : + MagickFalse,exception); (void) SetImageProgress(image,SaveImagesTag,0,1); } else - if (tmp_image->storage_class == PseudoClass) + if (next_image->storage_class == PseudoClass) { - if (tmp_image->compression == RLECompression) + if (next_image->compression == RLECompression) { /* Packbits compression. */ (void) WriteBlobMSBShort(image,1); - if (tmp_image->matte != MagickFalse) - WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,AlphaQuantum); - WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,IndexQuantum); + WritePackbitsLength(psd_info,image_info,image,next_image, + compact_pixels,IndexQuantum,exception); + if (next_image->matte != MagickFalse) + WritePackbitsLength(psd_info,image_info,image,next_image, + compact_pixels,AlphaQuantum,exception); } - if (tmp_image->matte != MagickFalse) - WriteOneChannel(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,AlphaQuantum,(i++ == 0) || - (separate != MagickFalse) ? MagickTrue : MagickFalse); - WriteOneChannel(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,IndexQuantum,(i++ == 0) || - (separate != MagickFalse) ? MagickTrue : MagickFalse); + WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels, + IndexQuantum,(i++ == 0) || (separate != MagickFalse) ? MagickTrue : + MagickFalse,exception); + if (next_image->matte != MagickFalse) + WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels, + AlphaQuantum,(i++ == 0) || (separate != MagickFalse) ? MagickTrue : + MagickFalse,exception); (void) SetImageProgress(image,SaveImagesTag,0,1); } else { - if (tmp_image->colorspace == CMYKColorspace) - (void) NegateImage(tmp_image,MagickFalse); - if (tmp_image->compression == RLECompression) + if (next_image->colorspace == CMYKColorspace) + (void) NegateImage(next_image,MagickFalse,exception); + if (next_image->compression == RLECompression) { /* Packbits compression. */ (void) WriteBlobMSBShort(image,1); - WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,RedQuantum); - WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,GreenQuantum); - WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,BlueQuantum); - if (tmp_image->colorspace == CMYKColorspace) - WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,BlackQuantum); - if (tmp_image->matte != MagickFalse) - WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,AlphaQuantum); + WritePackbitsLength(psd_info,image_info,image,next_image, + compact_pixels,RedQuantum,exception); + WritePackbitsLength(psd_info,image_info,image,next_image, + compact_pixels,GreenQuantum,exception); + WritePackbitsLength(psd_info,image_info,image,next_image, + compact_pixels,BlueQuantum,exception); + if (next_image->colorspace == CMYKColorspace) + WritePackbitsLength(psd_info,image_info,image,next_image, + compact_pixels,BlackQuantum,exception); + if (next_image->matte != MagickFalse) + WritePackbitsLength(psd_info,image_info,image,next_image, + compact_pixels,AlphaQuantum,exception); } (void) SetImageProgress(image,SaveImagesTag,0,6); - WriteOneChannel(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,RedQuantum,(i++ == 0) || (separate != MagickFalse) ? - MagickTrue : MagickFalse); + WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels, + RedQuantum,(i++ == 0) || (separate != MagickFalse) ? MagickTrue : + MagickFalse,exception); (void) SetImageProgress(image,SaveImagesTag,1,6); - WriteOneChannel(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,GreenQuantum,(i++ == 0) || (separate != MagickFalse) ? - MagickTrue : MagickFalse); + WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels, + GreenQuantum,(i++ == 0) || (separate != MagickFalse) ? MagickTrue : + MagickFalse,exception); (void) SetImageProgress(image,SaveImagesTag,2,6); - WriteOneChannel(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,BlueQuantum,(i++ == 0) || (separate != MagickFalse) ? - MagickTrue : MagickFalse); + WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels, + BlueQuantum,(i++ == 0) || (separate != MagickFalse) ? MagickTrue : + MagickFalse,exception); (void) SetImageProgress(image,SaveImagesTag,3,6); - if (tmp_image->colorspace == CMYKColorspace) - { - WriteOneChannel(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,BlackQuantum,(i++ == 0) || - (separate != MagickFalse) ? MagickTrue : MagickFalse); - (void) NegateImage(tmp_image,MagickFalse); - } + if (next_image->colorspace == CMYKColorspace) + WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels, + BlackQuantum,(i++ == 0) || (separate != MagickFalse) ? MagickTrue : + MagickFalse,exception); (void) SetImageProgress(image,SaveImagesTag,4,6); - if (tmp_image->matte != MagickFalse) - WriteOneChannel(psd_info,image_info,image,tmp_image,pixels, - compact_pixels,AlphaQuantum,(i++ == 0) || - (separate != MagickFalse) ? MagickTrue : MagickFalse); + if (next_image->matte != MagickFalse) + WriteOneChannel(psd_info,image_info,image,next_image,compact_pixels, + AlphaQuantum,(i++ == 0) || (separate != MagickFalse) ? MagickTrue : + MagickFalse,exception); (void) SetImageProgress(image,SaveImagesTag,5,6); + if (next_image->colorspace == CMYKColorspace) + (void) NegateImage(next_image,MagickFalse,exception); } - pixels=(unsigned char *) RelinquishMagickMemory(pixels); + if (next_image->compression == RLECompression) + compact_pixels=(unsigned char *) RelinquishMagickMemory(compact_pixels); return(MagickTrue); } static void WritePascalString(Image* inImage,const char *inString,int inPad) { size_t - strLength; - int i; - - /* max length is 255 */ + length; - strLength = (strlen(inString) > 255UL ) ? 255UL : strlen(inString); + register ssize_t + i; - if ( strLength != 0 ) - { - (void) WriteBlobByte(inImage,(unsigned char) strLength); - (void) WriteBlob(inImage, strLength, (const unsigned char *) inString); - } + /* + Max length is 255. + */ + length=(strlen(inString) > 255UL ) ? 255UL : strlen(inString); + if (length == 0) + (void) WriteBlobByte(inImage,0); else - (void) WriteBlobByte(inImage, 0); - - strLength ++; - - if ( (strLength % inPad) == 0 ) + { + (void) WriteBlobByte(inImage,(unsigned char) length); + (void) WriteBlob(inImage, length, (const unsigned char *) inString); + } + length++; + if ((length % inPad) == 0) return; - for (i=0; i < (ssize_t) (inPad-(strLength % inPad)); i++) + for (i=0; i < (ssize_t) (inPad-(length % inPad)); i++) (void) WriteBlobByte(inImage,0); } @@ -1865,13 +1957,13 @@ static void WriteResolutionResourceBlock(Image *image) unsigned short units; - x_resolution=65536.0*image->x_resolution+0.5; - y_resolution=65536.0*image->y_resolution+0.5; + x_resolution=65536.0*image->resolution.x+0.5; + y_resolution=65536.0*image->resolution.y+0.5; units=1; if (image->units == PixelsPerCentimeterResolution) { - x_resolution=2.54*65536.0*image->x_resolution*0.5; - y_resolution=2.54*65536.0*image->y_resolution+0.5; + x_resolution=2.54*65536.0*image->resolution.x*0.5; + y_resolution=2.54*65536.0*image->resolution.y+0.5; units=2; } (void) WriteBlob(image,4,(const unsigned char *) "8BIM"); @@ -1969,7 +2061,7 @@ static void RemoveResolutionFromResourceBlock(StringInfo *bim_profile) p=PushShortPixel(MSBEndian,p,&id); p=PushShortPixel(MSBEndian,p,&short_sans); p=PushLongPixel(MSBEndian,p,&count); - if (id == 0x000003ed) + if ((id == 0x000003ed) && (PSDQuantum(count) < (ssize_t) (length-12))) { (void) CopyMagickMemory(q,q+PSDQuantum(count)+12,length- (PSDQuantum(count)+12)-(q-datum)); @@ -1982,14 +2074,19 @@ static void RemoveResolutionFromResourceBlock(StringInfo *bim_profile) } } -static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image) +static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image, + ExceptionInfo *exception) { const char - *theAttr; + *property; const StringInfo *icc_profile; + Image + *base_image, + *next_image; + MagickBooleanType status; @@ -2000,9 +2097,14 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image) i; size_t + channel_size, + channelLength, + layer_count, + layer_info_size, length, num_channels, - packet_size; + packet_size, + rounded_layer_info_size; StringInfo *bim_profile; @@ -2010,17 +2112,6 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image) unsigned char layer_name[4]; - size_t - channel_size, - channelLength, - layer_count, - layer_info_size, - rounded_layer_info_size; - - Image - *tmp_image = (Image *) NULL, - *base_image = GetNextImageInList(image); - /* Open image file. */ @@ -2030,7 +2121,9 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image) assert(image->signature == MagickSignature); if (image->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickSignature); + status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); if (status == MagickFalse) return(status); packet_size=(size_t) (image->depth > 8 ? 6 : 3); @@ -2044,7 +2137,7 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image) (void) WriteBlobMSBShort(image,psd_info.version); /* version */ for (i=1; i <= 6; i++) (void) WriteBlobByte(image, 0); /* 6 bytes of reserved */ - if (IsGrayImage(image,&image->exception) != MagickFalse) + if (IsImageGray(image,exception) != MagickFalse) num_channels=(image->matte != MagickFalse ? 2UL : 1UL); else if (image->storage_class == PseudoClass) @@ -2059,7 +2152,7 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image) (void) WriteBlobMSBShort(image,(unsigned short) num_channels); (void) WriteBlobMSBLong(image,(unsigned int) image->rows); (void) WriteBlobMSBLong(image,(unsigned int) image->columns); - if (IsGrayImage(image,&image->exception) != MagickFalse) + if (IsImageGray(image,exception) != MagickFalse) { MagickBooleanType monochrome; @@ -2067,33 +2160,34 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image) /* Write depth & mode. */ - monochrome=IsMonochromeImage(image,&image->exception); + monochrome=IsImageMonochrome(image,exception) && (image->depth == 1) ? + MagickTrue : MagickFalse; (void) WriteBlobMSBShort(image,(unsigned short) (monochrome != MagickFalse ? 1 : image->depth > 8 ? 16 : 8)); - (void) WriteBlobMSBShort(image,monochrome != MagickFalse ? - BitmapMode : GrayscaleMode); + (void) WriteBlobMSBShort(image,(unsigned short) + (monochrome != MagickFalse ? BitmapMode : GrayscaleMode)); } else { - (void) WriteBlobMSBShort(image,(unsigned short) - (image->storage_class == PseudoClass ? 8 : image->depth > 8 ? 16 : 8)); - if (((image->colorspace != UndefinedColorspace) || + (void) WriteBlobMSBShort(image,(unsigned short) (image->storage_class == + PseudoClass ? 8 : image->depth > 8 ? 16 : 8)); + if (((image_info->colorspace != UndefinedColorspace) || (image->colorspace != CMYKColorspace)) && - (image->colorspace != CMYKColorspace)) + (image_info->colorspace != CMYKColorspace)) { - if (image->colorspace != RGBColorspace) - (void) TransformImageColorspace(image,RGBColorspace); + if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse) + (void) TransformImageColorspace(image,sRGBColorspace,exception); (void) WriteBlobMSBShort(image,(unsigned short) (image->storage_class == PseudoClass ? IndexedMode : RGBMode)); } else { - if (image->colorspace != RGBColorspace) - (void) TransformImageColorspace(image,CMYKColorspace); + if (image->colorspace != CMYKColorspace) + (void) TransformImageColorspace(image,CMYKColorspace,exception); (void) WriteBlobMSBShort(image,CMYKMode); } } - if ((IsGrayImage(image,&image->exception) != MagickFalse) || + if ((IsImageGray(image,exception) != MagickFalse) || (image->storage_class == DirectClass) || (image->colors > 256)) (void) WriteBlobMSBLong(image,0); else @@ -2107,7 +2201,8 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image) for ( ; i < 256; i++) (void) WriteBlobByte(image,0); for (i=0; i < (ssize_t) image->colors; i++) - (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].green)); + (void) WriteBlobByte(image,ScaleQuantumToChar( + image->colormap[i].green)); for ( ; i < 256; i++) (void) WriteBlobByte(image,0); for (i=0; i < (ssize_t) image->colors; i++) @@ -2152,151 +2247,169 @@ static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image) PSDQuantum(GetStringInfoLength(icc_profile))) (void) WriteBlobByte(image,0); } - - layer_count = 0; - layer_info_size = 2; - tmp_image = base_image; - while ( tmp_image != NULL ) { - packet_size=tmp_image->depth > 8 ? 2UL : 1UL; - - if (IsGrayImage(image,&image->exception) != MagickFalse) - num_channels=tmp_image->matte != MagickFalse ? 2UL : 1UL; + layer_count=0; + layer_info_size=2; + base_image=GetNextImageInList(image); + if ((image->matte != MagickFalse) && (base_image == (Image *) NULL)) + base_image=image; + next_image=base_image; + while ( next_image != NULL ) + { + packet_size=next_image->depth > 8 ? 2UL : 1UL; + if (IsImageGray(next_image,exception) != MagickFalse) + num_channels=next_image->matte != MagickFalse ? 2UL : 1UL; else - if (tmp_image->storage_class == PseudoClass) - num_channels=tmp_image->matte != MagickFalse ? 2UL : 1UL; + if (next_image->storage_class == PseudoClass) + num_channels=next_image->matte != MagickFalse ? 2UL : 1UL; else - if (tmp_image->colorspace != CMYKColorspace) - num_channels=tmp_image->matte != MagickFalse ? 4UL : 3UL; + if (next_image->colorspace != CMYKColorspace) + num_channels=next_image->matte != MagickFalse ? 4UL : 3UL; else - num_channels=tmp_image->matte != MagickFalse ? 5UL : 4UL; - - channelLength=(size_t) (tmp_image->columns * tmp_image->rows * - packet_size + 2); - layer_info_size += (size_t) (4*4 + 2 + num_channels * 6 + - (psd_info.version == 1 ? 8 : 16) + 4 * 1 + 4 + num_channels * - channelLength); - theAttr=(const char *) GetImageProperty(tmp_image,"label"); - if (!theAttr) - layer_info_size += 16; + num_channels=next_image->matte != MagickFalse ? 5UL : 4UL; + channelLength=(size_t) (next_image->columns*next_image->rows*packet_size+2); + layer_info_size+=(size_t) (4*4+2+num_channels*6+(psd_info.version == 1 ? 8 : + 16)+4*1+4+num_channels*channelLength); + property=(const char *) GetImageProperty(next_image,"label",exception); + if (property == (const char *) NULL) + layer_info_size+=16; else { - size_t length=strlen(theAttr); - layer_info_size += 8+length+(4-(length % 4)); + size_t + length; + + length=strlen(property); + layer_info_size+=8+length+(4-(length % 4)); } layer_count++; - tmp_image = GetNextImageInList(tmp_image); + next_image=GetNextImageInList(next_image); } if (layer_count == 0) (void) SetPSDSize(&psd_info,image,0); else - { - (void) SetPSDSize(&psd_info,image,layer_info_size+ - (psd_info.version == 1 ? 8 : 16)); - if ( layer_info_size/2 != (layer_info_size+1)/2 ) /* odd */ - rounded_layer_info_size = layer_info_size + 1; - else - rounded_layer_info_size = layer_info_size; - (void) SetPSDSize(&psd_info,image,rounded_layer_info_size); - (void) WriteBlobMSBShort(image,(unsigned short) layer_count); - layer_count=1; - tmp_image = base_image; - while ( tmp_image != NULL ) { - (void) WriteBlobMSBLong(image,0); - (void) WriteBlobMSBLong(image,0); - (void) WriteBlobMSBLong(image,(unsigned int) tmp_image->rows); - (void) WriteBlobMSBLong(image,(unsigned int) tmp_image->columns); - - packet_size=tmp_image->depth > 8 ? 2UL : 1UL; - channel_size=(unsigned int) ((packet_size*tmp_image->rows* - tmp_image->columns)+2); - if ((IsGrayImage(tmp_image,&image->exception) != MagickFalse) || - (tmp_image->storage_class == PseudoClass)) { - (void) WriteBlobMSBShort(image,(unsigned short) - (tmp_image->matte != MagickFalse ? 2 : 1)); - (void) WriteBlobMSBShort(image, 0); - (void) SetPSDSize(&psd_info,image,channel_size); - if (tmp_image->matte != MagickFalse) { - (void) WriteBlobMSBShort(image,(unsigned short) -1); - (void) SetPSDSize(&psd_info,image,channel_size); - } - } else - if (tmp_image->colorspace != CMYKColorspace) - { - (void) WriteBlobMSBShort(image,(unsigned short) - (tmp_image->matte != MagickFalse ? 4 : 3)); - (void) WriteBlobMSBShort(image, 0); - (void) SetPSDSize(&psd_info,image,channel_size); - (void) WriteBlobMSBShort(image, 1); - (void) SetPSDSize(&psd_info,image,channel_size); - (void) WriteBlobMSBShort(image, 2); - (void) SetPSDSize(&psd_info,image,channel_size); - if (tmp_image->matte!= MagickFalse ) { - (void) WriteBlobMSBShort(image,(unsigned short) -1); - (void) SetPSDSize(&psd_info,image,channel_size); - } - } + { + CompressionType + compression; + + (void) SetPSDSize(&psd_info,image,layer_info_size+ + (psd_info.version == 1 ? 8 : 16)); + if ((layer_info_size/2) != ((layer_info_size+1)/2)) + rounded_layer_info_size=layer_info_size+1; else + rounded_layer_info_size=layer_info_size; + (void) SetPSDSize(&psd_info,image,rounded_layer_info_size); + (void) WriteBlobMSBShort(image,(unsigned short) layer_count); + layer_count=1; + compression=base_image->compression; + next_image=base_image; + while (next_image != NULL) { - (void) WriteBlobMSBShort(image,(unsigned short) - (tmp_image->matte ? 5 : 4)); - (void) WriteBlobMSBShort(image, 0); - (void) SetPSDSize(&psd_info,image,channel_size); - (void) WriteBlobMSBShort(image, 1); - (void) SetPSDSize(&psd_info,image,channel_size); - (void) WriteBlobMSBShort(image, 2); - (void) SetPSDSize(&psd_info,image,channel_size); - (void) WriteBlobMSBShort(image, 3); - (void) SetPSDSize(&psd_info,image,channel_size); - if (tmp_image->matte) { - (void) WriteBlobMSBShort(image,(unsigned short) -1); - (void) SetPSDSize(&psd_info,image,channel_size); - } + next_image->compression=NoCompression; + (void) WriteBlobMSBLong(image,(unsigned int) next_image->page.y); + (void) WriteBlobMSBLong(image,(unsigned int) next_image->page.x); + (void) WriteBlobMSBLong(image,(unsigned int) next_image->page.y+ + next_image->rows); + (void) WriteBlobMSBLong(image,(unsigned int) next_image->page.x+ + next_image->columns); + packet_size=next_image->depth > 8 ? 2UL : 1UL; + channel_size=(unsigned int) ((packet_size*next_image->rows* + next_image->columns)+2); + if ((IsImageGray(next_image,exception) != MagickFalse) || + (next_image->storage_class == PseudoClass)) + { + (void) WriteBlobMSBShort(image,(unsigned short) + (next_image->matte != MagickFalse ? 2 : 1)); + (void) WriteBlobMSBShort(image,0); + (void) SetPSDSize(&psd_info,image,channel_size); + if (next_image->matte != MagickFalse) + { + (void) WriteBlobMSBShort(image,(unsigned short) -1); + (void) SetPSDSize(&psd_info,image,channel_size); + } + } + else + if (next_image->colorspace != CMYKColorspace) + { + (void) WriteBlobMSBShort(image,(unsigned short) + (next_image->matte != MagickFalse ? 4 : 3)); + (void) WriteBlobMSBShort(image,0); + (void) SetPSDSize(&psd_info,image,channel_size); + (void) WriteBlobMSBShort(image,1); + (void) SetPSDSize(&psd_info,image,channel_size); + (void) WriteBlobMSBShort(image,2); + (void) SetPSDSize(&psd_info,image,channel_size); + if (next_image->matte!= MagickFalse ) + { + (void) WriteBlobMSBShort(image,(unsigned short) -1); + (void) SetPSDSize(&psd_info,image,channel_size); + } + } + else + { + (void) WriteBlobMSBShort(image,(unsigned short) + (next_image->matte ? 5 : 4)); + (void) WriteBlobMSBShort(image,0); + (void) SetPSDSize(&psd_info,image,channel_size); + (void) WriteBlobMSBShort(image,1); + (void) SetPSDSize(&psd_info,image,channel_size); + (void) WriteBlobMSBShort(image,2); + (void) SetPSDSize(&psd_info,image,channel_size); + (void) WriteBlobMSBShort(image,3); + (void) SetPSDSize(&psd_info,image,channel_size); + if (next_image->matte) + { + (void) WriteBlobMSBShort(image,(unsigned short) -1); + (void) SetPSDSize(&psd_info,image,channel_size); + } + } + (void) WriteBlob(image,4,(const unsigned char *) "8BIM"); + (void) WriteBlob(image,4,(const unsigned char *) + CompositeOperatorToPSDBlendMode(next_image->compose)); + (void) WriteBlobByte(image,255); /* layer opacity */ + (void) WriteBlobByte(image,0); + (void) WriteBlobByte(image,1); /* layer propertys - visible, etc. */ + (void) WriteBlobByte(image,0); + property=(const char *) GetImageProperty(next_image,"label",exception); + if (property == (const char *) NULL) + { + (void) WriteBlobMSBLong(image,16); + (void) WriteBlobMSBLong(image,0); + (void) WriteBlobMSBLong(image,0); + (void) FormatLocaleString((char *) layer_name,MaxTextExtent, + "L%06ld",(long) layer_count++); + WritePascalString( image, (char*)layer_name, 4 ); + } + else + { + size_t + length; + + length=strlen(property); + (void) WriteBlobMSBLong(image,(unsigned int) (length+(4- + (length % 4))+8)); + (void) WriteBlobMSBLong(image,0); + (void) WriteBlobMSBLong(image,0); + WritePascalString(image,property,4); + } + next_image=GetNextImageInList(next_image); } - - (void) WriteBlob(image,4,(const unsigned char *) "8BIM"); - (void) WriteBlob(image,4,(const unsigned char *) - CompositeOperatorToPSDBlendMode(tmp_image->compose)); - (void) WriteBlobByte(image, 255); /* BOGUS: layer opacity */ - (void) WriteBlobByte(image, 0); - (void) WriteBlobByte(image, 1); /* BOGUS: layer attributes - visible, etc. */ - (void) WriteBlobByte(image, 0); - - - theAttr=(const char *) GetImageProperty(tmp_image,"label"); - if (!theAttr) { - (void) WriteBlobMSBLong(image, 16); - (void) WriteBlobMSBLong(image, 0); - (void) WriteBlobMSBLong(image, 0); - (void) FormatMagickString((char *) layer_name,MaxTextExtent,"L%06ld", - (long) layer_count++); - WritePascalString( image, (char*)layer_name, 4 ); - } else { - size_t length=strlen(theAttr); - (void) WriteBlobMSBLong(image,(unsigned int) (length+(4-(length % 4))+ - 8)); - (void) WriteBlobMSBLong(image,0); - (void) WriteBlobMSBLong(image,0); - WritePascalString( image, theAttr, 4 ); + /* + Now the image data! + */ + next_image=base_image; + while (next_image != NULL) + { + status=WriteImageChannels(&psd_info,image_info,image,next_image, + MagickTrue,exception); + next_image=GetNextImageInList(next_image); } - tmp_image = GetNextImageInList(tmp_image); + (void) WriteBlobMSBLong(image,0); /* user mask data */ + base_image->compression=compression; } - /* now the image data! */ - tmp_image = base_image; - while ( tmp_image != NULL ) { - status=WriteImageChannels(&psd_info,image_info,image,tmp_image,MagickTrue); - /* add in the pad! */ - if ( rounded_layer_info_size != layer_info_size ) - (void) WriteBlobByte(image,'\0'); - - tmp_image = GetNextImageInList(tmp_image); - }; - /* user mask data */ - (void) WriteBlobMSBLong(image,0); - } /* Write composite image. */ - status=WriteImageChannels(&psd_info,image_info,image,image,MagickFalse); + status=WriteImageChannels(&psd_info,image_info,image,image,MagickFalse, + exception); (void) CloseBlob(image); return(status); }