2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read/Write Adobe Photoshop Image Format %
21 % Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
22 % dedicated to making software imaging solutions freely available. %
24 % You may not use this file except in compliance with the License. You may %
25 % obtain a copy of the License at %
27 % http://www.imagemagick.org/script/license.php %
29 % Unless required by applicable law or agreed to in writing, software %
30 % distributed under the License is distributed on an "AS IS" BASIS, %
31 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
32 % See the License for the specific language governing permissions and %
33 % limitations under the License. %
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43 #include "magick/studio.h"
44 #include "magick/artifact.h"
45 #include "magick/blob.h"
46 #include "magick/blob-private.h"
47 #include "magick/cache.h"
48 #include "magick/colorspace.h"
49 #include "magick/constitute.h"
50 #include "magick/enhance.h"
51 #include "magick/exception.h"
52 #include "magick/exception-private.h"
53 #include "magick/image.h"
54 #include "magick/image-private.h"
55 #include "magick/list.h"
56 #include "magick/log.h"
57 #include "magick/magick.h"
58 #include "magick/memory_.h"
59 #include "magick/module.h"
60 #include "magick/monitor-private.h"
61 #include "magick/profile.h"
62 #include "magick/property.h"
63 #include "magick/quantum-private.h"
64 #include "magick/static.h"
65 #include "magick/string_.h"
70 #define MaxPSDChannels 56
73 Enumerated declaractions.
88 Typedef declaractions.
90 typedef struct _ChannelInfo
99 typedef struct _LayerInfo
109 channel_info[MaxPSDChannels];
133 typedef struct _PSDInfo
155 Forward declarations.
157 static MagickBooleanType
158 WritePSDImage(const ImageInfo *,Image *);
161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
165 % D e c o d e I m a g e %
169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
171 % DecodeImage uncompresses an image via Macintosh encoding specific to
172 % the Adobe Photoshop image format.
174 % The format of the DecodeImage method is:
176 % MagickBooleanType DecodeImage(Image *image,const long channel)
178 % A description of each parameter follows:
180 % o image,image: the address of a structure of type Image.
182 % o channel: Specifies which channel: red, green, blue, or index to
183 % decode the pixel values into.
186 static MagickBooleanType DecodeImage(Image *image,const long channel)
210 exception=(&image->exception);
211 number_pixels=(MagickOffsetType) image->columns*image->rows;
212 for (x=0; number_pixels > 0; )
214 count=(ssize_t) ReadBlobByte(image);
221 pixel=ScaleCharToQuantum((unsigned char) ReadBlobByte(image));
222 q=GetAuthenticPixels(image,(long) (x % image->columns),
223 (long) (x/image->columns),-count+1,1,exception);
224 if (q == (PixelPacket *) NULL)
226 indexes=GetAuthenticIndexQueue(image);
227 for (count=(-count+1); count > 0; count--)
233 q->opacity=(Quantum) (QuantumRange-pixel);
239 if (image->storage_class == PseudoClass)
241 *indexes=(IndexPacket) ScaleQuantumToChar(pixel);
242 q->red=image->colormap[(long) *indexes].red;
243 q->green=image->colormap[(long) *indexes].green;
244 q->blue=image->colormap[(long) *indexes].blue;
250 if (image->storage_class == PseudoClass)
251 q->opacity=(Quantum) (QuantumRange-pixel);
263 if (image->colorspace == CMYKColorspace)
264 *indexes=(IndexPacket) pixel;
266 q->opacity=(Quantum) (QuantumRange-pixel);
271 q->opacity=(Quantum) (QuantumRange-pixel);
277 if (SyncAuthenticPixels(image,exception) == MagickFalse)
287 q=GetAuthenticPixels(image,(long) (x % image->columns),
288 (long) (x/image->columns),count,1,exception);
289 if (q == (PixelPacket *) NULL)
291 indexes=GetAuthenticIndexQueue(image);
292 for (i=(long) count; i > 0; i--)
294 pixel=ScaleCharToQuantum((unsigned char) ReadBlobByte(image));
299 q->opacity=(Quantum) (QuantumRange-pixel);
305 if (image->storage_class == PseudoClass)
307 *indexes=(IndexPacket) ScaleQuantumToChar(pixel);
308 q->red=image->colormap[(long) *indexes].red;
309 q->green=image->colormap[(long) *indexes].green;
310 q->blue=image->colormap[(long) *indexes].blue;
316 if (image->storage_class == PseudoClass)
317 q->opacity=(Quantum) (QuantumRange-pixel);
329 if (image->colorspace == CMYKColorspace)
330 *indexes=(IndexPacket) pixel;
332 q->opacity=(Quantum) (QuantumRange-pixel);
337 q->opacity=(Quantum) pixel;
343 if (SyncAuthenticPixels(image,exception) == MagickFalse)
352 Guarentee the correct number of pixel packets.
354 if (number_pixels > 0)
355 ThrowBinaryException(CorruptImageError,"InsufficientImageDataInFile",
358 if (number_pixels < 0)
359 ThrowBinaryException(CorruptImageError,"TooMuchImageDataInFile",
365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 % IsPSD()() returns MagickTrue if the image format type, identified by the
376 % magick string, is PSD.
378 % The format of the IsPSD method is:
380 % MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
382 % A description of each parameter follows:
384 % o magick: compare image format pattern against these bytes.
386 % o length: Specifies the length of the magick string.
389 static MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
393 if (LocaleNCompare((const char *) magick,"8BPS",4) == 0)
399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
403 % R e a d P S D I m a g e %
407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409 % ReadPSDImage() reads an Adobe Photoshop image file and returns it. It
410 % allocates the memory necessary for the new Image structure and returns a
411 % pointer to the new image.
413 % The format of the ReadPSDImage method is:
415 % image=ReadPSDImage(image_info)
417 % A description of each parameter follows:
419 % o image_info: the image info.
421 % o exception: return any errors or warnings in this structure.
425 static inline MagickOffsetType GetPSDOffset(PSDInfo *psd_info,Image *image)
427 if (psd_info->version == 1)
428 return((MagickOffsetType) ReadBlobMSBShort(image));
429 return((MagickOffsetType) ReadBlobMSBLong(image));
432 static inline MagickSizeType GetPSDSize(PSDInfo *psd_info,Image *image)
434 if (psd_info->version == 1)
435 return((MagickSizeType) ReadBlobMSBLong(image));
436 return((MagickSizeType) ReadBlobMSBLongLong(image));
439 static inline long MagickAbsoluteValue(const long x)
446 static CompositeOperator PSDBlendModeToCompositeOperator(const char *mode)
448 if (mode == (const char *) NULL)
449 return(OverCompositeOp);
450 if (LocaleNCompare(mode,"norm",4) == 0)
451 return(OverCompositeOp);
452 if (LocaleNCompare(mode,"mul ",4) == 0)
453 return(MultiplyCompositeOp);
454 if (LocaleNCompare(mode,"diss",4) == 0)
455 return(DissolveCompositeOp);
456 if (LocaleNCompare(mode,"diff",4) == 0)
457 return(DifferenceCompositeOp);
458 if (LocaleNCompare(mode,"dark",4) == 0)
459 return(DarkenCompositeOp);
460 if (LocaleNCompare(mode,"lite",4) == 0)
461 return(LightenCompositeOp);
462 if (LocaleNCompare(mode,"hue ",4) == 0)
463 return(HueCompositeOp);
464 if (LocaleNCompare(mode,"sat ",4) == 0)
465 return(SaturateCompositeOp);
466 if (LocaleNCompare(mode,"colr",4) == 0)
467 return(ColorizeCompositeOp);
468 if (LocaleNCompare(mode,"lum ",4) == 0)
469 return(LuminizeCompositeOp);
470 if (LocaleNCompare(mode,"scrn",4) == 0)
471 return(ScreenCompositeOp);
472 if (LocaleNCompare(mode,"over",4) == 0)
473 return(OverlayCompositeOp);
474 if (LocaleNCompare(mode,"hLit",4) == 0)
475 return(OverCompositeOp);
476 if (LocaleNCompare(mode,"sLit",4) == 0)
477 return(OverCompositeOp);
478 if (LocaleNCompare(mode,"smud",4) == 0)
479 return(OverCompositeOp);
480 if (LocaleNCompare(mode,"div ",4) == 0)
481 return(OverCompositeOp);
482 if (LocaleNCompare(mode,"idiv",4) == 0)
483 return(OverCompositeOp);
484 return(OverCompositeOp);
487 static const char *CompositeOperatorToPSDBlendMode(CompositeOperator inOp)
494 case OverCompositeOp: outMode = "norm"; break;
495 case MultiplyCompositeOp: outMode = "mul "; break;
496 case DissolveCompositeOp: outMode = "diss"; break;
497 case DifferenceCompositeOp: outMode = "diff"; break;
498 case DarkenCompositeOp: outMode = "dark"; break;
499 case LightenCompositeOp: outMode = "lite"; break;
500 case HueCompositeOp: outMode = "hue "; break;
501 case SaturateCompositeOp: outMode = "sat "; break;
502 case ColorizeCompositeOp: outMode = "colr"; break;
503 case LuminizeCompositeOp: outMode = "lum "; break;
504 case ScreenCompositeOp: outMode = "scrn"; break;
505 case OverlayCompositeOp: outMode = "over"; break;
512 static const char *ModeToString( PSDImageType inType )
516 case BitmapMode: return "Bitmap";
517 case GrayscaleMode: return "Grayscale";
518 case IndexedMode: return "Indexed";
519 case RGBMode: return "RGB";
520 case CMYKMode: return "CMYK";
521 case MultichannelMode: return "Multichannel";
522 case DuotoneMode: return "Duotone";
523 case LabMode: return "L*A*B";
524 default: return "unknown";
528 static MagickBooleanType ParseImageResourceBlocks(Image *image,
529 const unsigned char *blocks,size_t length)
547 profile=AcquireStringInfo(length);
548 SetStringInfoDatum(profile,blocks);
549 (void) SetImageProfile(image,"8bim",profile);
550 profile=DestroyStringInfo(profile);
551 for (p=blocks; (p >= blocks) && (p < (blocks+length-16)); )
553 if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
555 p=PushLongPixel(LSBEndian,p,&long_sans);
556 p=PushShortPixel(LSBEndian,p,&id);
557 p=PushShortPixel(LSBEndian,p,&short_sans);
558 p=PushLongPixel(LSBEndian,p,&count);
569 p=PushShortPixel(LSBEndian,p,&resolution);
570 image->x_resolution=(double) resolution;
571 p=PushShortPixel(LSBEndian,p,&short_sans);
572 p=PushShortPixel(LSBEndian,p,&short_sans);
573 p=PushShortPixel(LSBEndian,p,&short_sans);
574 p=PushShortPixel(LSBEndian,p,&resolution);
575 image->y_resolution=(double) resolution;
576 p=PushShortPixel(LSBEndian,p,&short_sans);
577 p=PushShortPixel(LSBEndian,p,&short_sans);
578 p=PushShortPixel(LSBEndian,p,&short_sans);
587 if ((count & 0x01) != 0)
593 static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception)
651 skip_first_alpha = 0;
656 assert(image_info != (const ImageInfo *) NULL);
657 assert(image_info->signature == MagickSignature);
658 if (image_info->debug != MagickFalse)
659 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
660 image_info->filename);
661 assert(exception != (ExceptionInfo *) NULL);
662 assert(exception->signature == MagickSignature);
663 image=AcquireImage(image_info);
664 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
665 if (status == MagickFalse)
667 image=DestroyImageList(image);
668 return((Image *) NULL);
673 count=ReadBlob(image,4,(unsigned char *) psd_info.signature);
674 psd_info.version=ReadBlobMSBShort(image);
675 if ((count == 0) || (LocaleNCompare(psd_info.signature,"8BPS",4) != 0) ||
676 ((psd_info.version != 1) && (psd_info.version != 2)))
677 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
678 count=ReadBlob(image,6,psd_info.reserved);
679 psd_info.channels=ReadBlobMSBShort(image);
680 if (psd_info.channels > MaxPSDChannels)
681 ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
682 psd_info.rows=ReadBlobMSBLong(image);
683 psd_info.columns=ReadBlobMSBLong(image);
684 if ((psd_info.version == 1) && ((psd_info.rows > 30000) ||
685 (psd_info.columns > 30000)))
686 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
687 if ((psd_info.version == 1) && ((psd_info.rows > 300000) ||
688 (psd_info.columns > 300000)))
689 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
690 psd_info.depth=ReadBlobMSBShort(image);
691 if ((psd_info.depth != 1) && (psd_info.depth != 8) && (psd_info.depth != 16))
692 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
693 psd_info.mode=ReadBlobMSBShort(image);
694 if (image->debug != MagickFalse)
695 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
696 " Image is %ld x %ld with channels=%d, depth=%d, mode=%s",
697 psd_info.columns,psd_info.rows,psd_info.channels,psd_info.depth,
698 ModeToString((PSDImageType) psd_info.mode));
702 image->depth=psd_info.depth;
703 image->columns=psd_info.columns;
704 image->rows=psd_info.rows;
705 if (SetImageBackgroundColor(image) == MagickFalse)
707 InheritException(exception,&image->exception);
708 image=DestroyImageList(image);
709 return((Image *) NULL);
711 image->matte=psd_info.channels >= 4 ? MagickTrue : MagickFalse;
712 if (psd_info.mode == LabMode)
713 image->colorspace=LabColorspace;
714 if (psd_info.mode == CMYKMode)
716 image->colorspace=CMYKColorspace;
717 image->matte=psd_info.channels >= 5 ? MagickTrue : MagickFalse;
719 if ((psd_info.mode == BitmapMode) || (psd_info.mode == GrayscaleMode) ||
720 (psd_info.mode == DuotoneMode))
722 if (AcquireImageColormap(image,256) == MagickFalse)
723 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
724 image->matte=psd_info.channels >= 2 ? MagickTrue : MagickFalse;
725 if (image->debug != MagickFalse)
726 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
727 " ImageColorMap allocated");
729 if (image->debug != MagickFalse)
730 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
731 image->matte ? " image has matte" : " image has no matte");
733 Read PSD raster colormap only present for indexed and duotone images.
735 length=ReadBlobMSBLong(image);
738 if (image->debug != MagickFalse)
739 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
740 " reading colormap");
741 if (psd_info.mode == DuotoneMode)
744 Duotone image data; the format of this data is undocumented.
746 data=(unsigned char *) AcquireQuantumMemory(length,sizeof(*data));
747 if (data == (unsigned char *) NULL)
748 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
749 count=ReadBlob(image,length,data);
750 data=(unsigned char *) RelinquishMagickMemory(data);
755 Read PSD raster colormap.
757 if (AcquireImageColormap(image,(unsigned long) (length/3)) == MagickFalse)
758 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
759 for (i=0; i < (long) image->colors; i++)
760 image->colormap[i].red=ScaleCharToQuantum((unsigned char)
761 ReadBlobByte(image));
762 for (i=0; i < (long) image->colors; i++)
763 image->colormap[i].green=ScaleCharToQuantum((unsigned char)
764 ReadBlobByte(image));
765 for (i=0; i < (long) image->colors; i++)
766 image->colormap[i].blue=ScaleCharToQuantum((unsigned char)
767 ReadBlobByte(image));
768 image->matte=psd_info.channels >= 2 ? MagickTrue : MagickFalse;
771 length=ReadBlobMSBLong(image);
778 Image resources block.
780 if (image->debug != MagickFalse)
781 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
782 " reading image resource blocks - %ld bytes",(long) length);
783 blocks=(unsigned char *) AcquireQuantumMemory(length,sizeof(*blocks));
784 if (blocks == (unsigned char *) NULL)
785 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
786 count=ReadBlob(image,length,blocks);
787 if (((size_t) count != length) ||
788 (LocaleNCompare((char *) blocks,"8BIM",4) != 0))
790 blocks=(unsigned char *) RelinquishMagickMemory(blocks);
791 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
793 (void) ParseImageResourceBlocks(image,blocks,length);
794 blocks=(unsigned char *) RelinquishMagickMemory(blocks);
797 If we are only "pinging" the image, then we're done - so return.
799 if (image_info->ping != MagickFalse)
801 (void) CloseBlob(image);
802 return(GetFirstImageInList(image));
805 Layer and mask block.
807 layer_info=(LayerInfo *) NULL;
809 length=GetPSDSize(&psd_info,image);
812 length=ReadBlobMSBLong(image);
813 length=ReadBlobMSBLong(image);
815 if ((image_info->number_scenes == 1) && (image_info->scene == 0))
816 for ( ; length != 0; length--)
817 if (ReadBlobByte(image) == EOF)
819 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
825 if (image->debug != MagickFalse)
826 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
827 " image has no layers");
831 offset=TellBlob(image);
832 size=GetPSDSize(&psd_info,image);
841 quantum=psd_info.version == 1 ? 4 : 8;
842 for (j=0; j < (long) (length-quantum); j++)
843 (void) ReadBlobByte(image);
850 layer_offset=offset+length;
851 number_layers=(short) ReadBlobMSBShort(image);
852 if (image->debug != MagickFalse)
853 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
854 " image contains %ld layers", number_layers);
855 if (number_layers < 0)
858 Weird hack in PSD format to ignore first alpha channel.
861 number_layers=MagickAbsoluteValue(number_layers);
862 if (image->debug != MagickFalse)
863 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
864 " negative layer count corrected for");
866 layer_info=(LayerInfo *) AcquireQuantumMemory((size_t) number_layers,
867 sizeof(*layer_info));
868 if (layer_info == (LayerInfo *) NULL)
870 if (image->debug != MagickFalse)
871 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
872 " allocation of LayerInfo failed");
873 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
875 (void) ResetMagickMemory(layer_info,0,(size_t) number_layers*
876 sizeof(*layer_info));
877 for (i=0; i < number_layers; i++)
879 if (image->debug != MagickFalse)
880 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
881 " reading layer #%ld",i+1);
882 layer_info[i].page.y=(long) ReadBlobMSBLong(image);
883 layer_info[i].page.x=(long) ReadBlobMSBLong(image);
884 layer_info[i].page.height=ReadBlobMSBLong(image)-layer_info[i].page.y;
885 layer_info[i].page.width=ReadBlobMSBLong(image)-layer_info[i].page.x;
886 layer_info[i].channels=ReadBlobMSBShort(image);
887 if (layer_info[i].channels > MaxPSDChannels)
888 ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
889 if (image->debug != MagickFalse)
890 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
891 " offset(%ld,%ld), size(%ld,%ld), channels=%d",
892 layer_info[i].page.x, layer_info[i].page.y,
893 layer_info[i].page.height,layer_info[i].page.width,
894 layer_info[i].channels);
895 for (j=0; j < (long) layer_info[i].channels; j++)
897 layer_info[i].channel_info[j].type=(short) ReadBlobMSBShort(image);
898 layer_info[i].channel_info[j].size=GetPSDSize(&psd_info,image);
899 if (image->debug != MagickFalse)
900 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
901 " channel[%ld]: type=%d, size=%ld",j,
902 layer_info[i].channel_info[j].type,
903 (long) layer_info[i].channel_info[j].size);
905 count=ReadBlob(image,4,(unsigned char *) type);
906 if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0))
908 if (image->debug != MagickFalse)
909 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
910 " layer type was %.4s instead of 8BIM", type);
911 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
913 count=ReadBlob(image,4,(unsigned char *) layer_info[i].blendkey);
914 layer_info[i].opacity=(Quantum) (QuantumRange-ScaleCharToQuantum(
915 (unsigned char) ReadBlobByte(image)));
916 layer_info[i].clipping=(unsigned char) ReadBlobByte(image);
917 layer_info[i].flags=(unsigned char) ReadBlobByte(image);
918 layer_info[i].visible=!(layer_info[i].flags & 0x02);
919 if (image->debug != MagickFalse)
920 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
921 " blend=%.4s, opacity=%lu, clipping=%s, flags=%d, visible=%s",
922 layer_info[i].blendkey,(unsigned long) layer_info[i].opacity,
923 layer_info[i].clipping ? "true" : "false",layer_info[i].flags,
924 layer_info[i].visible ? "true" : "false");
925 (void) ReadBlobByte(image); /* filler */
927 size=ReadBlobMSBLong(image);
930 if (image->debug != MagickFalse)
931 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
932 " layer contains additional info");
933 length=ReadBlobMSBLong(image);
939 layer_info[i].mask.y=(long) ReadBlobMSBLong(image);
940 layer_info[i].mask.x=(long) ReadBlobMSBLong(image);
941 layer_info[i].mask.height=
942 (ReadBlobMSBLong(image)-layer_info[i].mask.y);
943 layer_info[i].mask.width=
944 (ReadBlobMSBLong(image)-layer_info[i].mask.x);
945 if (image->debug != MagickFalse)
946 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
947 " layer mask: offset(%ld,%ld), size(%ld,%ld), length=%ld",
948 layer_info[i].mask.x,layer_info[i].mask.y,
949 layer_info[i].mask.width, layer_info[i].mask.height,
952 Skip over the rest of the layer mask information.
954 for (j=0; j < (long) (length-16); j++)
955 (void) ReadBlobByte(image);
957 combinedlength+=length+4; /* +4 for length */
958 length=ReadBlobMSBLong(image);
962 Layer blending ranges info.
964 if (image->debug != MagickFalse)
965 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
966 " layer blending ranges: length=%ld",(long) length);
968 We read it, but don't use it...
970 for (j=0; j < (long) (length); j+=8)
972 size_t blend_source=ReadBlobMSBLong(image);
973 size_t blend_dest=ReadBlobMSBLong(image);
974 if (image->debug != MagickFalse)
975 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
976 " source(%x), dest(%x)",(unsigned int)
977 blend_source,(unsigned int) blend_dest);
980 combinedlength+=length+4;
984 length=(size_t) ReadBlobByte(image);
985 for (j=0; j < (long) length; j++)
986 layer_info[i].name[j]=(unsigned char) ReadBlobByte(image);
987 layer_info[i].name[j]='\0';
988 if (image->debug != MagickFalse)
989 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
990 " layer name: %s",layer_info[i].name);
991 combinedlength+=length+1;
993 #if 0 /* still in development */
995 Adjustment layers and other stuff...
1001 count=ReadBlob(image,4,alsig);
1002 if ((count == 0) || (LocaleNCompare(alsig,"8BIM",4) != 0)) {
1003 if (debug != MagickFalse)
1005 if (image->debug != MagickFalse)
1006 (void) LogMagickEvent(CoderEvent,GetMagickModule()," adjustment layer type was %.4s instead of 8BIM", alsig);
1008 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1010 count=ReadBlob(image,4,alkey);
1011 length=ReadBlobMSBLong(image);
1012 if (debug != MagickFalse)
1014 if (image->debug != MagickFalse)
1015 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1016 " adjustment layer key: %.4s, data length=%ld",
1021 for (j=0; j < (long) (length); j++)
1022 (void) ReadBlobByte(image);
1026 combinedlength += 12 + length; /* sig, key, length + the actual length*/
1030 Skip the rest of the variable data until we support it.
1032 if (image->debug != MagickFalse)
1033 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1034 " unsupported data: length=%ld",(long)
1035 (size-combinedlength));
1036 for (j=0; j < (long) (size-combinedlength); j++)
1037 (void) ReadBlobByte(image);
1040 Allocate layered image.
1042 layer_info[i].image=CloneImage(image,layer_info[i].page.width,
1043 layer_info[i].page.height,MagickFalse,&image->exception);
1044 if (layer_info[i].image == (Image *) NULL)
1046 for (j=0; j < i; j++)
1047 layer_info[j].image=DestroyImage(layer_info[j].image);
1048 if (image->debug != MagickFalse)
1049 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1050 " allocation of image for layer %ld failed", i);
1051 ThrowReaderException(ResourceLimitError,
1052 "MemoryAllocationFailed");
1054 if (image->debug != MagickFalse)
1055 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1056 " setting up new layer image");
1057 (void) SetImageBackgroundColor(layer_info[i].image);
1058 layer_info[i].image->compose=
1059 PSDBlendModeToCompositeOperator(layer_info[i].blendkey);
1060 if (layer_info[i].visible == MagickFalse)
1061 layer_info[i].image->compose=NoCompositeOp;
1062 if (psd_info.mode == CMYKMode)
1063 image->colorspace=CMYKColorspace;
1064 for (j=0; j < (long) layer_info[i].channels; j++)
1065 if (layer_info[i].channel_info[j].type == -1)
1066 layer_info[i].image->matte=MagickTrue;
1068 Set up some hidden attributes for folks that need them.
1070 (void) FormatMagickString(s,MaxTextExtent,"%ld",
1071 layer_info[i].page.x );
1072 (void) SetImageArtifact(layer_info[i].image,"psd:layer.x",s);
1073 (void) FormatMagickString(s,MaxTextExtent,"%ld",
1074 layer_info[i].page.y);
1075 (void) SetImageArtifact(layer_info[i].image,"psd:layer.y",s);
1076 (void) FormatMagickString(s,MaxTextExtent,"%lu",(unsigned long)
1077 layer_info[i].opacity );
1078 (void) SetImageArtifact(layer_info[i].image,"psd:layer.opacity",s);
1079 (void) SetImageProperty(layer_info[i].image,"label",(char *)
1080 layer_info[i].name);
1082 if (image->debug != MagickFalse)
1083 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1084 " reading image data for layers");
1086 Read pixel data for each layer.
1088 for (i=0; i < number_layers; i++)
1090 if (image->debug != MagickFalse)
1091 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1092 " reading data for layer %ld",i);
1093 for (j=0; j < (long) layer_info[i].channels; j++)
1095 if (image->debug != MagickFalse)
1096 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1097 " reading data for channel %ld", j);
1099 if (layer_info[i].channel_info[j].size <= (2*layer_info[i].image->rows))
1104 if (image->debug != MagickFalse)
1105 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1106 " layer data is empty");
1108 A layer without data.
1110 for (k=0; k < (long) layer_info[i].channel_info[j].size; k++)
1111 (void) ReadBlobByte(layer_info[i].image);
1115 compression=ReadBlobMSBShort(layer_info[i].image);
1116 if ((layer_info[i].page.height != 0) &&
1117 (layer_info[i].page.width != 0))
1119 if (compression == 1)
1122 Read RLE compressed data.
1124 if (image->debug != MagickFalse)
1125 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1126 " layer data is RLE compressed");
1127 for (y=0; y < (long) layer_info[i].image->rows; y++)
1128 (void) GetPSDOffset(&psd_info,layer_info[i].image);
1129 (void) DecodeImage(layer_info[i].image,
1130 layer_info[i].channel_info[j].type);
1134 Read uncompressed pixel data as separate planes.
1136 if (image->debug != MagickFalse)
1137 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1138 " layer data is uncompressed");
1140 if (layer_info[i].image->storage_class == PseudoClass)
1142 if (layer_info[i].image->colors > 256)
1145 if (layer_info[i].image->depth > 8)
1149 if (layer_info[i].image->depth > 8)
1151 for (y=0; y < (long) layer_info[i].image->rows; y++)
1153 q=GetAuthenticPixels(layer_info[i].image,0,y,
1154 layer_info[i].image->columns,1,exception);
1155 if (q == (PixelPacket *) NULL)
1157 indexes=GetAuthenticIndexQueue(layer_info[i].image);
1158 for (x=0; x < (long) layer_info[i].image->columns; x++)
1160 if (packet_size == 1)
1161 pixel=(unsigned long) ScaleCharToQuantum((unsigned char)
1162 ReadBlobByte(layer_info[i].image));
1164 pixel=(unsigned long) ScaleShortToQuantum(
1165 ReadBlobMSBShort(layer_info[i].image));
1166 switch (layer_info[i].channel_info[j].type)
1168 case -1: /* transparency mask */
1170 q->opacity=(Quantum) (QuantumRange-pixel);
1173 case 0: /* first component (Red, Cyan, Gray or Index) */
1175 q->red=(Quantum) pixel;
1176 if (layer_info[i].image->storage_class == PseudoClass)
1178 if (packet_size == 1)
1179 indexes[x]=(IndexPacket) ScaleQuantumToChar(
1182 indexes[x]=(IndexPacket) ScaleQuantumToShort(
1184 q->red=layer_info[i].image->colormap[(long) *indexes].red;
1185 q->green=layer_info[i].image->colormap[(long) *indexes].green;
1186 q->blue=layer_info[i].image->colormap[(long) *indexes].blue;
1190 case 1: /* second component (Green, Magenta, or opacity) */
1192 if (layer_info[i].image->storage_class == PseudoClass)
1193 q->opacity=(Quantum) (QuantumRange-pixel);
1195 q->green=(Quantum) pixel;
1198 case 2: /* third component (Blue or Yellow) */
1200 q->blue=(Quantum) pixel;
1203 case 3: /* fourth component (Opacity or Black) */
1205 if (image->colorspace == CMYKColorspace)
1206 indexes[x]=(Quantum) pixel;
1208 q->opacity=(Quantum) (QuantumRange-pixel);
1211 case 4: /* fifth component (opacity) */
1213 q->opacity=(Quantum) (QuantumRange-pixel);
1221 if (SyncAuthenticPixels(layer_info[i].image,exception) == MagickFalse)
1226 if (layer_info[i].opacity != OpaqueOpacity)
1229 Correct for opacity level.
1231 for (y=0; y < (long) layer_info[i].image->rows; y++)
1233 q=GetAuthenticPixels(layer_info[i].image,0,y,
1234 layer_info[i].image->columns,1,exception);
1235 if (q == (PixelPacket *) NULL)
1237 indexes=GetAuthenticIndexQueue(layer_info[i].image);
1238 for (x=0; x < (long) layer_info[i].image->columns; x++)
1240 q->opacity=(Quantum) (QuantumRange-(Quantum) (QuantumScale*
1241 ((QuantumRange-q->opacity)*(QuantumRange-
1242 layer_info[i].opacity))));
1245 if (SyncAuthenticPixels(layer_info[i].image,exception) == MagickFalse)
1249 if (layer_info[i].image->colorspace == CMYKColorspace)
1250 (void) NegateImage(layer_info[i].image,MagickFalse);
1251 status=SetImageProgress(image,LoadImagesTag,i,number_layers);
1252 if (status == MagickFalse)
1255 /* added by palf -> invisible group layer make layer of this group
1256 invisible I consider that all layer with width and height null are
1257 layer for group layer */
1259 short inside_layer = 0;
1260 short layer_visible = 0;
1261 for (i=number_layers-1; i >=0; i--)
1263 if ((layer_info[i].page.width == 0) ||
1264 (layer_info[i].page.height == 0))
1266 if (inside_layer == 0)
1269 layer_visible=(short int) layer_info[i].visible;
1277 if ((inside_layer == 1) && (layer_visible == 0))
1279 layer_info[i].visible=(unsigned char) layer_visible;
1280 layer_info[i].image->compose=NoCompositeOp;
1284 /* added by palf -> suppression of empty layer */
1285 /* I consider that all layer with width and height null are layer for group layer */
1286 for (i=0; i < number_layers; i++)
1288 if ((layer_info[i].page.width == 0) ||
1289 (layer_info[i].page.height == 0))
1291 if (layer_info[i].image != (Image *) NULL)
1292 layer_info[i].image=DestroyImage(layer_info[i].image);
1293 for (j=i; j < number_layers - 1; j++)
1294 layer_info[j] = layer_info[j+1];
1299 mask_size = ReadBlobMSBLong(image); /* global mask size: currently ignored */
1300 if (number_layers > 0)
1303 if (image->debug != MagickFalse)
1304 (void) LogMagickEvent(CoderEvent,GetMagickModule()," putting layers into image list");
1305 for (i=0; i < number_layers; i++)
1308 layer_info[i].image->previous=layer_info[i-1].image;
1309 if (i < (number_layers-1))
1310 layer_info[i].image->next=layer_info[i+1].image;
1311 layer_info[i].image->page=layer_info[i].page;
1313 image->next=layer_info[0].image;
1314 layer_info[0].image->previous=image;
1315 layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
1318 layer_offset-=TellBlob(image);
1319 offset=SeekBlob(image,layer_offset,SEEK_CUR);
1323 Read the precombined layer, present for PSD < 4 compatibility
1325 if (image->debug != MagickFalse)
1326 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1327 " reading the precombined layer");
1328 compression=ReadBlobMSBShort(image);
1329 if (compression == 1)
1332 Read Packbit encoded pixel data as separate planes.
1334 for (i=0; i < (long) (image->rows*psd_info.channels); i++)
1335 (void) GetPSDOffset(&psd_info,image);
1336 for (i=0; i < (long) psd_info.channels; i++)
1338 (void) DecodeImage(image,(int) i);
1339 status=SetImageProgress(image,LoadImagesTag,i,psd_info.channels);
1340 if (status == MagickFalse)
1347 Read uncompressed pixel data separate planes.
1350 if (image->storage_class == PseudoClass)
1352 if (image->colors > 256)
1355 if (image->depth > 8)
1359 if (image->depth > 8)
1361 for (i=0; i < (long) psd_info.channels; i++)
1363 for (y=0; y < (long) image->rows; y++)
1365 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
1366 if (q == (PixelPacket *) NULL)
1368 indexes=GetAuthenticIndexQueue(image);
1369 for (x=0; x < (long) image->columns; x++)
1371 if (packet_size == 1)
1372 pixel=(unsigned long) ScaleCharToQuantum((unsigned char)
1373 ReadBlobByte(image));
1375 pixel=(unsigned long) ScaleShortToQuantum(
1376 ReadBlobMSBShort(image));
1381 q->opacity=(Quantum) (QuantumRange-pixel);
1386 q->red=(Quantum) pixel;
1387 if (psd_info.channels == 1)
1392 if (image->storage_class == PseudoClass)
1394 if (packet_size == 1)
1395 indexes[x]=(IndexPacket) ScaleQuantumToChar((Quantum)
1398 indexes[x]=(IndexPacket) ScaleQuantumToShort((Quantum)
1400 *q=image->colormap[(long) indexes[x]];
1401 q->red=image->colormap[(long) indexes[x]].red;
1402 q->green=image->colormap[(long) indexes[x]].green;
1403 q->blue=image->colormap[(long) indexes[x]].blue;
1409 if (image->storage_class == PseudoClass)
1410 q->opacity=(Quantum) (QuantumRange-pixel);
1412 q->green=(Quantum) pixel;
1417 q->blue=(Quantum) pixel;
1422 if (image->colorspace == CMYKColorspace)
1423 indexes[x]=(IndexPacket) pixel;
1425 q->opacity=(Quantum) (QuantumRange-pixel);
1430 q->opacity=(Quantum) (QuantumRange-pixel);
1438 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1441 status=SetImageProgress(image,LoadImagesTag,i,psd_info.channels);
1442 if (status == MagickFalse)
1446 if (image->colorspace == CMYKColorspace)
1447 (void) NegateImage(image,MagickFalse);
1448 (void) CloseBlob(image);
1449 return(GetFirstImageInList(image));
1453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1457 % R e g i s t e r P S D I m a g e %
1461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1463 % RegisterPSDImage() adds properties for the PSD image format to
1464 % the list of supported formats. The properties include the image format
1465 % tag, a method to read and/or write the format, whether the format
1466 % supports the saving of more than one frame to the same file or blob,
1467 % whether the format supports native in-memory I/O, and a brief
1468 % description of the format.
1470 % The format of the RegisterPSDImage method is:
1472 % unsigned long RegisterPSDImage(void)
1475 ModuleExport unsigned long RegisterPSDImage(void)
1480 entry=SetMagickInfo("PSB");
1481 entry->decoder=(DecodeImageHandler *) ReadPSDImage;
1482 entry->encoder=(EncodeImageHandler *) WritePSDImage;
1483 entry->magick=(IsImageFormatHandler *) IsPSD;
1484 entry->description=ConstantString("Adobe Large Document Format");
1485 entry->module=ConstantString("PSD");
1486 (void) RegisterMagickInfo(entry);
1487 entry=SetMagickInfo("PSD");
1488 entry->decoder=(DecodeImageHandler *) ReadPSDImage;
1489 entry->encoder=(EncodeImageHandler *) WritePSDImage;
1490 entry->magick=(IsImageFormatHandler *) IsPSD;
1491 entry->description=ConstantString("Adobe Photoshop bitmap");
1492 entry->module=ConstantString("PSD");
1493 (void) RegisterMagickInfo(entry);
1494 return(MagickImageCoderSignature);
1498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1502 % U n r e g i s t e r P S D I m a g e %
1506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1508 % UnregisterPSDImage() removes format registrations made by the
1509 % PSD module from the list of supported formats.
1511 % The format of the UnregisterPSDImage method is:
1513 % UnregisterPSDImage(void)
1516 ModuleExport void UnregisterPSDImage(void)
1518 (void) UnregisterMagickInfo("PSB");
1519 (void) UnregisterMagickInfo("PSD");
1523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527 % W r i t e P S D I m a g e %
1531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1533 % WritePSDImage() writes an image in the Adobe Photoshop encoded image
1536 % The format of the WritePSDImage method is:
1538 % MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image)
1540 % A description of each parameter follows.
1542 % o image_info: the image info.
1544 % o image: The image.
1549 static inline ssize_t SetPSDOffset(const PSDInfo *psd_info,Image *image,
1550 const size_t offset)
1552 if (psd_info->version == 1)
1553 return(WriteBlobMSBShort(image,offset));
1554 return(WriteBlobMSBLong(image,offset));
1557 static inline ssize_t SetPSDSize(const PSDInfo *psd_info,Image *image,
1558 const MagickSizeType size)
1560 if (psd_info->version == 1)
1561 return(WriteBlobMSBLong(image,(unsigned long) size));
1562 return(WriteBlobMSBLongLong(image,size));
1565 static size_t PSDPackbitsEncodeImage(Image *image,const size_t length,
1566 const unsigned char *pixels,unsigned char *compressed_pixels)
1575 register unsigned char
1582 Compress pixels with Packbits encoding.
1584 assert(image != (Image *) NULL);
1585 assert(image->signature == MagickSignature);
1586 if (image->debug != MagickFalse)
1587 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1588 assert(pixels != (unsigned char *) NULL);
1589 packbits=(unsigned char *) AcquireQuantumMemory(128UL,sizeof(*packbits));
1590 if (packbits == (unsigned char *) NULL)
1591 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1593 q=compressed_pixels;
1594 for (i=(long) length; i != 0; )
1601 *q++=(unsigned char) 0;
1608 *q++=(unsigned char) 1;
1616 if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1618 *q++=(unsigned char) ((256-3)+1);
1622 *q++=(unsigned char) 2;
1630 if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1636 while (((long) count < i) && (*pixels == *(pixels+count)))
1643 *q++=(unsigned char) ((256-count)+1);
1652 while ((*(pixels+count) != *(pixels+count+1)) ||
1653 (*(pixels+count+1) != *(pixels+count+2)))
1655 packbits[count+1]=pixels[count];
1657 if (((long) count >= (i-3)) || (count >= 127))
1661 *packbits=(unsigned char) (count-1);
1662 for (j=0; j <= (long) count; j++)
1669 *q++=(unsigned char) 128; /* EOD marker */
1670 packbits=(unsigned char *) RelinquishMagickMemory(packbits);
1671 return(q-compressed_pixels);
1674 static void WritePackbitsLength(const PSDInfo *psd_info,
1675 const ImageInfo *image_info,Image *image,Image *tmp_image,
1676 unsigned char *pixels,unsigned char *compressed_pixels,
1677 const QuantumType quantum_type)
1685 register const PixelPacket
1692 if (tmp_image->depth > 8)
1693 tmp_image->depth=16;
1694 packet_size=tmp_image->depth > 8UL ? 2UL : 1UL;
1695 quantum_info=AcquireQuantumInfo(image_info,image);
1696 for (y=0; y < (long) tmp_image->rows; y++)
1698 p=GetVirtualPixels(tmp_image,0,y,tmp_image->columns,1,&image->exception);
1699 if (p == (const PixelPacket *) NULL)
1701 length=ExportQuantumPixels(tmp_image,(CacheView *) NULL,quantum_info,
1702 quantum_type,pixels,&image->exception);
1703 length=PSDPackbitsEncodeImage(image,length,pixels,compressed_pixels);
1704 (void) SetPSDOffset(psd_info,image,length);
1706 quantum_info=DestroyQuantumInfo(quantum_info);
1709 static void WriteOneChannel(const PSDInfo *psd_info,const ImageInfo *image_info,
1710 Image *image,Image *tmp_image,unsigned char *pixels,
1711 unsigned char *compressed_pixels,const QuantumType quantum_type,
1712 const MagickBooleanType compression_flag)
1720 register const PixelPacket
1728 if ((compression_flag != MagickFalse) &&
1729 (tmp_image->compression == NoCompression))
1730 (void) WriteBlobMSBShort(image,0);
1731 if (tmp_image->depth > 8)
1732 tmp_image->depth=16;
1733 packet_size=tmp_image->depth > 8UL ? 2UL : 1UL;
1734 quantum_info=AcquireQuantumInfo(image_info,image);
1735 for (y=0; y < (long) tmp_image->rows; y++)
1737 p=GetVirtualPixels(tmp_image,0,y,tmp_image->columns,1,&image->exception);
1738 if (p == (const PixelPacket *) NULL)
1740 length=ExportQuantumPixels(tmp_image,(CacheView *) NULL,quantum_info,
1741 quantum_type,pixels,&image->exception);
1742 if (tmp_image->compression == NoCompression)
1743 (void) WriteBlob(image,length,pixels);
1746 length=PSDPackbitsEncodeImage(image,length,pixels,compressed_pixels);
1747 (void) WriteBlob(image,length,compressed_pixels);
1750 quantum_info=DestroyQuantumInfo(quantum_info);
1753 static MagickBooleanType WriteImageChannels(const PSDInfo *psd_info,
1754 const ImageInfo *image_info,Image *image,Image *tmp_image,
1755 const MagickBooleanType separate)
1769 Write uncompressed pixels as separate planes.
1772 if ((tmp_image->storage_class == PseudoClass) &&
1773 (tmp_image->matte == MagickFalse))
1775 packet_size=tmp_image->depth > 8UL ? 2UL : 1UL;
1776 pixels=(unsigned char *) AcquireQuantumMemory(channels*tmp_image->columns,
1777 packet_size*sizeof(*pixels));
1778 compressed_pixels=(unsigned char *) AcquireQuantumMemory(2*channels*
1779 tmp_image->columns,packet_size*sizeof(*pixels));
1780 if ((pixels == (unsigned char *) NULL) ||
1781 (compressed_pixels == (unsigned char *) NULL))
1783 if (pixels != (unsigned char *) NULL)
1784 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1785 if (compressed_pixels != (unsigned char *) NULL)
1786 compressed_pixels=(unsigned char *)
1787 RelinquishMagickMemory(compressed_pixels);
1788 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1791 if (tmp_image->storage_class == PseudoClass)
1793 if (tmp_image->compression != NoCompression)
1796 Packbits compression.
1798 (void) WriteBlobMSBShort(image,1);
1799 if (tmp_image->matte == MagickFalse)
1800 WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels,
1801 compressed_pixels,IndexQuantum);
1803 WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels,
1804 compressed_pixels,IndexAlphaQuantum);
1806 if (tmp_image->matte == MagickFalse)
1807 WriteOneChannel(psd_info,image_info,image,tmp_image,pixels,
1808 compressed_pixels,IndexQuantum,(i++ == 0) ||
1809 (separate != MagickFalse) ? MagickTrue : MagickFalse);
1811 WriteOneChannel(psd_info,image_info,image,tmp_image,pixels,
1812 compressed_pixels,IndexAlphaQuantum,(i++ == 0) ||
1813 (separate != MagickFalse) ? MagickTrue : MagickFalse);
1814 (void) SetImageProgress(image,SaveImagesTag,0,1);
1818 if (tmp_image->colorspace == CMYKColorspace)
1819 (void) NegateImage(image,MagickFalse);
1820 if (tmp_image->compression != NoCompression)
1823 Packbits compression.
1825 (void) WriteBlobMSBShort(image,1);
1826 if (tmp_image->matte != MagickFalse)
1827 WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels,
1828 compressed_pixels,AlphaQuantum);
1829 WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels,
1830 compressed_pixels,RedQuantum);
1831 WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels,
1832 compressed_pixels,GreenQuantum);
1833 WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels,
1834 compressed_pixels,BlueQuantum);
1835 if (tmp_image->colorspace == CMYKColorspace)
1836 WritePackbitsLength(psd_info,image_info,image,tmp_image,pixels,
1837 compressed_pixels,BlackQuantum);
1839 (void) SetImageProgress(image,SaveImagesTag,0,6);
1840 if (tmp_image->matte != MagickFalse)
1841 WriteOneChannel(psd_info,image_info,image,tmp_image,pixels,
1842 compressed_pixels,AlphaQuantum,(i++ == 0) ||
1843 (separate != MagickFalse) ? MagickTrue : MagickFalse);
1844 (void) SetImageProgress(image,SaveImagesTag,1,6);
1845 WriteOneChannel(psd_info,image_info,image,tmp_image,pixels,
1846 compressed_pixels,RedQuantum,(i++ == 0) || (separate != MagickFalse) ?
1847 MagickTrue : MagickFalse);
1848 (void) SetImageProgress(image,SaveImagesTag,2,6);
1849 WriteOneChannel(psd_info,image_info,image,tmp_image,pixels,
1850 compressed_pixels,GreenQuantum,(i++ == 0) || (separate != MagickFalse) ?
1851 MagickTrue : MagickFalse);
1852 (void) SetImageProgress(image,SaveImagesTag,3,6);
1853 WriteOneChannel(psd_info,image_info,image,tmp_image,pixels,
1854 compressed_pixels,BlueQuantum,(i++ == 0) || (separate != MagickFalse) ?
1855 MagickTrue : MagickFalse);
1856 (void) SetImageProgress(image,SaveImagesTag,4,6);
1857 if (tmp_image->colorspace == CMYKColorspace)
1859 WriteOneChannel(psd_info,image_info,image,tmp_image,pixels,
1860 compressed_pixels,BlackQuantum,(i++ == 0) ||
1861 (separate != MagickFalse) ? MagickTrue : MagickFalse);
1862 (void) NegateImage(image,MagickFalse);
1864 (void) SetImageProgress(image,SaveImagesTag,5,6);
1866 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1870 /* Write white background, RLE-compressed */
1872 static void WriteWhiteBackground(const PSDInfo *psd_info,Image *image )
1875 char *d, scanline[256];
1877 int numChannels = 3, dim = (int) (image->rows*numChannels);
1888 (void) WriteBlobMSBShort(image,1); /* RLE compressed */
1889 w8 = (long) image->columns;
1891 /* Set up scanline */
1892 for (w=w8; w > 128; w-=128)
1910 bytecount = d - scanline;
1912 /* Scanline counts (rows*channels) */
1913 for (i=0; i < dim; i++)
1915 (void) SetPSDOffset(psd_info,image,bytecount);
1918 /* RLE compressed data */
1920 for (i=0; i < dim; i++)
1922 (void) WriteBlob( image, length, (unsigned char *) scanline );
1927 static void WritePascalString(Image* inImage,const char *inString,int inPad)
1933 /* max length is 255 */
1935 strLength = (strlen(inString) > 255UL ) ? 255UL : strlen(inString);
1937 if ( strLength != 0 )
1939 (void) WriteBlobByte(inImage,(unsigned char) strLength);
1940 (void) WriteBlob(inImage, strLength, (const unsigned char *) inString);
1943 (void) WriteBlobByte(inImage, 0);
1947 if ( (strLength % inPad) == 0 )
1949 for (i=0; i < (long) (inPad-(strLength % inPad)); i++)
1950 (void) WriteBlobByte(inImage,0);
1953 static void WriteResolutionResourceBlock(Image *image)
1962 x_resolution=65536.0*image->x_resolution+0.5;
1963 y_resolution=65536.0*image->y_resolution+0.5;
1965 if (image->units == PixelsPerCentimeterResolution)
1967 x_resolution=2.54*65536.0*image->x_resolution*0.5;
1968 y_resolution=2.54*65536.0*image->y_resolution+0.5;
1971 (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
1972 (void) WriteBlobMSBShort(image,0x03ED);
1973 (void) WriteBlobMSBShort(image,0);
1974 (void) WriteBlobMSBLong(image,16); /* resource size */
1975 (void) WriteBlobMSBLong(image,x_resolution);
1976 (void) WriteBlobMSBShort(image,units); /* horizontal resolution unit */
1977 (void) WriteBlobMSBShort(image,units); /* width unit */
1978 (void) WriteBlobMSBLong(image,y_resolution);
1979 (void) WriteBlobMSBShort(image,units); /* vertical resolution unit */
1980 (void) WriteBlobMSBShort(image,units); /* height unit */
1983 static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image)
1992 force_white_background = image->matte,
1993 invert_layer_count = MagickFalse,
2014 rounded_layer_info_size,
2018 * tmp_image = (Image *) NULL,
2019 * base_image = force_white_background ? image : GetNextImageInList(image);
2022 Open output image file.
2024 assert(image_info != (const ImageInfo *) NULL);
2025 assert(image_info->signature == MagickSignature);
2026 assert(image != (Image *) NULL);
2027 assert(image->signature == MagickSignature);
2028 if (image->debug != MagickFalse)
2029 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2030 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
2031 if (status == MagickFalse)
2033 packet_size=(size_t) (image->depth > 8 ? 6 : 3);
2034 if (image->matte != MagickFalse)
2035 packet_size+=image->depth > 8 ? 2 : 1;
2037 if ((LocaleCompare(image_info->magick,"PSB") == 0) ||
2038 (image->columns > 30000) || (image->rows > 30000))
2040 (void) WriteBlob(image,4,(const unsigned char *) "8BPS");
2041 (void) WriteBlobMSBShort(image,psd_info.version); /* version */
2042 for (i=1; i <= 6; i++)
2043 (void) WriteBlobByte(image, 0); /* 6 bytes of reserved */
2044 if ( force_white_background )
2048 if (image->storage_class == PseudoClass)
2049 num_channels=(image->matte ? 2UL : 1UL);
2052 if (image->colorspace != CMYKColorspace)
2053 num_channels=(image->matte ? 4UL : 3UL);
2055 num_channels=(image->matte ? 5UL : 4UL);
2058 (void) WriteBlobMSBShort(image,(unsigned short) num_channels);
2059 (void) WriteBlobMSBLong(image,image->rows);
2060 (void) WriteBlobMSBLong(image,image->columns);
2061 (void) WriteBlobMSBShort(image,(unsigned short)
2062 (image->storage_class == PseudoClass ? 8 : image->depth > 8 ? 16 : 8));
2063 if (((image->colorspace != UndefinedColorspace) ||
2064 (image->colorspace != CMYKColorspace)) &&
2065 (image->colorspace != CMYKColorspace))
2067 if (image->colorspace != RGBColorspace)
2068 (void) TransformImageColorspace(image,RGBColorspace);
2069 (void) WriteBlobMSBShort(image,(unsigned short)
2070 (image->storage_class == PseudoClass ? 2 : 3));
2074 if (image->colorspace != RGBColorspace)
2075 (void) TransformImageColorspace(image,CMYKColorspace);
2076 (void) WriteBlobMSBShort(image,4);
2078 if ((image->storage_class == DirectClass) || (image->colors > 256))
2079 (void) WriteBlobMSBLong(image,0);
2083 Write PSD raster colormap.
2085 (void) WriteBlobMSBLong(image,768);
2086 for (i=0; i < (long) image->colors; i++)
2087 (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].red));
2088 for ( ; i < 256; i++)
2089 (void) WriteBlobByte(image,0);
2090 for (i=0; i < (long) image->colors; i++)
2091 (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].green));
2092 for ( ; i < 256; i++)
2093 (void) WriteBlobByte(image,0);
2094 for (i=0; i < (long) image->colors; i++)
2095 (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].blue));
2096 for ( ; i < 256; i++)
2097 (void) WriteBlobByte(image,0);
2100 Image resource block.
2102 res_extra = 28; /* 0x03EB */
2103 profile=GetImageProfile(image,"8bim");
2104 if (profile == (StringInfo *) NULL)
2105 WriteBlobMSBLong(image, res_extra);
2108 (void) WriteBlobMSBLong(image,(unsigned long) res_extra +
2109 GetStringInfoLength(profile));
2110 (void) WriteBlob(image,GetStringInfoLength(profile),GetStringInfoDatum(
2113 WriteResolutionResourceBlock(image);
2117 layer_info_size = 2;
2118 tmp_image = base_image;
2119 while ( tmp_image != NULL ) {
2120 packet_size=tmp_image->depth > 8 ? 2UL : 1UL;
2122 if (tmp_image->storage_class == PseudoClass)
2123 num_channels = (tmp_image->matte != MagickFalse ? 2UL : 1UL);
2125 if (tmp_image->colorspace != CMYKColorspace)
2126 num_channels = (tmp_image->matte != MagickFalse ? 4UL : 3UL);
2128 num_channels = (tmp_image->matte != MagickFalse ? 5UL : 4UL);
2130 channelLength=(unsigned long) (tmp_image->columns * tmp_image->rows *
2132 layer_info_size += (unsigned long) (4*4 + 2 + num_channels * 6 +
2133 (psd_info.version == 1 ? 8 : 16) + 4 * 1 + 4 + num_channels *
2135 theAttr=(const char *) GetImageProperty(tmp_image,"label");
2137 layer_info_size += 16;
2140 size_t length=strlen(theAttr)+(4-(length % 4))+1;
2141 layer_info_size += 8+length;
2144 tmp_image = GetNextImageInList(tmp_image);
2147 /* if the image has a matte, then we need to use layers */
2148 if ( layer_count == 0 && image->matte == MagickTrue )
2150 invert_layer_count = MagickTrue;
2152 goto compute_layer_info; /* yes, goto's suck, but it keeps the code cleaner! */
2155 if ( layer_count == 0 )
2156 (void) SetPSDSize(&psd_info,image,0);
2159 (void) SetPSDSize(&psd_info,image,layer_info_size+
2160 (psd_info.version == 1 ? 8 : 16));
2161 if ( layer_info_size/2 != (layer_info_size+1)/2 ) /* odd */
2162 rounded_layer_info_size = layer_info_size + 1;
2164 rounded_layer_info_size = layer_info_size;
2165 (void) SetPSDSize(&psd_info,image,rounded_layer_info_size);
2167 if ( invert_layer_count )
2168 layer_count *= -1; /* if we have a matte, then use negative count! */
2169 (void) WriteBlobMSBShort(image,(unsigned short) layer_count);
2172 tmp_image = base_image;
2173 tmp_image->compression=NoCompression;
2174 while ( tmp_image != NULL ) {
2175 (void) WriteBlobMSBLong(image,0);
2176 (void) WriteBlobMSBLong(image,0);
2177 (void) WriteBlobMSBLong(image,tmp_image->rows);
2178 (void) WriteBlobMSBLong(image,tmp_image->columns);
2180 packet_size=tmp_image->depth > 8 ? 2UL : 1UL;
2181 channel_size=(unsigned int) ((packet_size*tmp_image->rows*
2182 tmp_image->columns)+2);
2183 if (tmp_image->storage_class == PseudoClass) {
2184 (void) WriteBlobMSBShort(image,(unsigned short)
2185 (tmp_image->matte ? 2 : 1));
2186 if (tmp_image->matte) {
2187 (void) WriteBlobMSBShort(image,(unsigned short) -1);
2188 (void) SetPSDSize(&psd_info,image,channel_size);
2190 (void) WriteBlobMSBShort(image, 0);
2191 (void) SetPSDSize(&psd_info,image,channel_size);
2193 if (tmp_image->colorspace != CMYKColorspace)
2195 (void) WriteBlobMSBShort(image,(unsigned short)
2196 (tmp_image->matte ? 4 : 3));
2197 if (tmp_image->matte) {
2198 (void) WriteBlobMSBShort(image,(unsigned short) -1);
2199 (void) SetPSDSize(&psd_info,image,channel_size);
2201 (void) WriteBlobMSBShort(image, 0);
2202 (void) SetPSDSize(&psd_info,image,channel_size);
2203 (void) WriteBlobMSBShort(image, 1);
2204 (void) SetPSDSize(&psd_info,image,channel_size);
2205 (void) WriteBlobMSBShort(image, 2);
2206 (void) SetPSDSize(&psd_info,image,channel_size);
2210 (void) WriteBlobMSBShort(image,(unsigned short)
2211 (tmp_image->matte ? 5 : 4));
2212 if (tmp_image->matte) {
2213 (void) WriteBlobMSBShort(image,(unsigned short) -1);
2214 (void) SetPSDSize(&psd_info,image,channel_size);
2216 (void) WriteBlobMSBShort(image, 0);
2217 (void) SetPSDSize(&psd_info,image,channel_size);
2218 (void) WriteBlobMSBShort(image, 1);
2219 (void) SetPSDSize(&psd_info,image,channel_size);
2220 (void) WriteBlobMSBShort(image, 2);
2221 (void) SetPSDSize(&psd_info,image,channel_size);
2222 (void) WriteBlobMSBShort(image, 3);
2223 (void) SetPSDSize(&psd_info,image,channel_size);
2226 (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
2227 (void) WriteBlob(image,4,(const unsigned char *)
2228 CompositeOperatorToPSDBlendMode(tmp_image->compose));
2229 (void) WriteBlobByte(image, 255); /* BOGUS: layer opacity */
2230 (void) WriteBlobByte(image, 0);
2231 (void) WriteBlobByte(image, 1); /* BOGUS: layer attributes - visible, etc. */
2232 (void) WriteBlobByte(image, 0);
2235 theAttr=(const char *) GetImageProperty(tmp_image,"label");
2237 (void) WriteBlobMSBLong(image, 16);
2238 (void) WriteBlobMSBLong(image, 0);
2239 (void) WriteBlobMSBLong(image, 0);
2240 (void) FormatMagickString((char *) layer_name,MaxTextExtent,"L%06ld",
2242 WritePascalString( image, (char*)layer_name, 4 );
2244 size_t length=strlen(theAttr)+(4-(length % 4))+1;
2245 (void) WriteBlobMSBLong(image, length+8);
2246 (void) WriteBlobMSBLong(image, 0);
2247 (void) WriteBlobMSBLong(image, 0);
2248 WritePascalString( image, theAttr, 4 );
2250 tmp_image = GetNextImageInList(tmp_image);
2253 /* now the image data! */
2254 tmp_image = base_image;
2255 while ( tmp_image != NULL ) {
2256 status=WriteImageChannels(&psd_info,image_info,image,tmp_image,MagickTrue);
2258 /* add in the pad! */
2259 if ( rounded_layer_info_size != layer_info_size )
2260 (void) WriteBlobByte(image,'\0');
2262 tmp_image = GetNextImageInList(tmp_image);
2265 /* user mask data */
2266 (void) WriteBlobMSBLong(image, 0);
2270 /* now the background image data! */
2271 if (force_white_background != MagickFalse)
2272 WriteWhiteBackground(&psd_info,image);
2274 status=WriteImageChannels(&psd_info,image_info,image,image,MagickFalse);
2276 (void) CloseBlob(image);