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