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