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