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