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