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