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)
395 if (LocaleNCompare((const char *) magick,"8BPB",4) == 0)
401 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
405 % R e a d P S D I m a g e %
409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411 % ReadPSDImage() reads an Adobe Photoshop image file and returns it. It
412 % allocates the memory necessary for the new Image structure and returns a
413 % pointer to the new image.
415 % The format of the ReadPSDImage method is:
417 % image=ReadPSDImage(image_info)
419 % A description of each parameter follows:
421 % o image_info: the image info.
423 % o exception: return any errors or warnings in this structure.
427 static inline MagickOffsetType GetPSDOffset(PSDInfo *psd_info,Image *image)
429 if (psd_info->version == 1)
430 return((MagickOffsetType) ReadBlobMSBShort(image));
431 return((MagickOffsetType) ReadBlobMSBLong(image));
434 static inline MagickSizeType GetPSDSize(PSDInfo *psd_info,Image *image)
436 if (psd_info->version == 1)
437 return((MagickSizeType) ReadBlobMSBLong(image));
438 return((MagickSizeType) ReadBlobMSBLongLong(image));
441 static inline long MagickAbsoluteValue(const long x)
448 static CompositeOperator PSDBlendModeToCompositeOperator(const char *mode)
450 if (mode == (const char *) NULL)
451 return(OverCompositeOp);
452 if (LocaleNCompare(mode,"norm",4) == 0)
453 return(OverCompositeOp);
454 if (LocaleNCompare(mode,"mul ",4) == 0)
455 return(MultiplyCompositeOp);
456 if (LocaleNCompare(mode,"diss",4) == 0)
457 return(DissolveCompositeOp);
458 if (LocaleNCompare(mode,"diff",4) == 0)
459 return(DifferenceCompositeOp);
460 if (LocaleNCompare(mode,"dark",4) == 0)
461 return(DarkenCompositeOp);
462 if (LocaleNCompare(mode,"lite",4) == 0)
463 return(LightenCompositeOp);
464 if (LocaleNCompare(mode,"hue ",4) == 0)
465 return(HueCompositeOp);
466 if (LocaleNCompare(mode,"sat ",4) == 0)
467 return(SaturateCompositeOp);
468 if (LocaleNCompare(mode,"colr",4) == 0)
469 return(ColorizeCompositeOp);
470 if (LocaleNCompare(mode,"lum ",4) == 0)
471 return(LuminizeCompositeOp);
472 if (LocaleNCompare(mode,"scrn",4) == 0)
473 return(ScreenCompositeOp);
474 if (LocaleNCompare(mode,"over",4) == 0)
475 return(OverlayCompositeOp);
476 if (LocaleNCompare(mode,"hLit",4) == 0)
477 return(OverCompositeOp);
478 if (LocaleNCompare(mode,"sLit",4) == 0)
479 return(OverCompositeOp);
480 if (LocaleNCompare(mode,"smud",4) == 0)
481 return(OverCompositeOp);
482 if (LocaleNCompare(mode,"div ",4) == 0)
483 return(OverCompositeOp);
484 if (LocaleNCompare(mode,"idiv",4) == 0)
485 return(OverCompositeOp);
486 return(OverCompositeOp);
489 static const char *CompositeOperatorToPSDBlendMode(CompositeOperator inOp)
496 case OverCompositeOp: outMode = "norm"; break;
497 case MultiplyCompositeOp: outMode = "mul "; break;
498 case DissolveCompositeOp: outMode = "diss"; break;
499 case DifferenceCompositeOp: outMode = "diff"; break;
500 case DarkenCompositeOp: outMode = "dark"; break;
501 case LightenCompositeOp: outMode = "lite"; break;
502 case HueCompositeOp: outMode = "hue "; break;
503 case SaturateCompositeOp: outMode = "sat "; break;
504 case ColorizeCompositeOp: outMode = "colr"; break;
505 case LuminizeCompositeOp: outMode = "lum "; break;
506 case ScreenCompositeOp: outMode = "scrn"; break;
507 case OverlayCompositeOp: outMode = "over"; break;
514 static const char *ModeToString( PSDImageType inType )
518 case BitmapMode: return "Bitmap";
519 case GrayscaleMode: return "Grayscale";
520 case IndexedMode: return "Indexed";
521 case RGBMode: return "RGB";
522 case CMYKMode: return "CMYK";
523 case MultichannelMode: return "Multichannel";
524 case DuotoneMode: return "Duotone";
525 case LabMode: return "L*A*B";
526 default: return "unknown";
530 static MagickBooleanType ParseImageResourceBlocks(Image *image,
531 const unsigned char *blocks,size_t length)
549 profile=AcquireStringInfo(length);
550 SetStringInfoDatum(profile,blocks);
551 (void) SetImageProfile(image,"8bim",profile);
552 profile=DestroyStringInfo(profile);
553 for (p=blocks; (p >= blocks) && (p < (blocks+length-16)); )
555 if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
557 p=PushLongPixel(LSBEndian,p,&long_sans);
558 p=PushShortPixel(LSBEndian,p,&id);
559 p=PushShortPixel(LSBEndian,p,&short_sans);
560 p=PushLongPixel(LSBEndian,p,&count);
571 p=PushShortPixel(LSBEndian,p,&resolution);
572 image->x_resolution=(double) resolution;
573 p=PushShortPixel(LSBEndian,p,&short_sans);
574 p=PushShortPixel(LSBEndian,p,&short_sans);
575 p=PushShortPixel(LSBEndian,p,&short_sans);
576 p=PushShortPixel(LSBEndian,p,&resolution);
577 image->y_resolution=(double) resolution;
578 p=PushShortPixel(LSBEndian,p,&short_sans);
579 p=PushShortPixel(LSBEndian,p,&short_sans);
580 p=PushShortPixel(LSBEndian,p,&short_sans);
589 if ((count & 0x01) != 0)
595 static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception)
653 skip_first_alpha = 0;
658 assert(image_info != (const ImageInfo *) NULL);
659 assert(image_info->signature == MagickSignature);
660 if (image_info->debug != MagickFalse)
661 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
662 image_info->filename);
663 assert(exception != (ExceptionInfo *) NULL);
664 assert(exception->signature == MagickSignature);
665 image=AcquireImage(image_info);
666 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
667 if (status == MagickFalse)
669 image=DestroyImageList(image);
670 return((Image *) NULL);
675 count=ReadBlob(image,4,(unsigned char *) psd_info.signature);
676 psd_info.version=ReadBlobMSBShort(image);
677 if ((count == 0) || ((LocaleNCompare(psd_info.signature,"8BPS",4) != 0) &&
678 (LocaleNCompare(psd_info.signature,"8BPB",4) != 0)) ||
679 ((psd_info.version != 1) && (psd_info.version != 2)))
680 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
681 count=ReadBlob(image,6,psd_info.reserved);
682 psd_info.channels=ReadBlobMSBShort(image);
683 if (psd_info.channels > MaxPSDChannels)
684 ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
685 psd_info.rows=ReadBlobMSBLong(image);
686 psd_info.columns=ReadBlobMSBLong(image);
687 if ((psd_info.version == 1) && ((psd_info.rows > 30000) ||
688 (psd_info.columns > 30000)))
689 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
690 if ((psd_info.version == 1) && ((psd_info.rows > 300000) ||
691 (psd_info.columns > 300000)))
692 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
693 psd_info.depth=ReadBlobMSBShort(image);
694 if ((psd_info.depth != 1) && (psd_info.depth != 8) && (psd_info.depth != 16))
695 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
696 psd_info.mode=ReadBlobMSBShort(image);
697 if (image->debug != MagickFalse)
698 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
699 " Image is %ld x %ld with channels=%d, depth=%d, mode=%s",
700 psd_info.columns,psd_info.rows,psd_info.channels,psd_info.depth,
701 ModeToString((PSDImageType) psd_info.mode));
705 image->depth=psd_info.depth;
706 image->columns=psd_info.columns;
707 image->rows=psd_info.rows;
708 if (SetImageBackgroundColor(image) == MagickFalse)
710 InheritException(exception,&image->exception);
711 image=DestroyImageList(image);
712 return((Image *) NULL);
714 image->matte=psd_info.channels >= 4 ? MagickTrue : MagickFalse;
715 if (psd_info.mode == LabMode)
716 image->colorspace=LabColorspace;
717 if (psd_info.mode == CMYKMode)
719 image->colorspace=CMYKColorspace;
720 image->matte=psd_info.channels >= 5 ? MagickTrue : MagickFalse;
722 if ((psd_info.mode == BitmapMode) || (psd_info.mode == GrayscaleMode) ||
723 (psd_info.mode == DuotoneMode))
725 if (AcquireImageColormap(image,256) == MagickFalse)
726 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
727 image->matte=psd_info.channels >= 2 ? MagickTrue : MagickFalse;
728 if (image->debug != MagickFalse)
729 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
730 " ImageColorMap allocated");
732 if (image->debug != MagickFalse)
733 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
734 image->matte ? " image has matte" : " image has no matte");
736 Read PSD raster colormap only present for indexed and duotone images.
738 length=ReadBlobMSBLong(image);
741 if (image->debug != MagickFalse)
742 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
743 " reading colormap");
744 if (psd_info.mode == DuotoneMode)
747 Duotone image data; the format of this data is undocumented.
749 data=(unsigned char *) AcquireQuantumMemory(length,sizeof(*data));
750 if (data == (unsigned char *) NULL)
751 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
752 count=ReadBlob(image,length,data);
753 data=(unsigned char *) RelinquishMagickMemory(data);
758 Read PSD raster colormap.
760 if (AcquireImageColormap(image,(unsigned long) (length/3)) == MagickFalse)
761 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
762 for (i=0; i < (long) image->colors; i++)
763 image->colormap[i].red=ScaleCharToQuantum((unsigned char)
764 ReadBlobByte(image));
765 for (i=0; i < (long) image->colors; i++)
766 image->colormap[i].green=ScaleCharToQuantum((unsigned char)
767 ReadBlobByte(image));
768 for (i=0; i < (long) image->colors; i++)
769 image->colormap[i].blue=ScaleCharToQuantum((unsigned char)
770 ReadBlobByte(image));
771 image->matte=psd_info.channels >= 2 ? MagickTrue : MagickFalse;
774 length=ReadBlobMSBLong(image);
781 Image resources block.
783 if (image->debug != MagickFalse)
784 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
785 " reading image resource blocks - %ld bytes",(long) length);
786 blocks=(unsigned char *) AcquireQuantumMemory(length,sizeof(*blocks));
787 if (blocks == (unsigned char *) NULL)
788 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
789 count=ReadBlob(image,length,blocks);
790 if (((size_t) count != length) ||
791 (LocaleNCompare((char *) blocks,"8BIM",4) != 0))
793 blocks=(unsigned char *) RelinquishMagickMemory(blocks);
794 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
796 (void) ParseImageResourceBlocks(image,blocks,length);
797 blocks=(unsigned char *) RelinquishMagickMemory(blocks);
800 If we are only "pinging" the image, then we're done - so return.
802 if (image_info->ping != MagickFalse)
804 (void) CloseBlob(image);
805 return(GetFirstImageInList(image));
808 Layer and mask block.
810 layer_info=(LayerInfo *) NULL;
812 length=GetPSDSize(&psd_info,image);
815 length=ReadBlobMSBLong(image);
816 length=ReadBlobMSBLong(image);
818 if ((image_info->number_scenes == 1) && (image_info->scene == 0))
819 for ( ; length != 0; length--)
820 if (ReadBlobByte(image) == EOF)
822 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
828 if (image->debug != MagickFalse)
829 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
830 " image has no layers");
834 offset=TellBlob(image);
835 size=GetPSDSize(&psd_info,image);
844 quantum=psd_info.version == 1 ? 4 : 8;
845 for (j=0; j < (long) (length-quantum); j++)
846 (void) ReadBlobByte(image);
853 layer_offset=offset+length;
854 number_layers=(short) ReadBlobMSBShort(image);
855 if (image->debug != MagickFalse)
856 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
857 " image contains %ld layers", number_layers);
858 if (number_layers < 0)
861 Weird hack in PSD format to ignore first alpha channel.
864 number_layers=MagickAbsoluteValue(number_layers);
865 if (image->debug != MagickFalse)
866 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
867 " negative layer count corrected for");
869 layer_info=(LayerInfo *) AcquireQuantumMemory((size_t) number_layers,
870 sizeof(*layer_info));
871 if (layer_info == (LayerInfo *) NULL)
873 if (image->debug != MagickFalse)
874 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
875 " allocation of LayerInfo failed");
876 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
878 (void) ResetMagickMemory(layer_info,0,(size_t) number_layers*
879 sizeof(*layer_info));
880 for (i=0; i < number_layers; i++)
882 if (image->debug != MagickFalse)
883 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
884 " reading layer #%ld",i+1);
885 layer_info[i].page.y=(long) ReadBlobMSBLong(image);
886 layer_info[i].page.x=(long) ReadBlobMSBLong(image);
887 layer_info[i].page.height=ReadBlobMSBLong(image)-layer_info[i].page.y;
888 layer_info[i].page.width=ReadBlobMSBLong(image)-layer_info[i].page.x;
889 layer_info[i].channels=ReadBlobMSBShort(image);
890 if (layer_info[i].channels > MaxPSDChannels)
891 ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
892 if (image->debug != MagickFalse)
893 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
894 " offset(%ld,%ld), size(%ld,%ld), channels=%d",
895 layer_info[i].page.x, layer_info[i].page.y,
896 layer_info[i].page.height,layer_info[i].page.width,
897 layer_info[i].channels);
898 for (j=0; j < (long) layer_info[i].channels; j++)
900 layer_info[i].channel_info[j].type=(short) ReadBlobMSBShort(image);
901 layer_info[i].channel_info[j].size=ReadBlobMSBLong(image);
902 if (image->debug != MagickFalse)
903 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
904 " channel[%ld]: type=%d, size=%ld",j,
905 layer_info[i].channel_info[j].type,
906 (long) layer_info[i].channel_info[j].size);
908 count=ReadBlob(image,4,(unsigned char *) type);
909 if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0))
911 if (image->debug != MagickFalse)
912 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
913 " layer type was %.4s instead of 8BIM", type);
914 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
916 count=ReadBlob(image,4,(unsigned char *) layer_info[i].blendkey);
917 layer_info[i].opacity=(Quantum) (QuantumRange-ScaleCharToQuantum(
918 (unsigned char) ReadBlobByte(image)));
919 layer_info[i].clipping=(unsigned char) ReadBlobByte(image);
920 layer_info[i].flags=(unsigned char) ReadBlobByte(image);
921 layer_info[i].visible=!(layer_info[i].flags & 0x02);
922 if (image->debug != MagickFalse)
923 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
924 " blend=%.4s, opacity=%lu, clipping=%s, flags=%d, visible=%s",
925 layer_info[i].blendkey,(unsigned long) layer_info[i].opacity,
926 layer_info[i].clipping ? "true" : "false",layer_info[i].flags,
927 layer_info[i].visible ? "true" : "false");
928 (void) ReadBlobByte(image); /* filler */
930 size=ReadBlobMSBLong(image);
933 if (image->debug != MagickFalse)
934 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
935 " layer contains additional info");
936 length=ReadBlobMSBLong(image);
942 layer_info[i].mask.y=(long) ReadBlobMSBLong(image);
943 layer_info[i].mask.x=(long) ReadBlobMSBLong(image);
944 layer_info[i].mask.height=
945 (ReadBlobMSBLong(image)-layer_info[i].mask.y);
946 layer_info[i].mask.width=
947 (ReadBlobMSBLong(image)-layer_info[i].mask.x);
948 if (image->debug != MagickFalse)
949 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
950 " layer mask: offset(%ld,%ld), size(%ld,%ld), length=%ld",
951 layer_info[i].mask.x,layer_info[i].mask.y,
952 layer_info[i].mask.width, layer_info[i].mask.height,
955 Skip over the rest of the layer mask information.
957 for (j=0; j < (long) (length-16); j++)
958 (void) ReadBlobByte(image);
960 combinedlength+=length+4; /* +4 for length */
961 length=ReadBlobMSBLong(image);
965 Layer blending ranges info.
967 if (image->debug != MagickFalse)
968 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
969 " layer blending ranges: length=%ld",(long) length);
971 We read it, but don't use it...
973 for (j=0; j < (long) (length); j+=8)
975 size_t blend_source=ReadBlobMSBLong(image);
976 size_t blend_dest=ReadBlobMSBLong(image);
977 if (image->debug != MagickFalse)
978 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
979 " source(%x), dest(%x)",(unsigned int)
980 blend_source,(unsigned int) blend_dest);
983 combinedlength+=length+4;
987 length=(size_t) ReadBlobByte(image);
988 for (j=0; j < (long) length; j++)
989 layer_info[i].name[j]=(unsigned char) ReadBlobByte(image);
990 layer_info[i].name[j]='\0';
991 if (image->debug != MagickFalse)
992 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
993 " layer name: %s",layer_info[i].name);
994 combinedlength+=length+1;
996 #if 0 /* still in development */
998 Adjustment layers and other stuff...
1004 count=ReadBlob(image,4,alsig);
1005 if ((count == 0) || (LocaleNCompare(alsig,"8BIM",4) != 0)) {
1006 if (debug != MagickFalse)
1008 if (image->debug != MagickFalse)
1009 (void) LogMagickEvent(CoderEvent,GetMagickModule()," adjustment layer type was %.4s instead of 8BIM", alsig);
1011 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1013 count=ReadBlob(image,4,alkey);
1014 length=ReadBlobMSBLong(image);
1015 if (debug != MagickFalse)
1017 if (image->debug != MagickFalse)
1018 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1019 " adjustment layer key: %.4s, data length=%ld",
1024 for (j=0; j < (long) (length); j++)
1025 (void) ReadBlobByte(image);
1029 combinedlength += 12 + length; /* sig, key, length + the actual length*/
1033 Skip the rest of the variable data until we support it.
1035 if (image->debug != MagickFalse)
1036 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1037 " unsupported data: length=%ld",(long)
1038 (size-combinedlength));
1039 for (j=0; j < (long) (size-combinedlength); j++)
1040 (void) ReadBlobByte(image);
1043 Allocate layered image.
1045 layer_info[i].image=CloneImage(image,layer_info[i].page.width,
1046 layer_info[i].page.height,MagickFalse,&image->exception);
1047 if (layer_info[i].image == (Image *) NULL)
1049 for (j=0; j < i; j++)
1050 layer_info[j].image=DestroyImage(layer_info[j].image);
1051 if (image->debug != MagickFalse)
1052 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1053 " allocation of image for layer %ld failed", i);
1054 ThrowReaderException(ResourceLimitError,
1055 "MemoryAllocationFailed");
1057 if (image->debug != MagickFalse)
1058 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1059 " setting up new layer image");
1060 (void) SetImageBackgroundColor(layer_info[i].image);
1061 layer_info[i].image->compose=
1062 PSDBlendModeToCompositeOperator(layer_info[i].blendkey);
1063 if (layer_info[i].visible == MagickFalse)
1064 layer_info[i].image->compose=NoCompositeOp;
1065 if (psd_info.mode == CMYKMode)
1066 image->colorspace=CMYKColorspace;
1067 for (j=0; j < (long) layer_info[i].channels; j++)
1068 if (layer_info[i].channel_info[j].type == -1)
1069 layer_info[i].image->matte=MagickTrue;
1071 Set up some hidden attributes for folks that need them.
1073 (void) FormatMagickString(s,MaxTextExtent,"%ld",
1074 layer_info[i].page.x );
1075 (void) SetImageArtifact(layer_info[i].image,"psd:layer.x",s);
1076 (void) FormatMagickString(s,MaxTextExtent,"%ld",
1077 layer_info[i].page.y);
1078 (void) SetImageArtifact(layer_info[i].image,"psd:layer.y",s);
1079 (void) FormatMagickString(s,MaxTextExtent,"%lu",(unsigned long)
1080 layer_info[i].opacity );
1081 (void) SetImageArtifact(layer_info[i].image,"psd:layer.opacity",s);
1082 (void) SetImageProperty(layer_info[i].image,"label",(char *)
1083 layer_info[i].name);
1085 if (image->debug != MagickFalse)
1086 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1087 " reading image data for layers");
1089 Read pixel data for each layer.
1091 for (i=0; i < number_layers; i++)
1093 if (image->debug != MagickFalse)
1094 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1095 " reading data for layer %ld",i);
1096 for (j=0; j < (long) layer_info[i].channels; j++)
1098 if (image->debug != MagickFalse)
1099 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1100 " reading data for channel %ld", j);
1102 if (layer_info[i].channel_info[j].size <= (2*layer_info[i].image->rows))
1107 if (image->debug != MagickFalse)
1108 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1109 " layer data is empty");
1111 A layer without data.
1113 for (k=0; k < (long) layer_info[i].channel_info[j].size; k++)
1114 (void) ReadBlobByte(layer_info[i].image);
1118 compression=ReadBlobMSBShort(layer_info[i].image);
1119 if ((layer_info[i].page.height != 0) &&
1120 (layer_info[i].page.width != 0))
1122 if (compression == 1)
1125 Read RLE compressed data.
1127 if (image->debug != MagickFalse)
1128 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1129 " layer data is RLE compressed");
1130 for (y=0; y < (long) layer_info[i].image->rows; y++)
1131 (void) GetPSDOffset(&psd_info,layer_info[i].image);
1132 (void) DecodeImage(layer_info[i].image,
1133 layer_info[i].channel_info[j].type);
1137 Read uncompressed pixel datas separate planes.
1139 if (image->debug != MagickFalse)
1140 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1141 " layer data is uncompressed");
1143 if (layer_info[i].image->storage_class == PseudoClass)
1145 if (layer_info[i].image->colors > 256)
1148 if (layer_info[i].image->depth > 8)
1152 if (layer_info[i].image->depth > 8)
1154 for (y=0; y < (long) layer_info[i].image->rows; y++)
1156 q=GetAuthenticPixels(layer_info[i].image,0,y,
1157 layer_info[i].image->columns,1,exception);
1158 if (q == (PixelPacket *) NULL)
1160 indexes=GetAuthenticIndexQueue(layer_info[i].image);
1161 for (x=0; x < (long) layer_info[i].image->columns; x++)
1163 if (packet_size == 1)
1164 pixel=(unsigned long) ScaleCharToQuantum((unsigned char)
1165 ReadBlobByte(layer_info[i].image));
1167 pixel=(unsigned long) ScaleShortToQuantum(
1168 ReadBlobMSBShort(layer_info[i].image));
1169 switch (layer_info[i].channel_info[j].type)
1171 case -1: /* transparency mask */
1173 q->opacity=(Quantum) (QuantumRange-pixel);
1176 case 0: /* first component (Red, Cyan, Gray or Index) */
1178 q->red=(Quantum) pixel;
1179 if (layer_info[i].image->storage_class == PseudoClass)
1181 if (packet_size == 1)
1182 indexes[x]=(IndexPacket) ScaleQuantumToChar(
1185 indexes[x]=(IndexPacket) ScaleQuantumToShort(
1187 q->red=layer_info[i].image->colormap[(long) *indexes].red;
1188 q->green=layer_info[i].image->colormap[(long) *indexes].green;
1189 q->blue=layer_info[i].image->colormap[(long) *indexes].blue;
1193 case 1: /* second component (Green, Magenta, or opacity) */
1195 if (layer_info[i].image->storage_class == PseudoClass)
1196 q->opacity=(Quantum) (QuantumRange-pixel);
1198 q->green=(Quantum) pixel;
1201 case 2: /* third component (Blue or Yellow) */
1203 q->blue=(Quantum) pixel;
1206 case 3: /* fourth component (Opacity or Black) */
1208 if (image->colorspace == CMYKColorspace)
1209 indexes[x]=(Quantum) pixel;
1211 q->opacity=(Quantum) (QuantumRange-pixel);
1214 case 4: /* fifth component (opacity) */
1216 q->opacity=(Quantum) (QuantumRange-pixel);
1224 if (SyncAuthenticPixels(layer_info[i].image,exception) == MagickFalse)
1229 if (layer_info[i].opacity != OpaqueOpacity)
1232 Correct for opacity level.
1234 for (y=0; y < (long) layer_info[i].image->rows; y++)
1236 q=GetAuthenticPixels(layer_info[i].image,0,y,
1237 layer_info[i].image->columns,1,exception);
1238 if (q == (PixelPacket *) NULL)
1240 indexes=GetAuthenticIndexQueue(layer_info[i].image);
1241 for (x=0; x < (long) layer_info[i].image->columns; x++)
1243 q->opacity=(Quantum) (QuantumRange-(Quantum) (QuantumScale*
1244 ((QuantumRange-q->opacity)*(QuantumRange-
1245 layer_info[i].opacity))));
1248 if (SyncAuthenticPixels(layer_info[i].image,exception) == MagickFalse)
1252 if (layer_info[i].image->colorspace == CMYKColorspace)
1253 (void) NegateImage(layer_info[i].image,MagickFalse);
1254 status=SetImageProgress(image,LoadImagesTag,i,number_layers);
1255 if (status == MagickFalse)
1258 /* added by palf -> invisible group layer make layer of this group
1259 invisible I consider that all layer with width and height null are
1260 layer for group layer */
1262 short inside_layer = 0;
1263 short layer_visible = 0;
1264 for (i=number_layers-1; i >=0; i--)
1266 if ((layer_info[i].page.width == 0) ||
1267 (layer_info[i].page.height == 0))
1269 if (inside_layer == 0)
1272 layer_visible=(short int) layer_info[i].visible;
1280 if ((inside_layer == 1) && (layer_visible == 0))
1282 layer_info[i].visible=(unsigned char) layer_visible;
1283 layer_info[i].image->compose=NoCompositeOp;
1287 /* added by palf -> suppression of empty layer */
1288 /* I consider that all layer with width and height null are layer for group layer */
1289 for (i=0; i < number_layers; i++)
1291 if ((layer_info[i].page.width == 0) ||
1292 (layer_info[i].page.height == 0))
1294 if (layer_info[i].image != (Image *) NULL)
1295 layer_info[i].image=DestroyImage(layer_info[i].image);
1296 for (j=i; j < number_layers - 1; j++)
1297 layer_info[j] = layer_info[j+1];
1302 mask_size = ReadBlobMSBLong(image); /* global mask size: currently ignored */
1303 if (number_layers > 0)
1306 if (image->debug != MagickFalse)
1307 (void) LogMagickEvent(CoderEvent,GetMagickModule()," putting layers into image list");
1308 for (i=0; i < number_layers; i++)
1311 layer_info[i].image->previous=layer_info[i-1].image;
1312 if (i < (number_layers-1))
1313 layer_info[i].image->next=layer_info[i+1].image;
1314 layer_info[i].image->page=layer_info[i].page;
1316 image->next=layer_info[0].image;
1317 layer_info[0].image->previous=image;
1318 layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
1321 layer_offset-=TellBlob(image);
1322 offset=SeekBlob(image,layer_offset,SEEK_CUR);
1326 Read the precombined layer, present for PSD < 4 compatibility
1328 if (image->debug != MagickFalse)
1329 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1330 " reading the precombined layer");
1331 compression=ReadBlobMSBShort(image);
1332 if (compression == 1)
1335 Read Packbit encoded pixel datas separate planes.
1337 for (i=0; i < (long) (image->rows*psd_info.channels); i++)
1338 (void) GetPSDOffset(&psd_info,image);
1339 for (i=0; i < (long) psd_info.channels; i++)
1341 (void) DecodeImage(image,(int) i);
1342 status=SetImageProgress(image,LoadImagesTag,i,psd_info.channels);
1343 if (status == MagickFalse)
1350 Read uncompressed pixel data separate planes.
1353 if (image->storage_class == PseudoClass)
1355 if (image->colors > 256)
1358 if (image->depth > 8)
1362 if (image->depth > 8)
1364 for (i=0; i < (long) psd_info.channels; i++)
1366 for (y=0; y < (long) image->rows; y++)
1368 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
1369 if (q == (PixelPacket *) NULL)
1371 indexes=GetAuthenticIndexQueue(image);
1372 for (x=0; x < (long) image->columns; x++)
1374 if (packet_size == 1)
1375 pixel=(unsigned long) ScaleCharToQuantum((unsigned char)
1376 ReadBlobByte(image));
1378 pixel=(unsigned long) ScaleShortToQuantum(
1379 ReadBlobMSBShort(image));
1384 q->opacity=(Quantum) (QuantumRange-pixel);
1389 q->red=(Quantum) pixel;
1390 if (psd_info.channels == 1)
1395 if (image->storage_class == PseudoClass)
1397 if (packet_size == 1)
1398 indexes[x]=(IndexPacket) ScaleQuantumToChar((Quantum)
1401 indexes[x]=(IndexPacket) ScaleQuantumToShort((Quantum)
1403 *q=image->colormap[(long) indexes[x]];
1404 q->red=image->colormap[(long) indexes[x]].red;
1405 q->green=image->colormap[(long) indexes[x]].green;
1406 q->blue=image->colormap[(long) indexes[x]].blue;
1412 if (image->storage_class == PseudoClass)
1413 q->opacity=(Quantum) (QuantumRange-pixel);
1415 q->green=(Quantum) pixel;
1420 q->blue=(Quantum) pixel;
1425 if (image->colorspace == CMYKColorspace)
1426 indexes[x]=(IndexPacket) pixel;
1428 q->opacity=(Quantum) (QuantumRange-pixel);
1433 q->opacity=(Quantum) (QuantumRange-pixel);
1441 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1444 status=SetImageProgress(image,LoadImagesTag,i,psd_info.channels);
1445 if (status == MagickFalse)
1449 if (image->colorspace == CMYKColorspace)
1450 (void) NegateImage(image,MagickFalse);
1451 (void) CloseBlob(image);
1452 return(GetFirstImageInList(image));
1456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1460 % R e g i s t e r P S D I m a g e %
1464 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1466 % RegisterPSDImage() adds properties for the PSD image format to
1467 % the list of supported formats. The properties include the image format
1468 % tag, a method to read and/or write the format, whether the format
1469 % supports the saving of more than one frame to the same file or blob,
1470 % whether the format supports native in-memory I/O, and a brief
1471 % description of the format.
1473 % The format of the RegisterPSDImage method is:
1475 % unsigned long RegisterPSDImage(void)
1478 ModuleExport unsigned long RegisterPSDImage(void)
1483 entry=SetMagickInfo("PSB");
1484 entry->decoder=(DecodeImageHandler *) ReadPSDImage;
1485 entry->encoder=(EncodeImageHandler *) WritePSDImage;
1486 entry->magick=(IsImageFormatHandler *) IsPSD;
1487 entry->description=ConstantString("Adobe Large Document Format");
1488 entry->module=ConstantString("PSD");
1489 (void) RegisterMagickInfo(entry);
1490 entry=SetMagickInfo("PSD");
1491 entry->decoder=(DecodeImageHandler *) ReadPSDImage;
1492 entry->encoder=(EncodeImageHandler *) WritePSDImage;
1493 entry->magick=(IsImageFormatHandler *) IsPSD;
1494 entry->description=ConstantString("Adobe Photoshop bitmap");
1495 entry->module=ConstantString("PSD");
1496 (void) RegisterMagickInfo(entry);
1497 return(MagickImageCoderSignature);
1501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1505 % U n r e g i s t e r P S D I m a g e %
1509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1511 % UnregisterPSDImage() removes format registrations made by the
1512 % PSD module from the list of supported formats.
1514 % The format of the UnregisterPSDImage method is:
1516 % UnregisterPSDImage(void)
1519 ModuleExport void UnregisterPSDImage(void)
1521 (void) UnregisterMagickInfo("PSB");
1522 (void) UnregisterMagickInfo("PSD");
1526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1530 % W r i t e P S D I m a g e %
1534 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1536 % WritePSDImage() writes an image in the Adobe Photoshop encoded image
1539 % The format of the WritePSDImage method is:
1541 % MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image)
1543 % A description of each parameter follows.
1545 % o image_info: the image info.
1547 % o image: The image.
1552 static inline ssize_t SetPSDOffset(PSDInfo *psd_info,Image *image,
1553 const size_t offset)
1555 if (psd_info->version == 1)
1556 return(WriteBlobMSBShort(image,offset));
1557 return(WriteBlobMSBLong(image,offset));
1560 static inline ssize_t SetPSDSize(PSDInfo *psd_info,Image *image,
1561 const MagickSizeType size)
1563 if (psd_info->version == 1)
1564 return(WriteBlobMSBLong(image,(unsigned long) size));
1565 return(WriteBlobMSBLongLong(image,size));
1568 static size_t PSDPackbitsEncodeImage(Image *image,const size_t length,
1569 const unsigned char *pixels,unsigned char *compressed_pixels)
1578 register unsigned char
1585 Compress pixels with Packbits encoding.
1587 assert(image != (Image *) NULL);
1588 assert(image->signature == MagickSignature);
1589 if (image->debug != MagickFalse)
1590 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1591 assert(pixels != (unsigned char *) NULL);
1592 packbits=(unsigned char *) AcquireQuantumMemory(128UL,sizeof(*packbits));
1593 if (packbits == (unsigned char *) NULL)
1594 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1596 q=compressed_pixels;
1597 for (i=(long) length; i != 0; )
1604 *q++=(unsigned char) 0;
1611 *q++=(unsigned char) 1;
1619 if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1621 *q++=(unsigned char) ((256-3)+1);
1625 *q++=(unsigned char) 2;
1633 if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1639 while (((long) count < i) && (*pixels == *(pixels+count)))
1646 *q++=(unsigned char) ((256-count)+1);
1655 while ((*(pixels+count) != *(pixels+count+1)) ||
1656 (*(pixels+count+1) != *(pixels+count+2)))
1658 packbits[count+1]=pixels[count];
1660 if (((long) count >= (i-3)) || (count >= 127))
1664 *packbits=(unsigned char) (count-1);
1665 for (j=0; j <= (long) count; j++)
1672 *q++=(unsigned char) 128; /* EOD marker */
1673 packbits=(unsigned char *) RelinquishMagickMemory(packbits);
1674 return(q-compressed_pixels);
1677 static void WritePackbitsLength(const ImageInfo *image_info,Image *image,
1678 Image *tmp_image,unsigned char *pixels,unsigned char *compressed_pixels,
1679 const QuantumType quantum_type)
1687 register const PixelPacket
1694 if (tmp_image->depth > 8)
1695 tmp_image->depth=16;
1696 packet_size=tmp_image->depth > 8UL ? 2UL : 1UL;
1697 quantum_info=AcquireQuantumInfo(image_info,image);
1698 for (y=0; y < (long) tmp_image->rows; y++)
1700 p=GetVirtualPixels(tmp_image,0,y,tmp_image->columns,1,&image->exception);
1701 if (p == (const PixelPacket *) NULL)
1703 length=ExportQuantumPixels(tmp_image,(CacheView *) NULL,quantum_info,
1704 quantum_type,pixels,&image->exception);
1705 length=PSDPackbitsEncodeImage(image,length,pixels,compressed_pixels);
1706 (void) WriteBlobMSBShort(image,length);
1708 quantum_info=DestroyQuantumInfo(quantum_info);
1711 static void WriteOneChannel(const ImageInfo *image_info,Image *image,
1712 Image *tmp_image,unsigned char *pixels,unsigned char *compressed_pixels,
1713 const QuantumType quantum_type,const MagickBooleanType compression_flag)
1721 register const PixelPacket
1728 if ((compression_flag != MagickFalse) &&
1729 (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 (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 ImageInfo *image_info,
1754 Image *image,Image *tmp_image,const MagickBooleanType separate)
1768 Write uncompressed pixel datas separate planes.
1771 if ((tmp_image->storage_class == PseudoClass) &&
1772 (tmp_image->matte == MagickFalse))
1774 packet_size=tmp_image->depth > 8UL ? 2UL : 1UL;
1775 pixels=(unsigned char *) AcquireQuantumMemory(channels*tmp_image->columns,
1776 packet_size*sizeof(*pixels));
1777 compressed_pixels=(unsigned char *) AcquireQuantumMemory(2*channels*
1778 tmp_image->columns,packet_size*sizeof(*pixels));
1779 if ((pixels == (unsigned char *) NULL) ||
1780 (compressed_pixels == (unsigned char *) NULL))
1782 if (pixels != (unsigned char *) NULL)
1783 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1784 if (compressed_pixels != (unsigned char *) NULL)
1785 compressed_pixels=(unsigned char *)
1786 RelinquishMagickMemory(compressed_pixels);
1787 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1790 if (tmp_image->storage_class == PseudoClass)
1792 if (image->compression != NoCompression)
1795 Packbits compression.
1797 (void) WriteBlobMSBShort(image,1);
1798 if (tmp_image->matte == MagickFalse)
1799 WritePackbitsLength(image_info,image,tmp_image,pixels,
1800 compressed_pixels,IndexQuantum);
1802 WritePackbitsLength(image_info,image,tmp_image,pixels,
1803 compressed_pixels,IndexAlphaQuantum);
1805 if (tmp_image->matte == MagickFalse)
1806 WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1807 IndexQuantum,(i++ == 0) || (separate != MagickFalse) ?
1808 MagickTrue : MagickFalse);
1810 WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1811 IndexAlphaQuantum,(i++ == 0) || (separate != MagickFalse) ?
1812 MagickTrue : MagickFalse);
1813 (void) SetImageProgress(image,SaveImagesTag,0,1);
1817 if (tmp_image->colorspace == CMYKColorspace)
1818 (void) NegateImage(image,MagickFalse);
1819 if (image->compression != NoCompression)
1822 Packbits compression.
1824 (void) WriteBlobMSBShort(image,1);
1825 if (tmp_image->matte != MagickFalse)
1826 WritePackbitsLength(image_info,image,tmp_image,pixels,
1827 compressed_pixels,AlphaQuantum);
1828 WritePackbitsLength(image_info,image,tmp_image,pixels,
1829 compressed_pixels,RedQuantum);
1830 WritePackbitsLength(image_info,image,tmp_image,pixels,
1831 compressed_pixels,GreenQuantum);
1832 WritePackbitsLength(image_info,image,tmp_image,pixels,
1833 compressed_pixels,BlueQuantum);
1834 if (tmp_image->colorspace == CMYKColorspace)
1835 WritePackbitsLength(image_info,image,tmp_image,pixels,
1836 compressed_pixels,BlackQuantum);
1838 (void) SetImageProgress(image,SaveImagesTag,0,6);
1839 if (tmp_image->matte != MagickFalse)
1840 WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1841 AlphaQuantum,(i++ == 0) || (separate != MagickFalse) ?
1842 MagickTrue : MagickFalse);
1843 (void) SetImageProgress(image,SaveImagesTag,1,6);
1844 WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1845 RedQuantum,(i++ == 0) || (separate != MagickFalse) ?
1846 MagickTrue : MagickFalse);
1847 (void) SetImageProgress(image,SaveImagesTag,2,6);
1848 WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1849 GreenQuantum,(i++ == 0) || (separate != MagickFalse) ?
1850 MagickTrue : MagickFalse);
1851 (void) SetImageProgress(image,SaveImagesTag,3,6);
1852 WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1853 BlueQuantum,(i++ == 0) || (separate != MagickFalse) ?
1854 MagickTrue : MagickFalse);
1855 (void) SetImageProgress(image,SaveImagesTag,4,6);
1856 if (tmp_image->colorspace == CMYKColorspace)
1858 WriteOneChannel(image_info,image,tmp_image,pixels,compressed_pixels,
1859 BlackQuantum,(i++ == 0) || (separate != MagickFalse) ?
1860 MagickTrue : MagickFalse);
1861 (void) NegateImage(image,MagickFalse);
1863 (void) SetImageProgress(image,SaveImagesTag,5,6);
1865 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1869 /* Write white background, RLE-compressed */
1871 static void WriteWhiteBackground( Image* image )
1874 char *d, scanline[256];
1876 int numChannels = 3, dim = (int) (image->rows*numChannels);
1887 (void) WriteBlobMSBShort(image,1); /* RLE compressed */
1888 w8 = (long) image->columns;
1890 /* Set up scanline */
1891 for (w=w8; w > 128; w-=128)
1909 bytecount = d - scanline;
1911 /* Scanline counts (rows*channels) */
1912 for (i=0; i < dim; i++)
1914 (void) WriteBlobMSBShort(image,bytecount);
1917 /* RLE compressed data */
1919 for (i=0; i < dim; i++)
1921 (void) WriteBlob( image, length, (unsigned char *) scanline );
1926 static void WritePascalString(Image* inImage,const char *inString,int inPad)
1932 /* max length is 255 */
1934 strLength = (strlen(inString) > 255UL ) ? 255UL : strlen(inString);
1936 if ( strLength != 0 )
1938 (void) WriteBlobByte(inImage,(unsigned char) strLength);
1939 (void) WriteBlob(inImage, strLength, (const unsigned char *) inString);
1942 (void) WriteBlobByte(inImage, 0);
1946 if ( (strLength % inPad) == 0 )
1948 for (i=0; i < (long) (inPad-(strLength % inPad)); i++)
1949 (void) WriteBlobByte(inImage,0);
1952 static void WriteResolutionResourceBlock(Image *image)
1961 x_resolution=65536.0*image->x_resolution+0.5;
1962 y_resolution=65536.0*image->y_resolution+0.5;
1964 if (image->units == PixelsPerCentimeterResolution)
1966 x_resolution=2.54*65536.0*image->x_resolution*0.5;
1967 y_resolution=2.54*65536.0*image->y_resolution+0.5;
1970 (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
1971 (void) WriteBlobMSBShort(image,0x03ED);
1972 (void) WriteBlobMSBShort(image,0);
1973 (void) WriteBlobMSBLong(image,16); /* resource size */
1974 (void) WriteBlobMSBLong(image,x_resolution);
1975 (void) WriteBlobMSBShort(image,units); /* horizontal resolution unit */
1976 (void) WriteBlobMSBShort(image,units); /* width unit */
1977 (void) WriteBlobMSBLong(image,y_resolution);
1978 (void) WriteBlobMSBShort(image,units); /* vertical resolution unit */
1979 (void) WriteBlobMSBShort(image,units); /* height unit */
1982 static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image)
1991 force_white_background = image->matte,
1992 invert_layer_count = MagickFalse,
2010 rounded_layer_info_size,
2014 * tmp_image = (Image *) NULL,
2015 * base_image = force_white_background ? image : GetNextImageInList(image);
2018 Open output image file.
2020 assert(image_info != (const ImageInfo *) NULL);
2021 assert(image_info->signature == MagickSignature);
2022 assert(image != (Image *) NULL);
2023 assert(image->signature == MagickSignature);
2024 if (image->debug != MagickFalse)
2025 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2026 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
2027 if (status == MagickFalse)
2029 packet_size=(size_t) (image->depth > 8 ? 6 : 3);
2030 if (image->matte != MagickFalse)
2031 packet_size+=image->depth > 8 ? 2 : 1;
2032 (void) WriteBlob(image,4,(const unsigned char *) "8BPS");
2033 (void) WriteBlobMSBShort(image,1); /* version */
2034 for ( i=1; i<=6; i++)
2035 (void) WriteBlobByte(image, 0); /* 6 bytes of reserved */
2036 if ( force_white_background )
2040 if (image->storage_class == PseudoClass)
2041 num_channels=(image->matte ? 2UL : 1UL);
2044 if (image->colorspace != CMYKColorspace)
2045 num_channels=(image->matte ? 4UL : 3UL);
2047 num_channels=(image->matte ? 5UL : 4UL);
2050 (void) WriteBlobMSBShort(image,(unsigned short) num_channels);
2051 (void) WriteBlobMSBLong(image,image->rows);
2052 (void) WriteBlobMSBLong(image,image->columns);
2053 (void) WriteBlobMSBShort(image,(unsigned short)
2054 (image->storage_class == PseudoClass ? 8 : image->depth > 8 ? 16 : 8));
2055 if (((image->colorspace != UndefinedColorspace) ||
2056 (image->colorspace != CMYKColorspace)) &&
2057 (image->colorspace != CMYKColorspace))
2059 if (image->colorspace != RGBColorspace)
2060 (void) TransformImageColorspace(image,RGBColorspace);
2061 (void) WriteBlobMSBShort(image,(unsigned short)
2062 (image->storage_class == PseudoClass ? 2 : 3));
2066 if (image->colorspace != RGBColorspace)
2067 (void) TransformImageColorspace(image,CMYKColorspace);
2068 (void) WriteBlobMSBShort(image,4);
2070 if ((image->storage_class == DirectClass) || (image->colors > 256))
2071 (void) WriteBlobMSBLong(image,0);
2075 Write PSD raster colormap.
2077 (void) WriteBlobMSBLong(image,768);
2078 for (i=0; i < (long) image->colors; i++)
2079 (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].red));
2080 for ( ; i < 256; i++)
2081 (void) WriteBlobByte(image,0);
2082 for (i=0; i < (long) image->colors; i++)
2083 (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].green));
2084 for ( ; i < 256; i++)
2085 (void) WriteBlobByte(image,0);
2086 for (i=0; i < (long) image->colors; i++)
2087 (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].blue));
2088 for ( ; i < 256; i++)
2089 (void) WriteBlobByte(image,0);
2092 Image resource block.
2094 res_extra = 28; /* 0x03EB */
2095 profile=GetImageProfile(image,"8bim");
2096 if (profile == (StringInfo *) NULL)
2097 WriteBlobMSBLong(image, res_extra);
2100 (void) WriteBlobMSBLong(image,(unsigned long) res_extra +
2101 GetStringInfoLength(profile));
2102 (void) WriteBlob(image,GetStringInfoLength(profile),GetStringInfoDatum(
2105 WriteResolutionResourceBlock(image);
2109 layer_info_size = 2;
2110 tmp_image = base_image;
2111 while ( tmp_image != NULL ) {
2112 packet_size=tmp_image->depth > 8 ? 2UL : 1UL;
2114 if (tmp_image->storage_class == PseudoClass)
2115 num_channels = (tmp_image->matte != MagickFalse ? 2UL : 1UL);
2117 if (tmp_image->colorspace != CMYKColorspace)
2118 num_channels = (tmp_image->matte != MagickFalse ? 4UL : 3UL);
2120 num_channels = (tmp_image->matte != MagickFalse ? 5UL : 4UL);
2122 channelLength=(unsigned long) (tmp_image->columns * tmp_image->rows *
2124 layer_info_size += (unsigned long) (4*4 + 2 + num_channels * 6 + 4 + 4 +
2125 4 * 1 + 4 + 12 + num_channels * channelLength);
2127 tmp_image = GetNextImageInList(tmp_image);
2130 /* if the image has a matte, then we need to use layers */
2131 if ( layer_count == 0 && image->matte == MagickTrue )
2133 invert_layer_count = MagickTrue;
2135 goto compute_layer_info; /* yes, goto's suck, but it keeps the code cleaner! */
2138 if ( layer_count == 0 )
2139 (void) WriteBlobMSBLong(image, 0);
2142 (void) WriteBlobMSBLong(image,layer_info_size+4+4);
2143 if ( layer_info_size/2 != (layer_info_size+1)/2 ) /* odd */
2144 rounded_layer_info_size = layer_info_size + 1;
2146 rounded_layer_info_size = layer_info_size;
2147 (void) WriteBlobMSBLong(image,rounded_layer_info_size);
2149 if ( invert_layer_count )
2150 layer_count *= -1; /* if we have a matte, then use negative count! */
2151 (void) WriteBlobMSBShort(image,(unsigned short) layer_count);
2154 tmp_image = base_image;
2155 while ( tmp_image != NULL ) {
2156 (void) WriteBlobMSBLong(image,0);
2157 (void) WriteBlobMSBLong(image,0);
2158 (void) WriteBlobMSBLong(image,tmp_image->rows);
2159 (void) WriteBlobMSBLong(image,tmp_image->columns);
2161 packet_size=tmp_image->depth > 8 ? 2UL : 1UL;
2162 channel_size=(unsigned int) ((packet_size*tmp_image->rows*
2163 tmp_image->columns)+2);
2164 if (tmp_image->storage_class == PseudoClass) {
2165 (void) WriteBlobMSBShort(image,(unsigned short)
2166 (tmp_image->matte ? 2 : 1));
2167 if (tmp_image->matte) {
2168 (void) WriteBlobMSBShort(image,(unsigned short) -1);
2169 (void) WriteBlobMSBLong(image,channel_size);
2171 (void) WriteBlobMSBShort(image, 0);
2172 (void) WriteBlobMSBLong(image, channel_size);
2174 if (tmp_image->colorspace != CMYKColorspace)
2176 (void) WriteBlobMSBShort(image,(unsigned short)
2177 (tmp_image->matte ? 4 : 3));
2178 if (tmp_image->matte) {
2179 (void) WriteBlobMSBShort(image,(unsigned short) -1);
2180 (void) WriteBlobMSBLong(image,channel_size);
2182 (void) WriteBlobMSBShort(image, 0);
2183 (void) WriteBlobMSBLong(image, channel_size);
2184 (void) WriteBlobMSBShort(image, 1);
2185 (void) WriteBlobMSBLong(image, channel_size);
2186 (void) WriteBlobMSBShort(image, 2);
2187 (void) WriteBlobMSBLong(image, channel_size);
2191 (void) WriteBlobMSBShort(image,(unsigned short)
2192 (tmp_image->matte ? 5 : 4));
2193 if (tmp_image->matte) {
2194 (void) WriteBlobMSBShort(image,(unsigned short) -1);
2195 (void) WriteBlobMSBLong(image,channel_size);
2197 (void) WriteBlobMSBShort(image, 0);
2198 (void) WriteBlobMSBLong(image, channel_size);
2199 (void) WriteBlobMSBShort(image, 1);
2200 (void) WriteBlobMSBLong(image, channel_size);
2201 (void) WriteBlobMSBShort(image, 2);
2202 (void) WriteBlobMSBLong(image, channel_size);
2203 (void) WriteBlobMSBShort(image, 3);
2204 (void) WriteBlobMSBLong(image, channel_size);
2207 (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
2208 (void) WriteBlob(image,4,(const unsigned char *)
2209 CompositeOperatorToPSDBlendMode(tmp_image->compose));
2210 (void) WriteBlobByte(image, 255); /* BOGUS: layer opacity */
2211 (void) WriteBlobByte(image, 0);
2212 (void) WriteBlobByte(image, 1); /* BOGUS: layer attributes - visible, etc. */
2213 (void) WriteBlobByte(image, 0);
2215 (void) WriteBlobMSBLong(image, 12);
2216 (void) WriteBlobMSBLong(image, 0);
2217 (void) WriteBlobMSBLong(image, 0);
2219 theAttr=(const char *) GetImageProperty(tmp_image,"label");
2221 WritePascalString( image, theAttr, 4 );
2223 sprintf((char *) &(layer_name[1]), "%4s", theAttr->value );
2224 (void) WriteBlobByte(image, 3);
2225 (void) WriteBlob(image, 3, &layer_name[1]);
2228 (void) FormatMagickString((char *) layer_name,MaxTextExtent,"L%02ld",
2230 WritePascalString( image, (char*)layer_name, 4 );
2232 tmp_image = GetNextImageInList(tmp_image);
2235 /* now the image data! */
2236 tmp_image = base_image;
2237 while ( tmp_image != NULL ) {
2238 status=WriteImageChannels(image_info,image,tmp_image,MagickTrue);
2240 /* add in the pad! */
2241 if ( rounded_layer_info_size != layer_info_size )
2242 (void) WriteBlobByte(image,'\0');
2244 tmp_image = GetNextImageInList(tmp_image);
2247 /* user mask data */
2248 (void) WriteBlobMSBLong(image, 0);
2252 /* now the background image data! */
2253 if (force_white_background != MagickFalse)
2254 WriteWhiteBackground(image);
2256 status=WriteImageChannels(image_info,image,image,MagickFalse);
2258 (void) CloseBlob(image);