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