blob: b1431c2e4c0ecd26a75bc054f7b5e9339e54bab5 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% PPPP SSSSS DDDD %
7% P P SS D D %
8% PPPP SSS D D %
9% P SS D D %
10% P SSSSS DDDD %
11% %
12% %
13% Read/Write Adobe Photoshop Image Format %
14% %
15% Software Design %
16% John Cristy %
17% Leonard Rosenthol %
18% July 1992 %
19% %
20% %
cristy16af1cb2009-12-11 21:38:29 +000021% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000022% dedicated to making software imaging solutions freely available. %
23% %
24% You may not use this file except in compliance with the License. You may %
25% obtain a copy of the License at %
26% %
27% http://www.imagemagick.org/script/license.php %
28% %
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. %
34% %
35%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
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/profile.h"
61#include "magick/property.h"
62#include "magick/quantum-private.h"
63#include "magick/static.h"
64#include "magick/string_.h"
65
66/*
67 Forward declarations.
68*/
69static MagickBooleanType
70 WritePSDImage(const ImageInfo *,Image *);
71
72/*
73%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74% %
75% %
76% %
77% D e c o d e I m a g e %
78% %
79% %
80% %
81%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82%
83% DecodeImage uncompresses an image via Macintosh encoding specific to
84% the Adobe Photoshop image format.
85%
86% The format of the DecodeImage method is:
87%
88% MagickBooleanType DecodeImage(Image *image,const long channel)
89%
90% A description of each parameter follows:
91%
92% o image,image: the address of a structure of type Image.
93%
94% o channel: Specifies which channel: red, green, blue, or index to
95% decode the pixel values into.
96%
97*/
98static MagickBooleanType DecodeImage(Image *image,const long channel)
99{
100 ExceptionInfo
101 *exception;
102
103 MagickOffsetType
104 number_pixels;
105
106 Quantum
107 pixel;
108
109 register IndexPacket
110 *indexes;
111
112 register long
113 i,
114 x;
115
116 register PixelPacket
117 *q;
118
119 ssize_t
120 count;
121
122 exception=(&image->exception);
123 number_pixels=(MagickOffsetType) image->columns*image->rows;
124 for (x=0; number_pixels > 0; )
125 {
126 count=(ssize_t) ReadBlobByte(image);
127 if (count >= 128)
128 count-=256;
129 if (count < 0)
130 {
131 if (count == -128)
132 continue;
133 pixel=ScaleCharToQuantum((unsigned char) ReadBlobByte(image));
134 for (count=(-count+1); count > 0; count--)
135 {
136 q=GetAuthenticPixels(image,(long) (x % image->columns),
137 (long) (x/image->columns),1,1,exception);
138 if (q == (PixelPacket *) NULL)
139 break;
140 indexes=GetAuthenticIndexQueue(image);
141 switch (channel)
142 {
143 case -1:
144 {
145 q->opacity=(Quantum) (QuantumRange-pixel);
146 break;
147 }
148 case 0:
149 {
150 q->red=pixel;
151 if (image->storage_class == PseudoClass)
152 {
153 *indexes=(IndexPacket) ScaleQuantumToChar(pixel);
154 q->red=image->colormap[(long) *indexes].red;
155 q->green=image->colormap[(long) *indexes].green;
156 q->blue=image->colormap[(long) *indexes].blue;
157 }
158 break;
159 }
160 case 1:
161 {
162 if (image->storage_class == PseudoClass)
163 q->opacity=(Quantum) (QuantumRange-pixel);
164 else
165 q->green=pixel;
166 break;
167 }
168 case 2:
169 {
170 q->blue=pixel;
171 break;
172 }
173 case 3:
174 {
175 if (image->colorspace == CMYKColorspace)
176 *indexes=(IndexPacket) pixel;
177 else
178 q->opacity=(Quantum) (QuantumRange-pixel);
179 break;
180 }
181 case 4:
182 {
183 q->opacity=(Quantum) (QuantumRange-pixel);
184 break;
185 }
186 default:
187 break;
188 }
189 if (SyncAuthenticPixels(image,exception) == MagickFalse)
190 break;
191 x++;
192 number_pixels--;
193 }
194 continue;
195 }
196 count++;
197 for (i=(long) count; i > 0; i--)
198 {
199 pixel=ScaleCharToQuantum((unsigned char) ReadBlobByte(image));
200 q=GetAuthenticPixels(image,(long) (x % image->columns),
201 (long) (x/image->columns),1,1,exception);
202 if (q == (PixelPacket *) NULL)
203 break;
204 indexes=GetAuthenticIndexQueue(image);
205 switch (channel)
206 {
207 case -1:
208 {
209 q->opacity=(Quantum) (QuantumRange-pixel);
210 break;
211 }
212 case 0:
213 {
214 q->red=pixel;
215 if (image->storage_class == PseudoClass)
216 {
217 *indexes=(IndexPacket) ScaleQuantumToChar(pixel);
218 q->red=image->colormap[(long) *indexes].red;
219 q->green=image->colormap[(long) *indexes].green;
220 q->blue=image->colormap[(long) *indexes].blue;
221 }
222 break;
223 }
224 case 1:
225 {
226 if (image->storage_class == PseudoClass)
227 q->opacity=(Quantum) (QuantumRange-pixel);
228 else
229 q->green=pixel;
230 break;
231 }
232 case 2:
233 {
234 q->blue=pixel;
235 break;
236 }
237 case 3:
238 {
239 if (image->colorspace == CMYKColorspace)
240 *indexes=(IndexPacket) pixel;
241 else
242 q->opacity=(Quantum) (QuantumRange-pixel);
243 break;
244 }
245 case 4:
246 {
247 q->opacity=(Quantum) pixel;
248 break;
249 }
250 default:
251 break;
252 }
253 if (SyncAuthenticPixels(image,exception) == MagickFalse)
254 break;
255 x++;
256 number_pixels--;
257 }
258 }
259 /*
260 Guarentee the correct number of pixel packets.
261 */
262 if (number_pixels > 0)
263 ThrowBinaryException(CorruptImageError,"InsufficientImageDataInFile",
264 image->filename)
265 else
266 if (number_pixels < 0)
267 ThrowBinaryException(CorruptImageError,"TooMuchImageDataInFile",
268 image->filename);
269 return(MagickTrue);
270}
271
272/*
273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274% %
275% %
276% %
277% I s P S D %
278% %
279% %
280% %
281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282%
283% IsPSD()() returns MagickTrue if the image format type, identified by the
284% magick string, is PSD.
285%
286% The format of the IsPSD method is:
287%
288% MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
289%
290% A description of each parameter follows:
291%
292% o magick: compare image format pattern against these bytes.
293%
294% o length: Specifies the length of the magick string.
295%
296*/
297static MagickBooleanType IsPSD(const unsigned char *magick,const size_t length)
298{
299 if (length < 4)
300 return(MagickFalse);
301 if (LocaleNCompare((const char *) magick,"8BPS",4) == 0)
302 return(MagickTrue);
303 return(MagickFalse);
304}
305
306/*
307%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
308% %
309% %
310% %
311% R e a d P S D I m a g e %
312% %
313% %
314% %
315%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
316%
317% ReadPSDImage() reads an Adobe Photoshop image file and returns it. It
318% allocates the memory necessary for the new Image structure and returns a
319% pointer to the new image.
320%
321% The format of the ReadPSDImage method is:
322%
323% image=ReadPSDImage(image_info)
324%
325% A description of each parameter follows:
326%
327% o image_info: the image info.
328%
329% o exception: return any errors or warnings in this structure.
330%
331*/
332
333static inline long MagickAbsoluteValue(const long x)
334{
335 if (x < 0)
336 return(-x);
337 return(x);
338}
339
340static CompositeOperator PSDBlendModeToCompositeOperator(const char *mode)
341{
342 if (mode == (const char *) NULL)
343 return(OverCompositeOp);
344 if (LocaleNCompare(mode,"norm",4) == 0)
345 return(OverCompositeOp);
346 if (LocaleNCompare(mode,"mul ",4) == 0)
347 return(MultiplyCompositeOp);
348 if (LocaleNCompare(mode,"diss",4) == 0)
349 return(DissolveCompositeOp);
350 if (LocaleNCompare(mode,"diff",4) == 0)
351 return(DifferenceCompositeOp);
352 if (LocaleNCompare(mode,"dark",4) == 0)
353 return(DarkenCompositeOp);
354 if (LocaleNCompare(mode,"lite",4) == 0)
355 return(LightenCompositeOp);
356 if (LocaleNCompare(mode,"hue ",4) == 0)
357 return(HueCompositeOp);
358 if (LocaleNCompare(mode,"sat ",4) == 0)
359 return(SaturateCompositeOp);
360 if (LocaleNCompare(mode,"colr",4) == 0)
361 return(ColorizeCompositeOp);
362 if (LocaleNCompare(mode,"lum ",4) == 0)
363 return(LuminizeCompositeOp);
364 if (LocaleNCompare(mode,"scrn",4) == 0)
365 return(ScreenCompositeOp);
366 if (LocaleNCompare(mode,"over",4) == 0)
367 return(OverlayCompositeOp);
368 if (LocaleNCompare(mode,"hLit",4) == 0)
369 return(OverCompositeOp);
370 if (LocaleNCompare(mode,"sLit",4) == 0)
371 return(OverCompositeOp);
372 if (LocaleNCompare(mode,"smud",4) == 0)
373 return(OverCompositeOp);
374 if (LocaleNCompare(mode,"div ",4) == 0)
375 return(OverCompositeOp);
376 if (LocaleNCompare(mode,"idiv",4) == 0)
377 return(OverCompositeOp);
378 return(OverCompositeOp);
379}
380
381static const char *CompositeOperatorToPSDBlendMode(CompositeOperator inOp)
382{
383 const char
384 *outMode = "norm";
385
386 switch (inOp)
387 {
388 case OverCompositeOp: outMode = "norm"; break;
389 case MultiplyCompositeOp: outMode = "mul "; break;
390 case DissolveCompositeOp: outMode = "diss"; break;
391 case DifferenceCompositeOp: outMode = "diff"; break;
392 case DarkenCompositeOp: outMode = "dark"; break;
393 case LightenCompositeOp: outMode = "lite"; break;
394 case HueCompositeOp: outMode = "hue "; break;
395 case SaturateCompositeOp: outMode = "sat "; break;
396 case ColorizeCompositeOp: outMode = "colr"; break;
397 case LuminizeCompositeOp: outMode = "lum "; break;
398 case ScreenCompositeOp: outMode = "scrn"; break;
399 case OverlayCompositeOp: outMode = "over"; break;
400
401 default:
402 outMode = "norm";
403/*
404 if (LocaleNCompare(mode,"hLit",4) == 0)
405 return(OverCompositeOp);
406 if (LocaleNCompare(mode,"sLit",4) == 0)
407 return(OverCompositeOp);
408 if (LocaleNCompare(mode,"smud",4) == 0)
409 return(OverCompositeOp);
410 if (LocaleNCompare(mode,"div ",4) == 0)
411 return(OverCompositeOp);
412 if (LocaleNCompare(mode,"idiv",4) == 0)
413 return(OverCompositeOp);
414*/
415 }
416 return(outMode);
417}
418
419typedef enum
420{
421 BitmapMode = 0,
422 GrayscaleMode = 1,
423 IndexedMode = 2,
424 RGBMode = 3,
425 CMYKMode = 4,
426 MultichannelMode = 7,
427 DuotoneMode = 8,
428 LabMode = 9
429} PSDImageType;
430
431static const char *ModeToString( PSDImageType inType )
432{
433 switch ( inType )
434 {
435 case BitmapMode: return "Bitmap";
436 case GrayscaleMode: return "Grayscale";
437 case IndexedMode: return "Indexed";
438 case RGBMode: return "RGB";
439 case CMYKMode: return "CMYK";
440 case MultichannelMode: return "Multichannel";
441 case DuotoneMode: return "Duotone";
442 case LabMode: return "L*A*B";
443 default: return "unknown";
444 }
445}
446
447static MagickBooleanType ParseImageResourceBlocks(Image *image,
448 const unsigned char *blocks,size_t length)
449{
450 const unsigned char
451 *p;
452
453 StringInfo
454 *profile;
455
456 unsigned long
457 count,
458 long_sans;
459
460 unsigned short
461 id,
462 short_sans;
463
464 if (length < 16)
465 return(MagickFalse);
466 profile=AcquireStringInfo(length);
467 SetStringInfoDatum(profile,blocks);
468 (void) SetImageProfile(image,"8bim",profile);
469 profile=DestroyStringInfo(profile);
470 for (p=blocks; (p >= blocks) && (p < (blocks+length-16)); )
471 {
472 if (LocaleNCompare((const char *) p,"8BIM",4) != 0)
473 break;
474 p=PushLongPixel(LSBEndian,p,&long_sans);
475 p=PushShortPixel(LSBEndian,p,&id);
476 p=PushShortPixel(LSBEndian,p,&short_sans);
477 p=PushLongPixel(LSBEndian,p,&count);
478 switch (id)
479 {
480 case 0x03ed:
481 {
482 unsigned short
483 resolution;
484
485 /*
486 Resolution info.
487 */
488 p=PushShortPixel(LSBEndian,p,&resolution);
489 image->x_resolution=(double) resolution;
490 p=PushShortPixel(LSBEndian,p,&short_sans);
491 p=PushShortPixel(LSBEndian,p,&short_sans);
492 p=PushShortPixel(LSBEndian,p,&short_sans);
493 p=PushShortPixel(LSBEndian,p,&resolution);
494 image->y_resolution=(double) resolution;
495 p=PushShortPixel(LSBEndian,p,&short_sans);
496 p=PushShortPixel(LSBEndian,p,&short_sans);
497 p=PushShortPixel(LSBEndian,p,&short_sans);
498 break;
499 }
500 default:
501 {
502 p+=count;
503 break;
504 }
505 }
506 if ((count & 0x01) != 0)
507 p++;
508 }
509 return(MagickTrue);
510}
511
512static Image *ReadPSDImage(const ImageInfo *image_info,ExceptionInfo *exception)
513{
514#define MaxPSDChannels 24
515
516 typedef struct _ChannelInfo
517 {
518 short int
519 type;
520
521 unsigned long
522 size;
523 } ChannelInfo;
524
525 typedef struct _LayerInfo
526 {
527 RectangleInfo
528 page,
529 mask;
530
531 unsigned short
532 channels;
533
534 ChannelInfo
535 channel_info[MaxPSDChannels];
536
537 char
538 blendkey[4];
539
540 Quantum
541 opacity;
542
543 unsigned char
544 clipping,
545 visible,
546 flags;
547
548 unsigned long
549 offset_x,
550 offset_y;
551
552 unsigned char
553 name[256];
554
555 Image
556 *image;
557 } LayerInfo;
558
559 typedef struct _PSDInfo
560 {
561 char
562 signature[4];
563
564 unsigned short
565 channels,
566 version;
567
568 unsigned char
569 reserved[6];
570
571 unsigned long
572 rows,
573 columns;
574
575 unsigned short
576 depth,
577 mode;
578 } PSDInfo;
579
580 char
581 s[MaxTextExtent],
582 type[4];
583
584 Image
585 *image;
586
587 IndexPacket
588 *indexes;
589
590 LayerInfo
591 *layer_info;
592
593 long
594 j,
595 number_layers,
596 y;
597
598 PSDInfo
599 psd_info;
600
601 register long
602 x;
603
604 register PixelPacket
605 *q;
606
607 register long
608 i;
609
610 size_t
611 length,
612 combinedlength,
613 size;
614
615 ssize_t
616 count;
617
618 MagickBooleanType
619 status;
620
621 MagickOffsetType
622 offset;
623
624 size_t
625 packet_size;
626
627 unsigned char
628 *data;
629
630 unsigned short
631 compression;
632
633 unsigned long
634 mask_size,
635 pixel,
636 skip_first_alpha = 0;
637
638 /*
639 Open image file.
640 */
641 assert(image_info != (const ImageInfo *) NULL);
642 assert(image_info->signature == MagickSignature);
643 if (image_info->debug != MagickFalse)
644 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
645 image_info->filename);
646 assert(exception != (ExceptionInfo *) NULL);
647 assert(exception->signature == MagickSignature);
648 image=AcquireImage(image_info);
649 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
650 if (status == MagickFalse)
651 {
652 image=DestroyImageList(image);
653 return((Image *) NULL);
654 }
655 /*
656 Read image header.
657 */
658 count=ReadBlob(image,4,(unsigned char *) psd_info.signature);
659 psd_info.version=ReadBlobMSBShort(image);
660 if ((count == 0) || (LocaleNCompare(psd_info.signature,"8BPS",4) != 0) ||
661 (psd_info.version != 1))
662 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
663 count=ReadBlob(image,6,psd_info.reserved);
664 psd_info.channels=ReadBlobMSBShort(image);
665 if (psd_info.channels > MaxPSDChannels)
666 ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
667 psd_info.rows=ReadBlobMSBLong(image);
668 psd_info.columns=ReadBlobMSBLong(image);
669 psd_info.depth=ReadBlobMSBShort(image);
670 psd_info.mode=ReadBlobMSBShort(image);
671 if (image->debug != MagickFalse)
672 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
673 " Image is %ld x %ld with channels=%d, depth=%d, mode=%s",
674 psd_info.columns,psd_info.rows,psd_info.channels,psd_info.depth,
675 ModeToString((PSDImageType) psd_info.mode));
676 /*
677 Initialize image.
678 */
679 image->depth=psd_info.depth;
680 image->columns=psd_info.columns;
681 image->rows=psd_info.rows;
682 (void) SetImageBackgroundColor(image);
683 image->matte=psd_info.channels >= 4 ? MagickTrue : MagickFalse;
684 if (psd_info.mode == LabMode)
685 image->colorspace=LabColorspace;
686 if (psd_info.mode == CMYKMode)
687 {
688 image->colorspace=CMYKColorspace;
689 image->matte=psd_info.channels >= 5 ? MagickTrue : MagickFalse;
690 }
691 if ((psd_info.mode == BitmapMode) || (psd_info.mode == GrayscaleMode) ||
692 (psd_info.mode == DuotoneMode))
693 {
cristy3ed852e2009-09-05 21:47:34 +0000694 image->matte=psd_info.channels >= 2 ? MagickTrue : MagickFalse;
695 if (image->debug != MagickFalse)
696 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
697 " ImageColorMap allocated");
698 }
699 if (image->debug != MagickFalse)
700 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
701 image->matte ? " image has matte" : " image has no matte");
702 /*
703 Read PSD raster colormap only present for indexed and duotone images.
704 */
705 length=ReadBlobMSBLong(image);
706 if (length != 0)
707 {
708 if (image->debug != MagickFalse)
709 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
710 " reading colormap");
711 if (psd_info.mode == DuotoneMode)
712 {
713 /*
714 Duotone image data; the format of this data is undocumented.
715 */
716 data=(unsigned char *) AcquireQuantumMemory(length,sizeof(*data));
717 if (data == (unsigned char *) NULL)
718 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
719 count=ReadBlob(image,length,data);
720 data=(unsigned char *) RelinquishMagickMemory(data);
721 }
722 else
723 {
724 /*
725 Read PSD raster colormap.
726 */
727 if (AcquireImageColormap(image,(unsigned long) (length/3)) == MagickFalse)
728 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
729 for (i=0; i < (long) image->colors; i++)
730 image->colormap[i].red=ScaleCharToQuantum((unsigned char)
731 ReadBlobByte(image));
732 for (i=0; i < (long) image->colors; i++)
733 image->colormap[i].green=ScaleCharToQuantum((unsigned char)
734 ReadBlobByte(image));
735 for (i=0; i < (long) image->colors; i++)
736 image->colormap[i].blue=ScaleCharToQuantum((unsigned char)
737 ReadBlobByte(image));
738 image->matte=psd_info.channels >= 2 ? MagickTrue : MagickFalse;
739 }
740 }
741 length=ReadBlobMSBLong(image);
742 if (length != 0)
743 {
744 unsigned char
745 *blocks;
746
747 /*
748 Image resources block.
749 */
750 if (image->debug != MagickFalse)
751 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
752 " reading image resource blocks - %ld bytes",(long) length);
753 blocks=(unsigned char *) AcquireQuantumMemory(length,sizeof(*blocks));
754 if (blocks == (unsigned char *) NULL)
755 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
756 count=ReadBlob(image,length,blocks);
757 if (((size_t) count != length) ||
758 (LocaleNCompare((char *) blocks,"8BIM",4) != 0))
759 {
760 blocks=(unsigned char *) RelinquishMagickMemory(blocks);
761 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
762 }
763 (void) ParseImageResourceBlocks(image,blocks,length);
764 blocks=(unsigned char *) RelinquishMagickMemory(blocks);
765 }
766 /*
767 If we are only "pinging" the image, then we're done - so return.
768 */
769 if (image_info->ping != MagickFalse)
770 {
771 (void) CloseBlob(image);
772 return(GetFirstImageInList(image));
773 }
774 /*
775 Layer and mask block.
776 */
777 layer_info=(LayerInfo *) NULL;
778 number_layers=0;
779 length=ReadBlobMSBLong(image);
780 if (length == 8)
781 {
782 length=ReadBlobMSBLong(image);
783 length=ReadBlobMSBLong(image);
784 }
785 if ((image_info->number_scenes == 1) && (image_info->scene == 0))
786 for ( ; length != 0; length--)
787 if (ReadBlobByte(image) == EOF)
788 {
789 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
790 image->filename);
791 break;
792 }
793 if (length == 0)
794 {
795 if (image->debug != MagickFalse)
796 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
797 " image has no layers");
798 }
799 else
800 {
801 offset=TellBlob(image);
802 size=ReadBlobMSBLong(image);
803 if (size == 0)
804 {
805 /*
806 Skip layers & masks.
807 */
808 for (j=0; j < (long) (length-4); j++)
809 (void) ReadBlobByte(image);
810 }
811 else
812 {
813 MagickOffsetType
814 layer_offset;
815
816 layer_offset=offset+length;
817 number_layers=(short) ReadBlobMSBShort(image);
818 if (image->debug != MagickFalse)
819 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
820 " image contains %ld layers", number_layers);
821 if (number_layers < 0)
822 {
823 /*
824 Weird hack in PSD format to ignore first alpha channel.
825 */
826 skip_first_alpha=1;
827 number_layers=MagickAbsoluteValue(number_layers);
828 if (image->debug != MagickFalse)
829 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
830 " negative layer count corrected for");
831 }
832 layer_info=(LayerInfo *) AcquireQuantumMemory((size_t) number_layers,
833 sizeof(*layer_info));
834 if (layer_info == (LayerInfo *) NULL)
835 {
836 if (image->debug != MagickFalse)
837 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
838 " allocation of LayerInfo failed");
839 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
840 }
841 (void) ResetMagickMemory(layer_info,0,(size_t) number_layers*
842 sizeof(*layer_info));
843 for (i=0; i < number_layers; i++)
844 {
845 if (image->debug != MagickFalse)
846 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
847 " reading layer #%ld",i+1);
848 layer_info[i].page.y=(long) ReadBlobMSBLong(image);
849 layer_info[i].page.x=(long) ReadBlobMSBLong(image);
850 layer_info[i].page.height=ReadBlobMSBLong(image)-layer_info[i].page.y;
851 layer_info[i].page.width=ReadBlobMSBLong(image)-layer_info[i].page.x;
852 layer_info[i].channels=ReadBlobMSBShort(image);
853 if (layer_info[i].channels > MaxPSDChannels)
854 ThrowReaderException(CorruptImageError,"MaximumChannelsExceeded");
855 if (image->debug != MagickFalse)
856 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
857 " offset(%ld,%ld), size(%ld,%ld), channels=%d",
858 layer_info[i].page.x, layer_info[i].page.y,
859 layer_info[i].page.height,layer_info[i].page.width,
860 layer_info[i].channels);
861 for (j=0; j < (long) layer_info[i].channels; j++)
862 {
863 layer_info[i].channel_info[j].type=(short) ReadBlobMSBShort(image);
864 layer_info[i].channel_info[j].size=ReadBlobMSBLong(image);
865 if (image->debug != MagickFalse)
866 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
867 " channel[%ld]: type=%d, size=%ld",j,
868 layer_info[i].channel_info[j].type,
869 (long) layer_info[i].channel_info[j].size);
870 }
871 count=ReadBlob(image,4,(unsigned char *) type);
872 if ((count == 0) || (LocaleNCompare(type,"8BIM",4) != 0))
873 {
874 if (image->debug != MagickFalse)
875 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
876 " layer type was %.4s instead of 8BIM", type);
877 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
878 }
879 count=ReadBlob(image,4,(unsigned char *) layer_info[i].blendkey);
880 layer_info[i].opacity=(Quantum) (QuantumRange-ScaleCharToQuantum(
881 (unsigned char) ReadBlobByte(image)));
882 layer_info[i].clipping=(unsigned char) ReadBlobByte(image);
883 layer_info[i].flags=(unsigned char) ReadBlobByte(image);
884 layer_info[i].visible=!(layer_info[i].flags & 0x02);
885 if (image->debug != MagickFalse)
886 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
887 " blend=%.4s, opacity=%lu, clipping=%s, flags=%d, visible=%s",
888 layer_info[i].blendkey,(unsigned long) layer_info[i].opacity,
889 layer_info[i].clipping ? "true" : "false",layer_info[i].flags,
890 layer_info[i].visible ? "true" : "false");
891 (void) ReadBlobByte(image); /* filler */
892 combinedlength=0;
893 size=ReadBlobMSBLong(image);
894 if (size != 0)
895 {
896 if (image->debug != MagickFalse)
897 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
898 " layer contains additional info");
899 length=ReadBlobMSBLong(image);
900 if (length != 0)
901 {
902 /*
903 Layer mask info.
904 */
905 layer_info[i].mask.y=(long) ReadBlobMSBLong(image);
906 layer_info[i].mask.x=(long) ReadBlobMSBLong(image);
907 layer_info[i].mask.height=
908 (ReadBlobMSBLong(image)-layer_info[i].mask.y);
909 layer_info[i].mask.width=
910 (ReadBlobMSBLong(image)-layer_info[i].mask.x);
911 if (image->debug != MagickFalse)
912 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
913 " layer mask: offset(%ld,%ld), size(%ld,%ld), length=%ld",
914 layer_info[i].mask.x,layer_info[i].mask.y,
915 layer_info[i].mask.width, layer_info[i].mask.height,
916 (long) length-16);
917 /*
918 Skip over the rest of the layer mask information.
919 */
920 for (j=0; j < (long) (length-16); j++)
921 (void) ReadBlobByte(image);
922 }
923 combinedlength+=length+4; /* +4 for length */
924 length=ReadBlobMSBLong(image);
925 if (length != 0)
926 {
927 /*
928 Layer blending ranges info.
929 */
930 if (image->debug != MagickFalse)
931 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
932 " layer blending ranges: length=%ld",(long) length);
933 /*
934 We read it, but don't use it...
935 */
936 for (j=0; j < (long) (length); j+=8)
937 {
938 size_t blend_source=ReadBlobMSBLong(image);
939 size_t blend_dest=ReadBlobMSBLong(image);
940 if (image->debug != MagickFalse)
941 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
942 " source(%x), dest(%x)",(unsigned int)
943 blend_source,(unsigned int) blend_dest);
944 }
945 }
cristy2cc39842009-10-10 20:04:02 +0000946 combinedlength+=length+4;
947 /*
948 Layer name.
949 */
cristy3ed852e2009-09-05 21:47:34 +0000950 length=(size_t) ReadBlobByte(image);
cristy2cc39842009-10-10 20:04:02 +0000951 for (j=0; j < (long) length; j++)
952 layer_info[i].name[j]=(unsigned char) ReadBlobByte(image);
953 layer_info[i].name[j]='\0';
954 if (image->debug != MagickFalse)
955 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
956 " layer name: %s",layer_info[i].name);
957 combinedlength+=length+1;
cristy3ed852e2009-09-05 21:47:34 +0000958
959#if 0 /* still in development */
960 /*
961 Adjustment layers and other stuff...
962 */
963 {
964 char alsig[4],
965 alkey[4];
966
967 count=ReadBlob(image,4,alsig);
968 if ((count == 0) || (LocaleNCompare(alsig,"8BIM",4) != 0)) {
969 if (debug != MagickFalse)
970 {
971 if (image->debug != MagickFalse)
972 (void) LogMagickEvent(CoderEvent,GetMagickModule()," adjustment layer type was %.4s instead of 8BIM", alsig);
973 }
974 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
975 }
976 count=ReadBlob(image,4,alkey);
977 length=ReadBlobMSBLong(image);
978 if (debug != MagickFalse)
979 {
980 if (image->debug != MagickFalse)
981 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
982 " adjustment layer key: %.4s, data length=%ld",
983 alkey, length);
984 }
985
986 if ( length ) {
987 for (j=0; j < (long) (length); j++)
988 (void) ReadBlobByte(image);
989 }
990
991 }
992 combinedlength += 12 + length; /* sig, key, length + the actual length*/
993#endif
994
995 /*
996 Skip the rest of the variable data until we support it.
997 */
998 if (image->debug != MagickFalse)
999 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1000 " unsupported data: length=%ld",(long)
1001 size-combinedlength);
1002 for (j=0; j < (long) (size-combinedlength); j++)
1003 (void) ReadBlobByte(image);
1004 }
1005 /*
1006 Allocate layered image.
1007 */
1008 layer_info[i].image=CloneImage(image,layer_info[i].page.width,
1009 layer_info[i].page.height,MagickFalse,&image->exception);
1010 if (layer_info[i].image == (Image *) NULL)
1011 {
1012 for (j=0; j < i; j++)
1013 layer_info[j].image=DestroyImage(layer_info[j].image);
1014 if (image->debug != MagickFalse)
1015 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1016 " allocation of image for layer %ld failed", i);
1017 ThrowReaderException(ResourceLimitError,
1018 "MemoryAllocationFailed");
1019 }
1020 if (image->debug != MagickFalse)
1021 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1022 " setting up new layer image");
1023 (void) SetImageBackgroundColor(layer_info[i].image);
1024 layer_info[i].image->compose=
1025 PSDBlendModeToCompositeOperator(layer_info[i].blendkey);
1026 if (layer_info[i].visible == MagickFalse)
1027 layer_info[i].image->compose=NoCompositeOp;
1028 if (psd_info.mode == CMYKMode)
1029 image->colorspace=CMYKColorspace;
1030 for (j=0; j < (long) layer_info[i].channels; j++)
1031 if (layer_info[i].channel_info[j].type == -1)
1032 layer_info[i].image->matte=MagickTrue;
1033 /*
1034 Set up some hidden attributes for folks that need them.
1035 */
1036 (void) FormatMagickString(s,MaxTextExtent,"%ld",
1037 layer_info[i].page.x );
1038 (void) SetImageArtifact(layer_info[i].image,"psd:layer.x",s);
1039 (void) FormatMagickString(s,MaxTextExtent,"%ld",
1040 layer_info[i].page.y);
1041 (void) SetImageArtifact(layer_info[i].image,"psd:layer.y",s);
1042 (void) FormatMagickString(s,MaxTextExtent,"%lu",(unsigned long)
1043 layer_info[i].opacity );
1044 (void) SetImageArtifact(layer_info[i].image,"psd:layer.opacity",s);
1045 (void) SetImageProperty(layer_info[i].image,"label",(char *)
1046 layer_info[i].name);
1047 }
1048 if (image->debug != MagickFalse)
1049 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1050 " reading image data for layers");
1051 /*
1052 Read pixel data for each layer.
1053 */
1054 for (i=0; i < number_layers; i++)
1055 {
1056 if (image->debug != MagickFalse)
1057 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1058 " reading data for layer %ld",i);
1059 for (j=0; j < (long) layer_info[i].channels; j++)
1060 {
1061 if (image->debug != MagickFalse)
1062 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1063 " reading data for channel %ld", j);
1064#if 1
1065 if (layer_info[i].channel_info[j].size <= (2*layer_info[i].image->rows))
1066 {
1067 long
1068 k;
1069
1070 if (image->debug != MagickFalse)
1071 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1072 " layer data is empty");
1073 /*
1074 A layer without data.
1075 */
1076 for (k=0; k < (long) layer_info[i].channel_info[j].size; k++)
1077 (void) ReadBlobByte(layer_info[i].image);
1078 continue;
1079 }
1080#endif
1081 compression=ReadBlobMSBShort(layer_info[i].image);
cristy2cc39842009-10-10 20:04:02 +00001082 if ((layer_info[i].page.height != 0) &&
1083 (layer_info[i].page.width != 0))
cristy3ed852e2009-09-05 21:47:34 +00001084 {
cristy2cc39842009-10-10 20:04:02 +00001085 if (compression == 1)
1086 {
1087 /*
1088 Read RLE compressed data.
1089 */
1090 if (image->debug != MagickFalse)
1091 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1092 " layer data is RLE compressed");
1093 for (y=0; y < (long) layer_info[i].image->rows; y++)
1094 (void) ReadBlobMSBShort(layer_info[i].image);
1095 (void) DecodeImage(layer_info[i].image,
1096 layer_info[i].channel_info[j].type);
1097 continue;
1098 }
cristy3ed852e2009-09-05 21:47:34 +00001099 /*
cristy2cc39842009-10-10 20:04:02 +00001100 Read uncompressed pixel datas separate planes.
cristy3ed852e2009-09-05 21:47:34 +00001101 */
1102 if (image->debug != MagickFalse)
1103 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
cristy2cc39842009-10-10 20:04:02 +00001104 " layer data is uncompressed");
1105 packet_size=1;
1106 if (layer_info[i].image->storage_class == PseudoClass)
1107 {
1108 if (layer_info[i].image->colors > 256)
1109 packet_size++;
1110 }
cristy3ed852e2009-09-05 21:47:34 +00001111 else
cristy2cc39842009-10-10 20:04:02 +00001112 if (layer_info[i].image->depth > 8)
1113 packet_size++;
1114 for (y=0; y < (long) layer_info[i].image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001115 {
cristy2cc39842009-10-10 20:04:02 +00001116 q=GetAuthenticPixels(layer_info[i].image,0,y,
1117 layer_info[i].image->columns,1,exception);
1118 if (q == (PixelPacket *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001119 break;
cristy2cc39842009-10-10 20:04:02 +00001120 indexes=GetAuthenticIndexQueue(layer_info[i].image);
1121 for (x=0; x < (long) layer_info[i].image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001122 {
cristy2cc39842009-10-10 20:04:02 +00001123 if (packet_size == 1)
1124 pixel=(unsigned long) ScaleCharToQuantum((unsigned char)
1125 ReadBlobByte(layer_info[i].image));
1126 else
1127 pixel=(unsigned long) ScaleShortToQuantum(
1128 ReadBlobMSBShort(layer_info[i].image));
1129 switch (layer_info[i].channel_info[j].type)
1130 {
1131 case -1: /* transparency mask */
cristy3ed852e2009-09-05 21:47:34 +00001132 {
cristy2cc39842009-10-10 20:04:02 +00001133 q->opacity=(Quantum) (QuantumRange-pixel);
1134 break;
cristy3ed852e2009-09-05 21:47:34 +00001135 }
cristy2cc39842009-10-10 20:04:02 +00001136 case 0: /* first component (Red, Cyan, Gray or Index) */
1137 {
1138 q->red=(Quantum) pixel;
1139 if (layer_info[i].image->storage_class == PseudoClass)
1140 {
1141 if (packet_size == 1)
1142 indexes[x]=(IndexPacket) ScaleQuantumToChar(
1143 (Quantum) pixel);
1144 else
1145 indexes[x]=(IndexPacket) ScaleQuantumToShort(
1146 (Quantum) pixel);
1147 q->red=layer_info[i].image->colormap[(long) *indexes].red;
1148 q->green=layer_info[i].image->colormap[(long) *indexes].green;
1149 q->blue=layer_info[i].image->colormap[(long) *indexes].blue;
1150 }
1151 break;
1152 }
1153 case 1: /* second component (Green, Magenta, or opacity) */
1154 {
1155 if (layer_info[i].image->storage_class == PseudoClass)
1156 q->opacity=(Quantum) (QuantumRange-pixel);
1157 else
1158 q->green=(Quantum) pixel;
1159 break;
1160 }
1161 case 2: /* third component (Blue or Yellow) */
1162 {
1163 q->blue=(Quantum) pixel;
1164 break;
1165 }
1166 case 3: /* fourth component (Opacity or Black) */
1167 {
1168 if (image->colorspace == CMYKColorspace)
1169 indexes[x]=(Quantum) pixel;
1170 else
1171 q->opacity=(Quantum) (QuantumRange-pixel);
1172 break;
1173 }
1174 case 4: /* fifth component (opacity) */
1175 {
1176 q->opacity=(Quantum) (QuantumRange-pixel);
1177 break;
1178 }
1179 default:
1180 break;
1181 }
1182 q++;
cristy3ed852e2009-09-05 21:47:34 +00001183 }
cristy2cc39842009-10-10 20:04:02 +00001184 if (SyncAuthenticPixels(layer_info[i].image,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +00001185 break;
1186 }
cristy2cc39842009-10-10 20:04:02 +00001187 }
cristy3ed852e2009-09-05 21:47:34 +00001188 }
cristy3ed852e2009-09-05 21:47:34 +00001189 if (layer_info[i].opacity != OpaqueOpacity)
1190 {
1191 /*
1192 Correct for opacity level.
1193 */
1194 for (y=0; y < (long) layer_info[i].image->rows; y++)
1195 {
1196 q=GetAuthenticPixels(layer_info[i].image,0,y,
1197 layer_info[i].image->columns,1,exception);
1198 if (q == (PixelPacket *) NULL)
1199 break;
1200 indexes=GetAuthenticIndexQueue(layer_info[i].image);
1201 for (x=0; x < (long) layer_info[i].image->columns; x++)
1202 {
cristy07758662010-01-15 20:25:50 +00001203 q->opacity=(Quantum) (QuantumRange-(Quantum) (QuantumScale*
1204 ((QuantumRange-q->opacity)*(QuantumRange-
1205 layer_info[i].opacity))));
cristy3ed852e2009-09-05 21:47:34 +00001206 q++;
1207 }
1208 if (SyncAuthenticPixels(layer_info[i].image,exception) == MagickFalse)
1209 break;
1210 }
1211 }
1212 if (layer_info[i].image->colorspace == CMYKColorspace)
1213 (void) NegateImage(layer_info[i].image,MagickFalse);
1214 }
1215 /* added by palf -> invisible group layer make layer of this group
1216 invisible I consider that all layer with width and height null are
1217 layer for group layer */
1218 {
1219 short inside_layer = 0;
1220 short layer_visible = 0;
1221 for (i=number_layers-1; i >=0; i--)
1222 {
1223 if ((layer_info[i].page.width == 0) ||
1224 (layer_info[i].page.height == 0))
1225 {
1226 if (inside_layer == 0)
1227 {
1228 inside_layer=1;
1229 layer_visible=(short int) layer_info[i].visible;
1230 }
1231 else
1232 {
1233 inside_layer = 0;
1234 }
1235 }
1236 else
1237 if ((inside_layer == 1) && (layer_visible == 0))
1238 {
1239 layer_info[i].visible=(unsigned char) layer_visible;
1240 layer_info[i].image->compose=NoCompositeOp;
1241 }
1242 }
1243 }
1244 /* added by palf -> suppression of empty layer */
1245 /* I consider that all layer with width and height null are layer for group layer */
1246 for (i=0; i < number_layers; i++)
1247 {
1248 if ((layer_info[i].page.width == 0) ||
1249 (layer_info[i].page.height == 0))
1250 {
1251 if (layer_info[i].image != (Image *) NULL)
1252 layer_info[i].image=DestroyImage(layer_info[i].image);
1253 for (j=i; j < number_layers - 1; j++)
1254 layer_info[j] = layer_info[j+1];
1255 number_layers--;
1256 i--;
1257 }
1258 }
1259 mask_size = ReadBlobMSBLong(image); /* global mask size: currently ignored */
1260
1261 if (number_layers > 0)
1262 {
1263
1264 if (image->debug != MagickFalse)
1265 (void) LogMagickEvent(CoderEvent,GetMagickModule()," putting layers into image list");
1266 for (i=0; i < number_layers; i++)
1267 {
1268 if (i > 0)
1269 layer_info[i].image->previous=layer_info[i-1].image;
1270 if (i < (number_layers-1))
1271 layer_info[i].image->next=layer_info[i+1].image;
1272 layer_info[i].image->page=layer_info[i].page;
1273 }
1274 image->next=layer_info[0].image;
1275 layer_info[0].image->previous=image;
1276 layer_info=(LayerInfo *) RelinquishMagickMemory(layer_info);
1277
1278 }
1279 layer_offset-=TellBlob(image);
1280 offset=SeekBlob(image,layer_offset,SEEK_CUR);
1281 }
1282 }
1283 /*
1284 Read the precombined layer, present for PSD < 4 compatibility
1285 */
1286 if (image->debug != MagickFalse)
1287 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1288 " reading the precombined layer");
1289 compression=ReadBlobMSBShort(image);
1290 if (compression == 1)
1291 {
1292 /*
1293 Read Packbit encoded pixel datas separate planes.
1294 */
1295 for (i=0; i < (long) (image->rows*psd_info.channels); i++)
1296 (void) ReadBlobMSBShort(image);
1297 for (i=0; i < (long) psd_info.channels; i++)
1298 (void) DecodeImage(image,(int) i);
1299 }
1300 else
1301 {
1302 /*
1303 Read uncompressed pixel data separate planes.
1304 */
1305 packet_size=1;
1306 if (image->storage_class == PseudoClass)
1307 {
1308 if (image->colors > 256)
1309 packet_size++;
1310 }
1311 else
1312 if (image->depth > 8)
1313 packet_size++;
1314 for (i=0; i < (long) psd_info.channels; i++)
1315 {
1316 for (y=0; y < (long) image->rows; y++)
1317 {
1318 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
1319 if (q == (PixelPacket *) NULL)
1320 break;
1321 indexes=GetAuthenticIndexQueue(image);
1322 for (x=0; x < (long) image->columns; x++)
1323 {
1324 if (packet_size == 1)
1325 pixel=(unsigned long) ScaleCharToQuantum((unsigned char)
1326 ReadBlobByte(image));
1327 else
1328 pixel=(unsigned long) ScaleShortToQuantum(
1329 ReadBlobMSBShort(image));
1330 switch (i)
1331 {
1332 case -1:
1333 {
1334 q->opacity=(Quantum) (QuantumRange-pixel);
1335 break;
1336 }
1337 case 0:
1338 {
1339 q->red=(Quantum) pixel;
cristy7e826ea2009-10-16 16:49:56 +00001340 if (psd_info.channels == 1)
1341 {
1342 q->green=q->red;
1343 q->blue=q->red;
1344 }
cristy3ed852e2009-09-05 21:47:34 +00001345 if (image->storage_class == PseudoClass)
1346 {
1347 if (packet_size == 1)
1348 indexes[x]=(IndexPacket) ScaleQuantumToChar((Quantum)
1349 pixel);
1350 else
1351 indexes[x]=(IndexPacket) ScaleQuantumToShort((Quantum)
1352 pixel);
1353 *q=image->colormap[(long) indexes[x]];
1354 q->red=image->colormap[(long) indexes[x]].red;
1355 q->green=image->colormap[(long) indexes[x]].green;
1356 q->blue=image->colormap[(long) indexes[x]].blue;
1357 }
1358 break;
1359 }
1360 case 1:
1361 {
1362 if (image->storage_class == PseudoClass)
1363 q->opacity=(Quantum) (QuantumRange-pixel);
1364 else
1365 q->green=(Quantum) pixel;
1366 break;
1367 }
1368 case 2:
1369 {
1370 q->blue=(Quantum) pixel;
1371 break;
1372 }
1373 case 3:
1374 {
1375 if (image->colorspace == CMYKColorspace)
1376 indexes[x]=(IndexPacket) pixel;
1377 else
1378 q->opacity=(Quantum) (QuantumRange-pixel);
1379 break;
1380 }
1381 case 4:
1382 {
1383 q->opacity=(Quantum) (QuantumRange-pixel);
1384 break;
1385 }
1386 default:
1387 break;
1388 }
1389 q++;
1390 }
1391 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1392 break;
1393 }
1394 }
1395 }
1396 if (image->colorspace == CMYKColorspace)
1397 (void) NegateImage(image,MagickFalse);
1398 (void) CloseBlob(image);
1399 return(GetFirstImageInList(image));
1400}
1401
1402/*
1403%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1404% %
1405% %
1406% %
1407% R e g i s t e r P S D I m a g e %
1408% %
1409% %
1410% %
1411%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1412%
1413% RegisterPSDImage() adds properties for the PSD image format to
1414% the list of supported formats. The properties include the image format
1415% tag, a method to read and/or write the format, whether the format
1416% supports the saving of more than one frame to the same file or blob,
1417% whether the format supports native in-memory I/O, and a brief
1418% description of the format.
1419%
1420% The format of the RegisterPSDImage method is:
1421%
1422% unsigned long RegisterPSDImage(void)
1423%
1424*/
1425ModuleExport unsigned long RegisterPSDImage(void)
1426{
1427 MagickInfo
1428 *entry;
1429
1430 entry=SetMagickInfo("PSD");
1431 entry->decoder=(DecodeImageHandler *) ReadPSDImage;
1432 entry->encoder=(EncodeImageHandler *) WritePSDImage;
1433 entry->magick=(IsImageFormatHandler *) IsPSD;
1434 entry->description=ConstantString("Adobe Photoshop bitmap");
1435 entry->module=ConstantString("PSD");
1436 (void) RegisterMagickInfo(entry);
1437 return(MagickImageCoderSignature);
1438}
1439
1440/*
1441%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1442% %
1443% %
1444% %
1445% U n r e g i s t e r P S D I m a g e %
1446% %
1447% %
1448% %
1449%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1450%
1451% UnregisterPSDImage() removes format registrations made by the
1452% PSD module from the list of supported formats.
1453%
1454% The format of the UnregisterPSDImage method is:
1455%
1456% UnregisterPSDImage(void)
1457%
1458*/
1459ModuleExport void UnregisterPSDImage(void)
1460{
1461 (void) UnregisterMagickInfo("PSD");
1462}
1463
1464/*
1465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1466% %
1467% %
1468% %
1469% W r i t e P S D I m a g e %
1470% %
1471% %
1472% %
1473%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1474%
1475% WritePSDImage() writes an image in the Adobe Photoshop encoded image
1476% format.
1477%
1478% The format of the WritePSDImage method is:
1479%
1480% MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image)
1481%
1482% A description of each parameter follows.
1483%
1484% o image_info: the image info.
1485%
1486% o image: The image.
1487%
1488%
1489*/
1490
1491static void WriteOneChannel(const ImageInfo *image_info,Image *image,
1492 Image *tmp_image,unsigned char *pixels,QuantumType quantum_type,
1493 const MagickBooleanType compression_flag)
1494{
1495 int
1496 y;
1497
1498 QuantumInfo
1499 *quantum_info;
1500
1501 register const PixelPacket
1502 *p;
1503
1504 size_t
1505 packet_size;
1506
1507 if (compression_flag)
1508 (void) WriteBlobMSBShort(image,0); /* compression */
1509 if (tmp_image->depth > 8)
1510 tmp_image->depth=16;
1511 quantum_info=AcquireQuantumInfo(image_info,image);
1512 packet_size=tmp_image->depth > 8UL ? 2UL : 1UL;
1513 for (y=0; y < (long) tmp_image->rows; y++)
1514 {
1515 p=GetVirtualPixels(tmp_image,0,y,tmp_image->columns,1,&image->exception);
1516 if (p == (const PixelPacket *) NULL)
1517 break;
1518 (void) ExportQuantumPixels(tmp_image,(CacheView *) NULL,quantum_info,
1519 quantum_type,pixels,&image->exception);
1520 (void) WriteBlob(image,packet_size*tmp_image->columns,pixels);
1521 }
1522 quantum_info=DestroyQuantumInfo(quantum_info);
1523}
1524
1525static MagickBooleanType WriteImageChannels(const ImageInfo *image_info,
1526 Image *image,Image *tmp_image,const MagickBooleanType separate)
1527{
1528 int
1529 i;
1530
1531 size_t
1532 channels,
1533 packet_size;
1534
1535 unsigned char
1536 *pixels;
1537
1538 /*
1539 Write uncompressed pixel datas separate planes.
1540 */
1541 channels=1;
1542 if ((tmp_image->storage_class == PseudoClass) &&
1543 (tmp_image->matte == MagickFalse))
1544 channels++;
1545 packet_size=tmp_image->depth > 8UL ? 2UL : 1UL;
1546 pixels=(unsigned char *) AcquireQuantumMemory(channels*tmp_image->columns,
1547 packet_size*sizeof(*pixels));
1548 if (pixels == (unsigned char *) NULL)
1549 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1550 i=0;
1551 if (tmp_image->storage_class == PseudoClass)
1552 {
1553 if (tmp_image->matte == MagickFalse)
1554 WriteOneChannel(image_info,image,tmp_image,pixels,IndexQuantum,
1555 (i++ == 0) || (separate != MagickFalse) ? MagickTrue : MagickFalse);
1556 else
1557 WriteOneChannel(image_info,image,tmp_image,pixels,IndexAlphaQuantum,
1558 (i++ == 0) || (separate != MagickFalse) ? MagickTrue : MagickFalse);
1559 }
1560 else
1561 {
1562 if (tmp_image->colorspace == CMYKColorspace)
1563 (void) NegateImage(image,MagickFalse);
1564 if (tmp_image->matte)
1565 WriteOneChannel(image_info,image,tmp_image,pixels,AlphaQuantum,
1566 (i++ == 0) || (separate != MagickFalse) ? MagickTrue : MagickFalse);
1567 WriteOneChannel(image_info,image,tmp_image,pixels,RedQuantum,
1568 (i++ == 0) || (separate != MagickFalse) ? MagickTrue : MagickFalse);
1569 WriteOneChannel(image_info,image,tmp_image,pixels,GreenQuantum,
1570 (i++ == 0) || (separate != MagickFalse) ? MagickTrue : MagickFalse);
1571 WriteOneChannel(image_info,image,tmp_image,pixels,BlueQuantum,
1572 (i++ == 0) || (separate != MagickFalse) ? MagickTrue : MagickFalse);
1573 if (tmp_image->colorspace == CMYKColorspace)
1574 {
1575 WriteOneChannel(image_info,image,tmp_image,pixels,BlackQuantum,
1576 (i++ == 0) || (separate != MagickFalse) ? MagickTrue : MagickFalse);
1577 (void) NegateImage(image,MagickFalse);
1578 }
1579 }
1580 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1581 return(MagickTrue);
1582}
1583
1584/* Write white background, RLE-compressed */
1585
1586static void WriteWhiteBackground( Image* image )
1587{
1588 long w8, w;
1589 char *d, scanline[256];
1590
1591 int numChannels = 3, dim = (int) (image->rows*numChannels);
1592
1593 register long
1594 i;
1595
1596 size_t
1597 length;
1598
1599 unsigned short
1600 bytecount;
1601
1602 (void) WriteBlobMSBShort(image,1); /* RLE compressed */
1603 w8 = (long) image->columns;
1604 d = scanline;
1605 /* Set up scanline */
1606 for (w=w8; w > 128; w-=128)
1607 {
1608 *d++=(-127);
1609 *d++=(char) 255;
1610 }
1611 switch (w)
1612 {
1613 case 0:
1614 break;
1615 case 1:
1616 *d++=0;
1617 *d++=(char) 255;
1618 break;
1619 default:
1620 *d++=(char) (1-w);
1621 *d++=(char) 255;
1622 break;
1623 }
1624 bytecount = d - scanline;
1625
1626 /* Scanline counts (rows*channels) */
1627 for (i=0; i < dim; i++)
1628 {
1629 (void) WriteBlobMSBShort(image,bytecount);
1630 }
1631
1632 /* RLE compressed data */
1633 length = bytecount;
1634 for (i=0; i < dim; i++)
1635 {
1636 (void) WriteBlob( image, length, (unsigned char *) scanline );
1637 }
1638
1639}
1640
1641static void WritePascalString(Image* inImage,const char *inString,int inPad)
1642{
1643 size_t
1644 strLength;
1645 int i;
1646
1647 /* max length is 255 */
1648
1649 strLength = (strlen(inString) > 255UL ) ? 255UL : strlen(inString);
1650
1651 if ( strLength != 0 )
1652 {
1653 (void) WriteBlobByte(inImage,(unsigned char) strLength);
1654 (void) WriteBlob(inImage, strLength, (const unsigned char *) inString);
1655 }
1656 else
1657 (void) WriteBlobByte(inImage, 0);
1658
1659 strLength ++;
1660
1661 if ( (strLength % inPad) == 0 )
1662 return;
1663 for (i=0; i < (long) (inPad-(strLength % inPad)); i++)
1664 (void) WriteBlobByte(inImage,0);
1665}
1666
1667static void WriteResolutionResourceBlock(Image *image)
1668{
1669 unsigned long
1670 x_resolution,
1671 y_resolution;
1672
1673 unsigned short
1674 units;
1675
1676 x_resolution=65536.0*image->x_resolution+0.5;
1677 y_resolution=65536.0*image->y_resolution+0.5;
1678 units=1;
1679 if (image->units == PixelsPerCentimeterResolution)
1680 {
1681 x_resolution=2.54*65536.0*image->x_resolution*0.5;
1682 y_resolution=2.54*65536.0*image->y_resolution+0.5;
1683 units=2;
1684 }
1685 (void) WriteBlob(image,4,(const unsigned char *) "8BIM");
1686 (void) WriteBlobMSBShort(image,0x03ED);
1687 (void) WriteBlobMSBShort(image,0);
1688 (void) WriteBlobMSBLong(image,16); /* resource size */
1689 (void) WriteBlobMSBLong(image,x_resolution);
1690 (void) WriteBlobMSBShort(image,units); /* horizontal resolution unit */
1691 (void) WriteBlobMSBShort(image,units); /* width unit */
1692 (void) WriteBlobMSBLong(image,y_resolution);
1693 (void) WriteBlobMSBShort(image,units); /* vertical resolution unit */
1694 (void) WriteBlobMSBShort(image,units); /* height unit */
1695}
1696
1697static MagickBooleanType WritePSDImage(const ImageInfo *image_info,Image *image)
1698{
1699 const char
1700 *theAttr;
1701
1702 const StringInfo
1703 *profile;
1704
1705 MagickBooleanType
1706 force_white_background = image->matte,
1707 invert_layer_count = MagickFalse,
1708 status;
1709
1710 register long
1711 i;
1712
1713 size_t
1714 num_channels,
1715 packet_size;
1716
1717 unsigned char
1718 layer_name[4];
1719
1720 unsigned long
1721 channel_size,
1722 channelLength,
1723 layer_count,
1724 layer_info_size,
1725 rounded_layer_info_size,
1726 res_extra;
1727
1728 Image
1729 * tmp_image = (Image *) NULL,
1730 * base_image = force_white_background ? image : GetNextImageInList(image);
1731
1732 /*
1733 Open output image file.
1734 */
1735 assert(image_info != (const ImageInfo *) NULL);
1736 assert(image_info->signature == MagickSignature);
1737 assert(image != (Image *) NULL);
1738 assert(image->signature == MagickSignature);
1739 if (image->debug != MagickFalse)
1740 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1741 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1742 if (status == MagickFalse)
1743 return(status);
1744 packet_size=(size_t) (image->depth > 8 ? 6 : 3);
1745 if (image->matte != MagickFalse)
1746 packet_size+=image->depth > 8 ? 2 : 1;
1747 (void) WriteBlob(image,4,(const unsigned char *) "8BPS");
1748 (void) WriteBlobMSBShort(image,1); /* version */
1749 for ( i=1; i<=6; i++)
1750 (void) WriteBlobByte(image, 0); /* 6 bytes of reserved */
1751 if ( force_white_background )
1752 num_channels = 3;
1753 else
1754 {
1755 if (image->storage_class == PseudoClass)
1756 num_channels=(image->matte ? 2UL : 1UL);
1757 else
1758 {
1759 if (image->colorspace != CMYKColorspace)
1760 num_channels=(image->matte ? 4UL : 3UL);
1761 else
1762 num_channels=(image->matte ? 5UL : 4UL);
1763 }
1764 }
1765 (void) WriteBlobMSBShort(image,(unsigned short) num_channels);
1766 (void) WriteBlobMSBLong(image,image->rows);
1767 (void) WriteBlobMSBLong(image,image->columns);
1768 (void) WriteBlobMSBShort(image,(unsigned short)
1769 (image->storage_class == PseudoClass ? 8 : image->depth > 8 ? 16 : 8));
1770 if (((image->colorspace != UndefinedColorspace) ||
1771 (image->colorspace != CMYKColorspace)) &&
1772 (image->colorspace != CMYKColorspace))
1773 {
1774 if (image->colorspace != RGBColorspace)
1775 (void) TransformImageColorspace(image,RGBColorspace);
1776 (void) WriteBlobMSBShort(image,(unsigned short)
1777 (image->storage_class == PseudoClass ? 2 : 3));
1778 }
1779 else
1780 {
1781 if (image->colorspace != RGBColorspace)
1782 (void) TransformImageColorspace(image,CMYKColorspace);
1783 (void) WriteBlobMSBShort(image,4);
1784 }
1785 if ((image->storage_class == DirectClass) || (image->colors > 256))
1786 (void) WriteBlobMSBLong(image,0);
1787 else
1788 {
1789 /*
1790 Write PSD raster colormap.
1791 */
1792 (void) WriteBlobMSBLong(image,768);
1793 for (i=0; i < (long) image->colors; i++)
1794 (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].red));
1795 for ( ; i < 256; i++)
1796 (void) WriteBlobByte(image,0);
1797 for (i=0; i < (long) image->colors; i++)
1798 (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].green));
1799 for ( ; i < 256; i++)
1800 (void) WriteBlobByte(image,0);
1801 for (i=0; i < (long) image->colors; i++)
1802 (void) WriteBlobByte(image,ScaleQuantumToChar(image->colormap[i].blue));
1803 for ( ; i < 256; i++)
1804 (void) WriteBlobByte(image,0);
1805 }
1806 /*
1807 Image resource block.
1808 */
1809 res_extra = 28; /* 0x03EB */
1810 profile=GetImageProfile(image,"8bim");
1811 if (profile == (StringInfo *) NULL)
1812 WriteBlobMSBLong(image, res_extra);
1813 else
1814 {
1815 (void) WriteBlobMSBLong(image,(unsigned long) res_extra +
1816 GetStringInfoLength(profile));
1817 (void) WriteBlob(image,GetStringInfoLength(profile),GetStringInfoDatum(
1818 profile));
1819 }
1820 WriteResolutionResourceBlock(image);
1821
1822compute_layer_info:
1823 layer_count = 0;
1824 layer_info_size = 2;
1825 tmp_image = base_image;
1826 while ( tmp_image != NULL ) {
1827 packet_size=tmp_image->depth > 8 ? 2UL : 1UL;
1828
1829 if (tmp_image->storage_class == PseudoClass)
1830 num_channels = (tmp_image->matte != MagickFalse ? 2UL : 1UL);
1831 else
1832 if (tmp_image->colorspace != CMYKColorspace)
1833 num_channels = (tmp_image->matte != MagickFalse ? 4UL : 3UL);
1834 else
1835 num_channels = (tmp_image->matte != MagickFalse ? 5UL : 4UL);
1836
1837 channelLength=(unsigned long) (tmp_image->columns * tmp_image->rows * packet_size + 2);
1838 layer_info_size += (unsigned long) (4*4 + 2 + num_channels * 6 + 4 + 4 + 4 * 1 + 4 + 12 + num_channels * channelLength);
1839
1840 layer_count++;
1841 tmp_image = GetNextImageInList(tmp_image);
1842 }
1843
1844 /* if the image has a matte, then we need to use layers */
1845 if ( layer_count == 0 && image->matte == MagickTrue )
1846 {
1847 invert_layer_count = MagickTrue;
1848 base_image = image;
1849 goto compute_layer_info; /* yes, goto's suck, but it keeps the code cleaner! */
1850 }
1851
1852 if ( layer_count == 0 )
1853 (void) WriteBlobMSBLong(image, 0);
1854 else
1855 {
1856 (void) WriteBlobMSBLong(image,layer_info_size+4+4);
1857 if ( layer_info_size/2 != (layer_info_size+1)/2 ) /* odd */
1858 rounded_layer_info_size = layer_info_size + 1;
1859 else
1860 rounded_layer_info_size = layer_info_size;
1861 (void) WriteBlobMSBLong(image,rounded_layer_info_size);
1862
1863 if ( invert_layer_count )
1864 layer_count *= -1; /* if we have a matte, then use negative count! */
1865 (void) WriteBlobMSBShort(image,(unsigned short) layer_count);
1866
1867 layer_count = 1;
1868 tmp_image = base_image;
1869 while ( tmp_image != NULL ) {
1870 (void) WriteBlobMSBLong(image,0);
1871 (void) WriteBlobMSBLong(image,0);
1872 (void) WriteBlobMSBLong(image,tmp_image->rows);
1873 (void) WriteBlobMSBLong(image,tmp_image->columns);
1874
1875 packet_size=tmp_image->depth > 8 ? 2UL : 1UL;
1876 channel_size=(unsigned int) ((packet_size*tmp_image->rows*tmp_image->columns)+2);
1877 if (tmp_image->storage_class == PseudoClass) {
1878 (void) WriteBlobMSBShort(image,(unsigned short)
1879 (tmp_image->matte ? 2 : 1));
1880 if (tmp_image->matte) {
1881 (void) WriteBlobMSBShort(image,(unsigned short) -1);
1882 (void) WriteBlobMSBLong(image,channel_size);
1883 }
1884 (void) WriteBlobMSBShort(image, 0);
1885 (void) WriteBlobMSBLong(image, channel_size);
1886 } else
1887 if (tmp_image->colorspace != CMYKColorspace)
1888 {
1889 (void) WriteBlobMSBShort(image,(unsigned short)
1890 (tmp_image->matte ? 4 : 3));
1891 if (tmp_image->matte) {
1892 (void) WriteBlobMSBShort(image,(unsigned short) -1);
1893 (void) WriteBlobMSBLong(image,channel_size);
1894 }
1895 (void) WriteBlobMSBShort(image, 0);
1896 (void) WriteBlobMSBLong(image, channel_size);
1897 (void) WriteBlobMSBShort(image, 1);
1898 (void) WriteBlobMSBLong(image, channel_size);
1899 (void) WriteBlobMSBShort(image, 2);
1900 (void) WriteBlobMSBLong(image, channel_size);
1901 }
1902 else
1903 {
1904 (void) WriteBlobMSBShort(image,(unsigned short)
1905 (tmp_image->matte ? 5 : 4));
1906 if (tmp_image->matte) {
1907 (void) WriteBlobMSBShort(image,(unsigned short) -1);
1908 (void) WriteBlobMSBLong(image,channel_size);
1909 }
1910 (void) WriteBlobMSBShort(image, 0);
1911 (void) WriteBlobMSBLong(image, channel_size);
1912 (void) WriteBlobMSBShort(image, 1);
1913 (void) WriteBlobMSBLong(image, channel_size);
1914 (void) WriteBlobMSBShort(image, 2);
1915 (void) WriteBlobMSBLong(image, channel_size);
1916 (void) WriteBlobMSBShort(image, 3);
1917 (void) WriteBlobMSBLong(image, channel_size);
1918 }
1919
1920 (void) WriteBlob(image, 4, (const unsigned char *) "8BIM");
1921 (void) WriteBlob(image, 4, (const unsigned char *) CompositeOperatorToPSDBlendMode(tmp_image->compose));
1922 (void) WriteBlobByte(image, 255); /* BOGUS: layer opacity */
1923 (void) WriteBlobByte(image, 0);
1924 (void) WriteBlobByte(image, 1); /* BOGUS: layer attributes - visible, etc. */
1925 (void) WriteBlobByte(image, 0);
1926
1927 (void) WriteBlobMSBLong(image, 12);
1928 (void) WriteBlobMSBLong(image, 0);
1929 (void) WriteBlobMSBLong(image, 0);
1930
1931 theAttr=(const char *) GetImageProperty(tmp_image,"label");
1932 if (theAttr) {
1933 WritePascalString( image, theAttr, 4 );
1934 /*
1935 sprintf((char *) &(layer_name[1]), "%4s", theAttr->value );
1936 (void) WriteBlobByte(image, 3);
1937 (void) WriteBlob(image, 3, &layer_name[1]);
1938 */
1939 } else {
1940 (void) FormatMagickString((char *) layer_name,MaxTextExtent,"L%02ld",
1941 layer_count++ );
1942 WritePascalString( image, (char*)layer_name, 4 );
1943 }
1944 tmp_image = GetNextImageInList(tmp_image);
1945 };
1946
1947 /* now the image data! */
1948 tmp_image = base_image;
1949 while ( tmp_image != NULL ) {
1950 status=WriteImageChannels(image_info,image,tmp_image,MagickTrue);
1951
1952 /* add in the pad! */
1953 if ( rounded_layer_info_size != layer_info_size )
1954 (void) WriteBlobByte(image,'\0');
1955
1956 tmp_image = GetNextImageInList(tmp_image);
1957 };
1958
1959 /* user mask data */
1960 (void) WriteBlobMSBLong(image, 0);
1961
1962 }
1963
1964 /* now the background image data! */
1965 if (force_white_background != MagickFalse)
1966 WriteWhiteBackground(image);
1967 else
1968 status=WriteImageChannels(image_info,image,image,MagickFalse);
1969
1970 (void) CloseBlob(image);
1971 return(status);
1972}