• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                         CCCC  M   M  Y   Y  K   K                           %
7 %                        C      MM MM   Y Y   K  K                            %
8 %                        C      M M M    Y    KKK                             %
9 %                        C      M   M    Y    K  K                            %
10 %                         CCCC  M   M    Y    K   K                           %
11 %                                                                             %
12 %                                                                             %
13 %                     Read/Write RAW CMYK Image Format                        %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://imagemagick.org/script/license.php                               %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/blob-private.h"
45 #include "MagickCore/cache.h"
46 #include "MagickCore/channel.h"
47 #include "MagickCore/colorspace.h"
48 #include "MagickCore/constitute.h"
49 #include "MagickCore/exception.h"
50 #include "MagickCore/exception-private.h"
51 #include "MagickCore/image.h"
52 #include "MagickCore/image-private.h"
53 #include "MagickCore/list.h"
54 #include "MagickCore/magick.h"
55 #include "MagickCore/memory_.h"
56 #include "MagickCore/monitor.h"
57 #include "MagickCore/monitor-private.h"
58 #include "MagickCore/pixel-accessor.h"
59 #include "MagickCore/quantum-private.h"
60 #include "MagickCore/static.h"
61 #include "MagickCore/statistic.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/module.h"
64 #include "MagickCore/utility.h"
65 
66 /*
67   Forward declarations.
68 */
69 static MagickBooleanType
70   WriteCMYKImage(const ImageInfo *,Image *,ExceptionInfo *);
71 
72 /*
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74 %                                                                             %
75 %                                                                             %
76 %                                                                             %
77 %   R e a d C M Y K I m a g e                                                 %
78 %                                                                             %
79 %                                                                             %
80 %                                                                             %
81 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82 %
83 %  ReadCMYKImage() reads an image of raw CMYK or CMYKA samples and returns it.
84 %  It allocates the memory necessary for the new Image structure and returns a
85 %  pointer to the new image.
86 %
87 %  The format of the ReadCMYKImage method is:
88 %
89 %      Image *ReadCMYKImage(const ImageInfo *image_info,
90 %        ExceptionInfo *exception)
91 %
92 %  A description of each parameter follows:
93 %
94 %    o image_info: the image info.
95 %
96 %    o exception: return any errors or warnings in this structure.
97 %
98 */
ReadCMYKImage(const ImageInfo * image_info,ExceptionInfo * exception)99 static Image *ReadCMYKImage(const ImageInfo *image_info,
100   ExceptionInfo *exception)
101 {
102   const void
103     *stream;
104 
105   Image
106     *canvas_image,
107     *image;
108 
109   MagickBooleanType
110     status;
111 
112   MagickOffsetType
113     scene;
114 
115   QuantumInfo
116     *quantum_info;
117 
118   QuantumType
119     quantum_type;
120 
121   ssize_t
122     i;
123 
124   size_t
125     length;
126 
127   ssize_t
128     count,
129     y;
130 
131   unsigned char
132     *pixels;
133 
134   /*
135     Open image file.
136   */
137   assert(image_info != (const ImageInfo *) NULL);
138   assert(image_info->signature == MagickCoreSignature);
139   if (image_info->debug != MagickFalse)
140     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
141       image_info->filename);
142   assert(exception != (ExceptionInfo *) NULL);
143   assert(exception->signature == MagickCoreSignature);
144   image=AcquireImage(image_info,exception);
145   if ((image->columns == 0) || (image->rows == 0))
146     ThrowReaderException(OptionError,"MustSpecifyImageSize");
147   status=SetImageExtent(image,image->columns,image->rows,exception);
148   if (status == MagickFalse)
149     return(DestroyImageList(image));
150   (void) SetImageColorspace(image,CMYKColorspace,exception);
151   if (image_info->interlace != PartitionInterlace)
152     {
153       status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
154       if (status == MagickFalse)
155         {
156           image=DestroyImageList(image);
157           return((Image *) NULL);
158         }
159       if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
160         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
161           image->filename);
162     }
163   /*
164     Create virtual canvas to support cropping (i.e. image.cmyk[100x100+10+20]).
165   */
166   canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
167     exception);
168   if (canvas_image == (Image *) NULL)
169     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
170   (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
171     exception);
172   quantum_info=AcquireQuantumInfo(image_info,canvas_image);
173   if (quantum_info == (QuantumInfo *) NULL)
174     {
175       canvas_image=DestroyImage(canvas_image);
176       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
177     }
178   quantum_type=CMYKQuantum;
179   if (LocaleCompare(image_info->magick,"CMYKA") == 0)
180     {
181       quantum_type=CMYKAQuantum;
182       image->alpha_trait=BlendPixelTrait;
183     }
184   pixels=GetQuantumPixels(quantum_info);
185   if (image_info->number_scenes != 0)
186     while (image->scene < image_info->scene)
187     {
188       /*
189         Skip to next image.
190       */
191       image->scene++;
192       length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
193       for (y=0; y < (ssize_t) image->rows; y++)
194       {
195         stream=ReadBlobStream(image,length,pixels,&count);
196         if (count != (ssize_t) length)
197           break;
198       }
199     }
200   count=0;
201   length=0;
202   scene=0;
203   status=MagickTrue;
204   stream=NULL;
205   do
206   {
207     /*
208       Read pixels to virtual canvas image then push to image.
209     */
210     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
211       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
212         break;
213     status=SetImageExtent(image,image->columns,image->rows,exception);
214     if (status == MagickFalse)
215       break;
216     if (SetImageColorspace(image,CMYKColorspace,exception) == MagickFalse)
217       break;
218     switch (image_info->interlace)
219     {
220       case NoInterlace:
221       default:
222       {
223         /*
224           No interlacing:  CMYKCMYKCMYKCMYKCMYKCMYK...
225         */
226         if (scene == 0)
227           {
228             length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
229             stream=ReadBlobStream(image,length,pixels,&count);
230           }
231         for (y=0; y < (ssize_t) image->extract_info.height; y++)
232         {
233           const Quantum
234             *magick_restrict p;
235 
236           Quantum
237             *magick_restrict q;
238 
239           ssize_t
240             x;
241 
242           if (count != (ssize_t) length)
243             {
244               status=MagickFalse;
245               ThrowFileException(exception,CorruptImageError,
246                 "UnexpectedEndOfFile",image->filename);
247               break;
248             }
249           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
250             exception);
251           if (q == (Quantum *) NULL)
252             break;
253           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
254             quantum_info,quantum_type,(unsigned char *) stream,exception);
255           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
256             break;
257           if (((y-image->extract_info.y) >= 0) &&
258               ((y-image->extract_info.y) < (ssize_t) image->rows))
259             {
260               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
261                 canvas_image->columns,1,exception);
262               q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
263                 image->columns,1,exception);
264               if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
265                 break;
266               for (x=0; x < (ssize_t) image->columns; x++)
267               {
268                 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
269                 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
270                 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
271                 SetPixelBlack(image,GetPixelBlack(canvas_image,p),q);
272                 SetPixelAlpha(image,OpaqueAlpha,q);
273                 if (image->alpha_trait != UndefinedPixelTrait)
274                   SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
275                 p+=GetPixelChannels(canvas_image);
276                 q+=GetPixelChannels(image);
277               }
278               if (SyncAuthenticPixels(image,exception) == MagickFalse)
279                 break;
280             }
281           if (image->previous == (Image *) NULL)
282             {
283               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
284                 image->rows);
285               if (status == MagickFalse)
286                 break;
287             }
288           stream=ReadBlobStream(image,length,pixels,&count);
289         }
290         break;
291       }
292       case LineInterlace:
293       {
294         static QuantumType
295           quantum_types[5] =
296           {
297             CyanQuantum,
298             MagentaQuantum,
299             YellowQuantum,
300             BlackQuantum,
301             OpacityQuantum
302           };
303 
304         /*
305           Line interlacing:  CCC...MMM...YYY...KKK...CCC...MMM...YYY...KKK...
306         */
307         if (scene == 0)
308           {
309             length=GetQuantumExtent(canvas_image,quantum_info,CyanQuantum);
310             stream=ReadBlobStream(image,length,pixels,&count);
311           }
312         for (y=0; y < (ssize_t) image->extract_info.height; y++)
313         {
314           for (i=0; i < (ssize_t) (image->alpha_trait != UndefinedPixelTrait ? 5 : 4); i++)
315           {
316             const Quantum
317               *magick_restrict p;
318 
319             Quantum
320               *magick_restrict q;
321 
322             ssize_t
323               x;
324 
325             if (count != (ssize_t) length)
326               {
327                 status=MagickFalse;
328                 ThrowFileException(exception,CorruptImageError,
329                   "UnexpectedEndOfFile",image->filename);
330                 break;
331               }
332             quantum_type=quantum_types[i];
333             q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
334               exception);
335             if (q == (Quantum *) NULL)
336               break;
337             length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
338               quantum_info,quantum_type,(unsigned char *) stream,exception);
339             if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
340               break;
341             if (((y-image->extract_info.y) >= 0) &&
342                 ((y-image->extract_info.y) < (ssize_t) image->rows))
343               {
344                 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
345                   0,canvas_image->columns,1,exception);
346                 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
347                   image->columns,1,exception);
348                 if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
349                   break;
350                 for (x=0; x < (ssize_t) image->columns; x++)
351                 {
352                   switch (quantum_type)
353                   {
354                     case CyanQuantum:
355                     {
356                       SetPixelCyan(image,GetPixelCyan(canvas_image,p),q);
357                       break;
358                     }
359                     case MagentaQuantum:
360                     {
361                       SetPixelMagenta(image,GetPixelMagenta(canvas_image,p),q);
362                       break;
363                     }
364                     case YellowQuantum:
365                     {
366                       SetPixelYellow(image,GetPixelYellow(canvas_image,p),q);
367                       break;
368                     }
369                     case BlackQuantum:
370                     {
371                       SetPixelBlack(image,GetPixelBlack(canvas_image,p),q);
372                       break;
373                     }
374                     case OpacityQuantum:
375                     {
376                       SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
377                       break;
378                     }
379                     default:
380                       break;
381                   }
382                   p+=GetPixelChannels(canvas_image);
383                   q+=GetPixelChannels(image);
384                 }
385                 if (SyncAuthenticPixels(image,exception) == MagickFalse)
386                   break;
387               }
388             stream=ReadBlobStream(image,length,pixels,&count);
389           }
390           if (image->previous == (Image *) NULL)
391             {
392               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
393                 image->rows);
394               if (status == MagickFalse)
395                 break;
396             }
397         }
398         break;
399       }
400       case PlaneInterlace:
401       {
402         /*
403           Plane interlacing:  CCCCCC...MMMMMM...YYYYYY...KKKKKK...
404         */
405         if (scene == 0)
406           {
407             length=GetQuantumExtent(canvas_image,quantum_info,CyanQuantum);
408             stream=ReadBlobStream(image,length,pixels,&count);
409           }
410         for (y=0; y < (ssize_t) image->extract_info.height; y++)
411         {
412           const Quantum
413             *magick_restrict p;
414 
415           Quantum
416             *magick_restrict q;
417 
418           ssize_t
419             x;
420 
421           if (count != (ssize_t) length)
422             {
423               status=MagickFalse;
424               ThrowFileException(exception,CorruptImageError,
425                 "UnexpectedEndOfFile",image->filename);
426               break;
427             }
428           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
429             exception);
430           if (q == (Quantum *) NULL)
431             break;
432           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
433             quantum_info,CyanQuantum,(unsigned char *) stream,exception);
434           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
435             break;
436           if (((y-image->extract_info.y) >= 0) &&
437               ((y-image->extract_info.y) < (ssize_t) image->rows))
438             {
439               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
440                 canvas_image->columns,1,exception);
441               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
442                 image->columns,1,exception);
443               if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
444                 break;
445               for (x=0; x < (ssize_t) image->columns; x++)
446               {
447                 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
448                 p+=GetPixelChannels(canvas_image);
449                 q+=GetPixelChannels(image);
450               }
451               if (SyncAuthenticPixels(image,exception) == MagickFalse)
452                 break;
453             }
454           stream=ReadBlobStream(image,length,pixels,&count);
455         }
456         if (image->previous == (Image *) NULL)
457           {
458             status=SetImageProgress(image,LoadImageTag,1,6);
459             if (status == MagickFalse)
460               break;
461           }
462         for (y=0; y < (ssize_t) image->extract_info.height; y++)
463         {
464           const Quantum
465             *magick_restrict p;
466 
467           Quantum
468             *magick_restrict q;
469 
470           ssize_t
471             x;
472 
473           if (count != (ssize_t) length)
474             {
475               status=MagickFalse;
476               ThrowFileException(exception,CorruptImageError,
477                 "UnexpectedEndOfFile",image->filename);
478               break;
479             }
480           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
481             exception);
482           if (q == (Quantum *) NULL)
483             break;
484           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
485             quantum_info,MagentaQuantum,(unsigned char *) stream,exception);
486           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
487             break;
488           if (((y-image->extract_info.y) >= 0) &&
489               ((y-image->extract_info.y) < (ssize_t) image->rows))
490             {
491               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
492                 canvas_image->columns,1,exception);
493               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
494                 image->columns,1,exception);
495               if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
496                 break;
497               for (x=0; x < (ssize_t) image->columns; x++)
498               {
499                 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
500                 p+=GetPixelChannels(canvas_image);
501                 q+=GetPixelChannels(image);
502               }
503               if (SyncAuthenticPixels(image,exception) == MagickFalse)
504                 break;
505            }
506           stream=ReadBlobStream(image,length,pixels,&count);
507         }
508         if (image->previous == (Image *) NULL)
509           {
510             status=SetImageProgress(image,LoadImageTag,2,6);
511             if (status == MagickFalse)
512               break;
513           }
514         for (y=0; y < (ssize_t) image->extract_info.height; y++)
515         {
516           const Quantum
517             *magick_restrict p;
518 
519           Quantum
520             *magick_restrict q;
521 
522           ssize_t
523             x;
524 
525           if (count != (ssize_t) length)
526             {
527               status=MagickFalse;
528               ThrowFileException(exception,CorruptImageError,
529                 "UnexpectedEndOfFile",image->filename);
530               break;
531             }
532           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
533             exception);
534           if (q == (Quantum *) NULL)
535             break;
536           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
537             quantum_info,YellowQuantum,(unsigned char *) stream,exception);
538           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
539             break;
540           if (((y-image->extract_info.y) >= 0) &&
541               ((y-image->extract_info.y) < (ssize_t) image->rows))
542             {
543               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
544                 canvas_image->columns,1,exception);
545               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
546                 image->columns,1,exception);
547               if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
548                 break;
549               for (x=0; x < (ssize_t) image->columns; x++)
550               {
551                 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
552                 p+=GetPixelChannels(canvas_image);
553                 q+=GetPixelChannels(image);
554               }
555               if (SyncAuthenticPixels(image,exception) == MagickFalse)
556                 break;
557             }
558           stream=ReadBlobStream(image,length,pixels,&count);
559         }
560         if (image->previous == (Image *) NULL)
561           {
562             status=SetImageProgress(image,LoadImageTag,3,6);
563             if (status == MagickFalse)
564               break;
565           }
566         for (y=0; y < (ssize_t) image->extract_info.height; y++)
567         {
568           const Quantum
569             *magick_restrict p;
570 
571           Quantum
572             *magick_restrict q;
573 
574           ssize_t
575             x;
576 
577           if (count != (ssize_t) length)
578             {
579               status=MagickFalse;
580               ThrowFileException(exception,CorruptImageError,
581                 "UnexpectedEndOfFile",image->filename);
582               break;
583             }
584           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
585             exception);
586           if (q == (Quantum *) NULL)
587             break;
588           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
589             quantum_info,BlackQuantum,(unsigned char *) stream,exception);
590           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
591             break;
592           if (((y-image->extract_info.y) >= 0) &&
593               ((y-image->extract_info.y) < (ssize_t) image->rows))
594             {
595               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
596                 canvas_image->columns,1,exception);
597               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
598                 image->columns,1,exception);
599               if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
600                 break;
601               for (x=0; x < (ssize_t) image->columns; x++)
602               {
603                 SetPixelBlack(image,GetPixelBlack(canvas_image,p),q);
604                 p+=GetPixelChannels(canvas_image);
605                 q+=GetPixelChannels(image);
606               }
607               if (SyncAuthenticPixels(image,exception) == MagickFalse)
608                 break;
609             }
610           stream=ReadBlobStream(image,length,pixels,&count);
611         }
612         if (image->previous == (Image *) NULL)
613           {
614             status=SetImageProgress(image,LoadImageTag,4,6);
615             if (status == MagickFalse)
616               break;
617           }
618         if (image->alpha_trait != UndefinedPixelTrait)
619           {
620             for (y=0; y < (ssize_t) image->extract_info.height; y++)
621             {
622               const Quantum
623                 *magick_restrict p;
624 
625               Quantum
626                 *magick_restrict q;
627 
628               ssize_t
629                 x;
630 
631               if (count != (ssize_t) length)
632                 {
633                   status=MagickFalse;
634                   ThrowFileException(exception,CorruptImageError,
635                     "UnexpectedEndOfFile",image->filename);
636                   break;
637                 }
638               q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
639                 exception);
640               if (q == (Quantum *) NULL)
641                 break;
642               length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
643                 quantum_info,AlphaQuantum,(unsigned char *) stream,exception);
644               if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
645                 break;
646               if (((y-image->extract_info.y) >= 0) &&
647                   ((y-image->extract_info.y) < (ssize_t) image->rows))
648                 {
649                   p=GetVirtualPixels(canvas_image,
650                     canvas_image->extract_info.x,0,canvas_image->columns,1,
651                     exception);
652                   q=GetAuthenticPixels(image,0,y-image->extract_info.y,
653                     image->columns,1,exception);
654                   if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
655                     break;
656                   for (x=0; x < (ssize_t) image->columns; x++)
657                   {
658                     SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
659                     p+=GetPixelChannels(canvas_image);
660                     q+=GetPixelChannels(image);
661                   }
662                   if (SyncAuthenticPixels(image,exception) == MagickFalse)
663                     break;
664                 }
665               stream=ReadBlobStream(image,length,pixels,&count);
666             }
667             if (image->previous == (Image *) NULL)
668               {
669                 status=SetImageProgress(image,LoadImageTag,5,6);
670                 if (status == MagickFalse)
671                   break;
672               }
673           }
674         if (image->previous == (Image *) NULL)
675           {
676             status=SetImageProgress(image,LoadImageTag,6,6);
677             if (status == MagickFalse)
678               break;
679           }
680         break;
681       }
682       case PartitionInterlace:
683       {
684         /*
685           Partition interlacing:  CCCCCC..., MMMMMM..., YYYYYY..., KKKKKK...
686         */
687         AppendImageFormat("C",image->filename);
688         status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
689         if (status == MagickFalse)
690           break;
691         if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
692           {
693             status=MagickFalse;
694             ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
695               image->filename);
696             break;
697           }
698         length=GetQuantumExtent(canvas_image,quantum_info,CyanQuantum);
699         for (i=0; i < (ssize_t) scene; i++)
700         {
701           for (y=0; y < (ssize_t) image->extract_info.height; y++)
702           {
703             stream=ReadBlobStream(image,length,pixels,&count);
704             if (count != (ssize_t) length)
705               break;
706           }
707           if (count != (ssize_t) length)
708             break;
709         }
710         stream=ReadBlobStream(image,length,pixels,&count);
711         for (y=0; y < (ssize_t) image->extract_info.height; y++)
712         {
713           const Quantum
714             *magick_restrict p;
715 
716           Quantum
717             *magick_restrict q;
718 
719           ssize_t
720             x;
721 
722           if (count != (ssize_t) length)
723             {
724               status=MagickFalse;
725               ThrowFileException(exception,CorruptImageError,
726                 "UnexpectedEndOfFile",image->filename);
727               break;
728             }
729           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
730             exception);
731           if (q == (Quantum *) NULL)
732             break;
733           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
734             quantum_info,CyanQuantum,(unsigned char *) stream,exception);
735           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
736             break;
737           if (((y-image->extract_info.y) >= 0) &&
738               ((y-image->extract_info.y) < (ssize_t) image->rows))
739             {
740               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
741                 canvas_image->columns,1,exception);
742               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
743                 image->columns,1,exception);
744               if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
745                 break;
746               for (x=0; x < (ssize_t) image->columns; x++)
747               {
748                 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
749                 p+=GetPixelChannels(canvas_image);
750                 q+=GetPixelChannels(image);
751               }
752               if (SyncAuthenticPixels(image,exception) == MagickFalse)
753                 break;
754             }
755           stream=ReadBlobStream(image,length,pixels,&count);
756         }
757         if (image->previous == (Image *) NULL)
758           {
759             status=SetImageProgress(image,LoadImageTag,1,5);
760             if (status == MagickFalse)
761               break;
762           }
763         (void) CloseBlob(image);
764         AppendImageFormat("M",image->filename);
765         status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
766         if (status == MagickFalse)
767           break;
768         length=GetQuantumExtent(canvas_image,quantum_info,MagentaQuantum);
769         for (i=0; i < (ssize_t) scene; i++)
770         {
771           for (y=0; y < (ssize_t) image->extract_info.height; y++)
772           {
773             stream=ReadBlobStream(image,length,pixels,&count);
774             if (count != (ssize_t) length)
775               break;
776           }
777           if (count != (ssize_t) length)
778             break;
779         }
780         stream=ReadBlobStream(image,length,pixels,&count);
781         for (y=0; y < (ssize_t) image->extract_info.height; y++)
782         {
783           const Quantum
784             *magick_restrict p;
785 
786           Quantum
787             *magick_restrict q;
788 
789           ssize_t
790             x;
791 
792           if (count != (ssize_t) length)
793             {
794               status=MagickFalse;
795               ThrowFileException(exception,CorruptImageError,
796                 "UnexpectedEndOfFile",image->filename);
797               break;
798             }
799           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
800             exception);
801           if (q == (Quantum *) NULL)
802             break;
803           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
804             quantum_info,MagentaQuantum,(unsigned char *) stream,exception);
805           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
806             break;
807           if (((y-image->extract_info.y) >= 0) &&
808               ((y-image->extract_info.y) < (ssize_t) image->rows))
809             {
810               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
811                 canvas_image->columns,1,exception);
812               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
813                 image->columns,1,exception);
814               if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
815                 break;
816               for (x=0; x < (ssize_t) image->columns; x++)
817               {
818                 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
819                 p+=GetPixelChannels(canvas_image);
820                 q+=GetPixelChannels(image);
821               }
822               if (SyncAuthenticPixels(image,exception) == MagickFalse)
823                 break;
824            }
825           stream=ReadBlobStream(image,length,pixels,&count);
826         }
827         if (image->previous == (Image *) NULL)
828           {
829             status=SetImageProgress(image,LoadImageTag,2,5);
830             if (status == MagickFalse)
831               break;
832           }
833         (void) CloseBlob(image);
834         AppendImageFormat("Y",image->filename);
835         status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
836         if (status == MagickFalse)
837           break;
838         length=GetQuantumExtent(canvas_image,quantum_info,YellowQuantum);
839         for (i=0; i < (ssize_t) scene; i++)
840         {
841           for (y=0; y < (ssize_t) image->extract_info.height; y++)
842           {
843             stream=ReadBlobStream(image,length,pixels,&count);
844             if (count != (ssize_t) length)
845               break;
846           }
847           if (count != (ssize_t) length)
848             break;
849         }
850         stream=ReadBlobStream(image,length,pixels,&count);
851         for (y=0; y < (ssize_t) image->extract_info.height; y++)
852         {
853           const Quantum
854             *magick_restrict p;
855 
856           Quantum
857             *magick_restrict q;
858 
859           ssize_t
860             x;
861 
862           if (count != (ssize_t) length)
863             {
864               status=MagickFalse;
865               ThrowFileException(exception,CorruptImageError,
866                 "UnexpectedEndOfFile",image->filename);
867               break;
868             }
869           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
870             exception);
871           if (q == (Quantum *) NULL)
872             break;
873           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
874             quantum_info,YellowQuantum,(unsigned char *) stream,exception);
875           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
876             break;
877           if (((y-image->extract_info.y) >= 0) &&
878               ((y-image->extract_info.y) < (ssize_t) image->rows))
879             {
880               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
881                 canvas_image->columns,1,exception);
882               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
883                 image->columns,1,exception);
884               if ((p == (const Quantum *) NULL) ||
885                   (q == (Quantum *) NULL))
886                 break;
887               for (x=0; x < (ssize_t) image->columns; x++)
888               {
889                 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
890                 p+=GetPixelChannels(canvas_image);
891                 q+=GetPixelChannels(image);
892               }
893               if (SyncAuthenticPixels(image,exception) == MagickFalse)
894                 break;
895            }
896           stream=ReadBlobStream(image,length,pixels,&count);
897         }
898         if (image->previous == (Image *) NULL)
899           {
900             status=SetImageProgress(image,LoadImageTag,3,5);
901             if (status == MagickFalse)
902               break;
903           }
904         (void) CloseBlob(image);
905         AppendImageFormat("K",image->filename);
906         status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
907         if (status == MagickFalse)
908           break;
909         length=GetQuantumExtent(canvas_image,quantum_info,BlackQuantum);
910         for (i=0; i < (ssize_t) scene; i++)
911         {
912           for (y=0; y < (ssize_t) image->extract_info.height; y++)
913           {
914             stream=ReadBlobStream(image,length,pixels,&count);
915             if (count != (ssize_t) length)
916               break;
917           }
918           if (count != (ssize_t) length)
919             break;
920         }
921         stream=ReadBlobStream(image,length,pixels,&count);
922         for (y=0; y < (ssize_t) image->extract_info.height; y++)
923         {
924           const Quantum
925             *magick_restrict p;
926 
927           Quantum
928             *magick_restrict q;
929 
930           ssize_t
931             x;
932 
933           if (count != (ssize_t) length)
934             {
935               status=MagickFalse;
936               ThrowFileException(exception,CorruptImageError,
937                 "UnexpectedEndOfFile",image->filename);
938               break;
939             }
940           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
941             exception);
942           if (q == (Quantum *) NULL)
943             break;
944           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
945             quantum_info,BlackQuantum,(unsigned char *) stream,exception);
946           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
947             break;
948           if (((y-image->extract_info.y) >= 0) &&
949               ((y-image->extract_info.y) < (ssize_t) image->rows))
950             {
951               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
952                 canvas_image->columns,1,exception);
953               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
954                 image->columns,1,exception);
955               if ((p == (const Quantum *) NULL) ||
956                   (q == (Quantum *) NULL))
957                 break;
958               for (x=0; x < (ssize_t) image->columns; x++)
959               {
960                 SetPixelBlack(image,GetPixelBlack(canvas_image,p),q);
961                 p+=GetPixelChannels(canvas_image);
962                 q+=GetPixelChannels(image);
963               }
964               if (SyncAuthenticPixels(image,exception) == MagickFalse)
965                 break;
966            }
967           stream=ReadBlobStream(image,length,pixels,&count);
968         }
969         if (image->previous == (Image *) NULL)
970           {
971             status=SetImageProgress(image,LoadImageTag,3,5);
972             if (status == MagickFalse)
973               break;
974           }
975         if (image->alpha_trait != UndefinedPixelTrait)
976           {
977             (void) CloseBlob(image);
978             AppendImageFormat("A",image->filename);
979             status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
980             if (status == MagickFalse)
981               break;
982             length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
983             for (i=0; i < (ssize_t) scene; i++)
984             {
985               for (y=0; y < (ssize_t) image->extract_info.height; y++)
986               {
987                 stream=ReadBlobStream(image,length,pixels,&count);
988                 if (count != (ssize_t) length)
989                   break;
990               }
991               if (count != (ssize_t) length)
992                 break;
993             }
994             stream=ReadBlobStream(image,length,pixels,&count);
995             for (y=0; y < (ssize_t) image->extract_info.height; y++)
996             {
997               const Quantum
998                 *magick_restrict p;
999 
1000               Quantum
1001                 *magick_restrict q;
1002 
1003               ssize_t
1004                 x;
1005 
1006               if (count != (ssize_t) length)
1007                 {
1008                   status=MagickFalse;
1009                   ThrowFileException(exception,CorruptImageError,
1010                     "UnexpectedEndOfFile",image->filename);
1011                   break;
1012                 }
1013               q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
1014                 exception);
1015               if (q == (Quantum *) NULL)
1016                 break;
1017               length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
1018                 quantum_info,YellowQuantum,(unsigned char *) stream,exception);
1019               if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
1020                 break;
1021               if (((y-image->extract_info.y) >= 0) &&
1022                   ((y-image->extract_info.y) < (ssize_t) image->rows))
1023                 {
1024                   p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
1025                     0,canvas_image->columns,1,exception);
1026                   q=GetAuthenticPixels(image,0,y-image->extract_info.y,
1027                     image->columns,1,exception);
1028                   if ((p == (const Quantum *) NULL) ||
1029                       (q == (Quantum *) NULL))
1030                     break;
1031                   for (x=0; x < (ssize_t) image->columns; x++)
1032                   {
1033                     SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
1034                     p+=GetPixelChannels(canvas_image);
1035                     q+=GetPixelChannels(image);
1036                   }
1037                   if (SyncAuthenticPixels(image,exception) == MagickFalse)
1038                     break;
1039                }
1040               stream=ReadBlobStream(image,length,pixels,&count);
1041             }
1042             if (image->previous == (Image *) NULL)
1043               {
1044                 status=SetImageProgress(image,LoadImageTag,4,5);
1045                 if (status == MagickFalse)
1046                   break;
1047               }
1048           }
1049         if (image->previous == (Image *) NULL)
1050           {
1051             status=SetImageProgress(image,LoadImageTag,5,5);
1052             if (status == MagickFalse)
1053               break;
1054           }
1055         break;
1056       }
1057     }
1058     if (status == MagickFalse)
1059       break;
1060     SetQuantumImageType(image,quantum_type);
1061     /*
1062       Proceed to next image.
1063     */
1064     if (image_info->number_scenes != 0)
1065       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1066         break;
1067     if (count == (ssize_t) length)
1068       {
1069         /*
1070           Allocate next image structure.
1071         */
1072         AcquireNextImage(image_info,image,exception);
1073         if (GetNextImageInList(image) == (Image *) NULL)
1074           {
1075             status=MagickFalse;
1076             break;
1077           }
1078         image=SyncNextImageInList(image);
1079         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1080           GetBlobSize(image));
1081         if (status == MagickFalse)
1082           break;
1083       }
1084     scene++;
1085   } while (count == (ssize_t) length);
1086   quantum_info=DestroyQuantumInfo(quantum_info);
1087   canvas_image=DestroyImage(canvas_image);
1088   (void) CloseBlob(image);
1089   if (status == MagickFalse)
1090     return(DestroyImageList(image));
1091   return(GetFirstImageInList(image));
1092 }
1093 
1094 /*
1095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1096 %                                                                             %
1097 %                                                                             %
1098 %                                                                             %
1099 %   R e g i s t e r C M Y K I m a g e                                         %
1100 %                                                                             %
1101 %                                                                             %
1102 %                                                                             %
1103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1104 %
1105 %  RegisterCMYKImage() adds attributes for the CMYK image format to
1106 %  the list of supported formats.  The attributes include the image format
1107 %  tag, a method to read and/or write the format, whether the format
1108 %  supports the saving of more than one frame to the same file or blob,
1109 %  whether the format supports native in-memory I/O, and a brief
1110 %  description of the format.
1111 %
1112 %  The format of the RegisterCMYKImage method is:
1113 %
1114 %      size_t RegisterCMYKImage(void)
1115 %
1116 */
RegisterCMYKImage(void)1117 ModuleExport size_t RegisterCMYKImage(void)
1118 {
1119   MagickInfo
1120     *entry;
1121 
1122   entry=AcquireMagickInfo("CMYK","CMYK",
1123     "Raw cyan, magenta, yellow, and black samples");
1124   entry->decoder=(DecodeImageHandler *) ReadCMYKImage;
1125   entry->encoder=(EncodeImageHandler *) WriteCMYKImage;
1126   entry->flags|=CoderRawSupportFlag;
1127   entry->flags|=CoderEndianSupportFlag;
1128   (void) RegisterMagickInfo(entry);
1129   entry=AcquireMagickInfo("CMYK","CMYKA",
1130     "Raw cyan, magenta, yellow, black, and alpha samples");
1131   entry->decoder=(DecodeImageHandler *) ReadCMYKImage;
1132   entry->encoder=(EncodeImageHandler *) WriteCMYKImage;
1133   entry->flags|=CoderRawSupportFlag;
1134   entry->flags|=CoderEndianSupportFlag;
1135   (void) RegisterMagickInfo(entry);
1136   return(MagickImageCoderSignature);
1137 }
1138 
1139 /*
1140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1141 %                                                                             %
1142 %                                                                             %
1143 %                                                                             %
1144 %   U n r e g i s t e r C M Y K I m a g e                                     %
1145 %                                                                             %
1146 %                                                                             %
1147 %                                                                             %
1148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1149 %
1150 %  UnregisterCMYKImage() removes format registrations made by the
1151 %  CMYK module from the list of supported formats.
1152 %
1153 %  The format of the UnregisterCMYKImage method is:
1154 %
1155 %      UnregisterCMYKImage(void)
1156 %
1157 */
UnregisterCMYKImage(void)1158 ModuleExport void UnregisterCMYKImage(void)
1159 {
1160   (void) UnregisterMagickInfo("CMYK");
1161   (void) UnregisterMagickInfo("CMYKA");
1162 }
1163 
1164 /*
1165 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1166 %                                                                             %
1167 %                                                                             %
1168 %                                                                             %
1169 %   W r i t e C M Y K I m a g e                                               %
1170 %                                                                             %
1171 %                                                                             %
1172 %                                                                             %
1173 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1174 %
1175 %  WriteCMYKImage() writes an image to a file in cyan, magenta, yellow, and
1176 %  black,rasterfile format.
1177 %
1178 %  The format of the WriteCMYKImage method is:
1179 %
1180 %      MagickBooleanType WriteCMYKImage(const ImageInfo *image_info,
1181 %        Image *image,ExceptionInfo *exception)
1182 %
1183 %  A description of each parameter follows.
1184 %
1185 %    o image_info: the image info.
1186 %
1187 %    o image:  The image.
1188 %
1189 %    o exception: return any errors or warnings in this structure.
1190 %
1191 */
WriteCMYKImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)1192 static MagickBooleanType WriteCMYKImage(const ImageInfo *image_info,
1193   Image *image,ExceptionInfo *exception)
1194 {
1195   MagickBooleanType
1196     status;
1197 
1198   MagickOffsetType
1199     scene;
1200 
1201   QuantumInfo
1202     *quantum_info;
1203 
1204   QuantumType
1205     quantum_type;
1206 
1207   size_t
1208     imageListLength,
1209     length;
1210 
1211   ssize_t
1212     count,
1213     y;
1214 
1215   unsigned char
1216     *pixels;
1217 
1218   /*
1219     Allocate memory for pixels.
1220   */
1221   assert(image_info != (const ImageInfo *) NULL);
1222   assert(image_info->signature == MagickCoreSignature);
1223   assert(image != (Image *) NULL);
1224   assert(image->signature == MagickCoreSignature);
1225   if (image->debug != MagickFalse)
1226     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1227   if (image_info->interlace != PartitionInterlace)
1228     {
1229       /*
1230         Open output image file.
1231       */
1232       status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1233       if (status == MagickFalse)
1234         return(status);
1235     }
1236   scene=0;
1237   imageListLength=GetImageListLength(image);
1238   do
1239   {
1240     /*
1241       Convert MIFF to CMYK raster pixels.
1242     */
1243     if (image->colorspace != CMYKColorspace)
1244       (void) TransformImageColorspace(image,CMYKColorspace,exception);
1245     quantum_type=CMYKQuantum;
1246     if (LocaleCompare(image_info->magick,"CMYKA") == 0)
1247       {
1248         quantum_type=CMYKAQuantum;
1249         if (image->alpha_trait == UndefinedPixelTrait)
1250           (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1251       }
1252     quantum_info=AcquireQuantumInfo(image_info,image);
1253     if (quantum_info == (QuantumInfo *) NULL)
1254       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1255     pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1256     switch (image_info->interlace)
1257     {
1258       case NoInterlace:
1259       default:
1260       {
1261         /*
1262           No interlacing:  CMYKCMYKCMYKCMYKCMYKCMYK...
1263         */
1264         for (y=0; y < (ssize_t) image->rows; y++)
1265         {
1266           const Quantum
1267             *magick_restrict p;
1268 
1269           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1270           if (p == (const Quantum *) NULL)
1271             break;
1272           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1273             quantum_type,pixels,exception);
1274           count=WriteBlob(image,length,pixels);
1275           if (count != (ssize_t) length)
1276             break;
1277           if (image->previous == (Image *) NULL)
1278             {
1279               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1280                 image->rows);
1281               if (status == MagickFalse)
1282                 break;
1283             }
1284         }
1285         break;
1286       }
1287       case LineInterlace:
1288       {
1289         /*
1290           Line interlacing:  CCC...MMM...YYY...KKK...CCC...MMM...YYY...KKK...
1291         */
1292         for (y=0; y < (ssize_t) image->rows; y++)
1293         {
1294           const Quantum
1295             *magick_restrict p;
1296 
1297           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1298           if (p == (const Quantum *) NULL)
1299             break;
1300           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1301             CyanQuantum,pixels,exception);
1302           count=WriteBlob(image,length,pixels);
1303           if (count != (ssize_t) length)
1304             break;
1305           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1306             MagentaQuantum,pixels,exception);
1307           count=WriteBlob(image,length,pixels);
1308           if (count != (ssize_t) length)
1309             break;
1310           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1311             YellowQuantum,pixels,exception);
1312           count=WriteBlob(image,length,pixels);
1313           if (count != (ssize_t) length)
1314             break;
1315           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1316             BlackQuantum,pixels,exception);
1317           count=WriteBlob(image,length,pixels);
1318           if (count != (ssize_t) length)
1319             break;
1320           if (quantum_type == CMYKAQuantum)
1321             {
1322               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1323                 AlphaQuantum,pixels,exception);
1324               count=WriteBlob(image,length,pixels);
1325               if (count != (ssize_t) length)
1326                 break;
1327             }
1328           if (image->previous == (Image *) NULL)
1329             {
1330               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1331                 image->rows);
1332               if (status == MagickFalse)
1333                 break;
1334             }
1335         }
1336         break;
1337       }
1338       case PlaneInterlace:
1339       {
1340         /*
1341           Plane interlacing:  CCCCCC...MMMMMM...YYYYYY...KKKKKK...
1342         */
1343         for (y=0; y < (ssize_t) image->rows; y++)
1344         {
1345           const Quantum
1346             *magick_restrict p;
1347 
1348           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1349           if (p == (const Quantum *) NULL)
1350             break;
1351           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1352             CyanQuantum,pixels,exception);
1353           count=WriteBlob(image,length,pixels);
1354           if (count != (ssize_t) length)
1355             break;
1356         }
1357         if (image->previous == (Image *) NULL)
1358           {
1359             status=SetImageProgress(image,SaveImageTag,1,6);
1360             if (status == MagickFalse)
1361               break;
1362           }
1363         for (y=0; y < (ssize_t) image->rows; y++)
1364         {
1365           const Quantum
1366             *magick_restrict p;
1367 
1368           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1369           if (p == (const Quantum *) NULL)
1370             break;
1371           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1372             MagentaQuantum,pixels,exception);
1373           count=WriteBlob(image,length,pixels);
1374           if (count != (ssize_t) length)
1375             break;
1376         }
1377         if (image->previous == (Image *) NULL)
1378           {
1379             status=SetImageProgress(image,SaveImageTag,2,6);
1380             if (status == MagickFalse)
1381               break;
1382           }
1383         for (y=0; y < (ssize_t) image->rows; y++)
1384         {
1385           const Quantum
1386             *magick_restrict p;
1387 
1388           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1389           if (p == (const Quantum *) NULL)
1390             break;
1391           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1392             YellowQuantum,pixels,exception);
1393           count=WriteBlob(image,length,pixels);
1394           if (count != (ssize_t) length)
1395             break;
1396         }
1397         if (image->previous == (Image *) NULL)
1398           {
1399             status=SetImageProgress(image,SaveImageTag,3,6);
1400             if (status == MagickFalse)
1401               break;
1402           }
1403         for (y=0; y < (ssize_t) image->rows; y++)
1404         {
1405           const Quantum
1406             *magick_restrict p;
1407 
1408           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1409           if (p == (const Quantum *) NULL)
1410             break;
1411           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1412             BlackQuantum,pixels,exception);
1413           count=WriteBlob(image,length,pixels);
1414           if (count != (ssize_t) length)
1415             break;
1416         }
1417         if (image->previous == (Image *) NULL)
1418           {
1419             status=SetImageProgress(image,SaveImageTag,4,6);
1420             if (status == MagickFalse)
1421               break;
1422           }
1423         if (quantum_type == CMYKAQuantum)
1424           {
1425             for (y=0; y < (ssize_t) image->rows; y++)
1426             {
1427               const Quantum
1428                 *magick_restrict p;
1429 
1430               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1431               if (p == (const Quantum *) NULL)
1432                 break;
1433               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1434                 AlphaQuantum,pixels,exception);
1435               count=WriteBlob(image,length,pixels);
1436               if (count != (ssize_t) length)
1437               break;
1438             }
1439             if (image->previous == (Image *) NULL)
1440               {
1441                 status=SetImageProgress(image,SaveImageTag,5,6);
1442                 if (status == MagickFalse)
1443                   break;
1444               }
1445           }
1446         if (image_info->interlace == PartitionInterlace)
1447           (void) CopyMagickString(image->filename,image_info->filename,
1448             MagickPathExtent);
1449         if (image->previous == (Image *) NULL)
1450           {
1451             status=SetImageProgress(image,SaveImageTag,6,6);
1452             if (status == MagickFalse)
1453               break;
1454           }
1455         break;
1456       }
1457       case PartitionInterlace:
1458       {
1459         /*
1460           Partition interlacing:  CCCCCC..., MMMMMM..., YYYYYY..., KKKKKK...
1461         */
1462         AppendImageFormat("C",image->filename);
1463         status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1464           AppendBinaryBlobMode,exception);
1465         if (status == MagickFalse)
1466           return(status);
1467         for (y=0; y < (ssize_t) image->rows; y++)
1468         {
1469           const Quantum
1470             *magick_restrict p;
1471 
1472           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1473           if (p == (const Quantum *) NULL)
1474             break;
1475           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1476             CyanQuantum,pixels,exception);
1477           count=WriteBlob(image,length,pixels);
1478           if (count != (ssize_t) length)
1479             break;
1480         }
1481         if (image->previous == (Image *) NULL)
1482           {
1483             status=SetImageProgress(image,SaveImageTag,1,6);
1484             if (status == MagickFalse)
1485               break;
1486           }
1487         (void) CloseBlob(image);
1488         AppendImageFormat("M",image->filename);
1489         status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1490           AppendBinaryBlobMode,exception);
1491         if (status == MagickFalse)
1492           return(status);
1493         for (y=0; y < (ssize_t) image->rows; y++)
1494         {
1495           const Quantum
1496             *magick_restrict p;
1497 
1498           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1499           if (p == (const Quantum *) NULL)
1500             break;
1501           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1502             MagentaQuantum,pixels,exception);
1503           count=WriteBlob(image,length,pixels);
1504           if (count != (ssize_t) length)
1505             break;
1506         }
1507         if (image->previous == (Image *) NULL)
1508           {
1509             status=SetImageProgress(image,SaveImageTag,2,6);
1510             if (status == MagickFalse)
1511               break;
1512           }
1513         (void) CloseBlob(image);
1514         AppendImageFormat("Y",image->filename);
1515         status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1516           AppendBinaryBlobMode,exception);
1517         if (status == MagickFalse)
1518           return(status);
1519         for (y=0; y < (ssize_t) image->rows; y++)
1520         {
1521           const Quantum
1522             *magick_restrict p;
1523 
1524           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1525           if (p == (const Quantum *) NULL)
1526             break;
1527           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1528             YellowQuantum,pixels,exception);
1529           count=WriteBlob(image,length,pixels);
1530           if (count != (ssize_t) length)
1531             break;
1532         }
1533         if (image->previous == (Image *) NULL)
1534           {
1535             status=SetImageProgress(image,SaveImageTag,3,6);
1536             if (status == MagickFalse)
1537               break;
1538           }
1539         (void) CloseBlob(image);
1540         AppendImageFormat("K",image->filename);
1541         status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1542           AppendBinaryBlobMode,exception);
1543         if (status == MagickFalse)
1544           return(status);
1545         for (y=0; y < (ssize_t) image->rows; y++)
1546         {
1547           const Quantum
1548             *magick_restrict p;
1549 
1550           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1551           if (p == (const Quantum *) NULL)
1552             break;
1553           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1554             BlackQuantum,pixels,exception);
1555           count=WriteBlob(image,length,pixels);
1556           if (count != (ssize_t) length)
1557             break;
1558         }
1559         if (image->previous == (Image *) NULL)
1560           {
1561             status=SetImageProgress(image,SaveImageTag,4,6);
1562             if (status == MagickFalse)
1563               break;
1564           }
1565         if (quantum_type == CMYKAQuantum)
1566           {
1567             (void) CloseBlob(image);
1568             AppendImageFormat("A",image->filename);
1569             status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1570               AppendBinaryBlobMode,exception);
1571             if (status == MagickFalse)
1572               return(status);
1573             for (y=0; y < (ssize_t) image->rows; y++)
1574             {
1575               const Quantum
1576                 *magick_restrict p;
1577 
1578               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1579               if (p == (const Quantum *) NULL)
1580                 break;
1581               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1582                 AlphaQuantum,pixels,exception);
1583               count=WriteBlob(image,length,pixels);
1584               if (count != (ssize_t) length)
1585                 break;
1586             }
1587             if (image->previous == (Image *) NULL)
1588               {
1589                 status=SetImageProgress(image,SaveImageTag,5,6);
1590                 if (status == MagickFalse)
1591                   break;
1592               }
1593           }
1594         (void) CloseBlob(image);
1595         (void) CopyMagickString(image->filename,image_info->filename,
1596           MagickPathExtent);
1597         if (image->previous == (Image *) NULL)
1598           {
1599             status=SetImageProgress(image,SaveImageTag,6,6);
1600             if (status == MagickFalse)
1601               break;
1602           }
1603         break;
1604       }
1605     }
1606     quantum_info=DestroyQuantumInfo(quantum_info);
1607     if (GetNextImageInList(image) == (Image *) NULL)
1608       break;
1609     image=SyncNextImageInList(image);
1610     status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
1611     if (status == MagickFalse)
1612       break;
1613   } while (image_info->adjoin != MagickFalse);
1614   (void) CloseBlob(image);
1615   return(MagickTrue);
1616 }
1617