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