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