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