]> granicus.if.org Git - imagemagick/blob - coders/rgb.c
https://github.com/ImageMagick/ImageMagick/issues/463
[imagemagick] / coders / rgb.c
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-2017 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://www.imagemagick.org/script/license.php                           %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/blob-private.h"
45 #include "MagickCore/cache.h"
46 #include "MagickCore/channel.h"
47 #include "MagickCore/colorspace.h"
48 #include "MagickCore/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 \f
67 /*
68   Forward declarations.
69 */
70 static MagickBooleanType
71   WriteRGBImage(const ImageInfo *,Image *,ExceptionInfo *);
72 \f
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 */
100 static 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 \f
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 */
1010 ModuleExport 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 \f
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 */
1058 ModuleExport void UnregisterRGBImage(void)
1059 {
1060   (void) UnregisterMagickInfo("RGBO");
1061   (void) UnregisterMagickInfo("RGBA");
1062   (void) UnregisterMagickInfo("RGB");
1063 }
1064 \f
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 */
1093 static 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 }