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