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