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