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