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