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