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