Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                             GGGG  IIIII  FFFFF                              %
      7 %                            G        I    F                                  %
      8 %                            G  GG    I    FFF                                %
      9 %                            G   G    I    F                                  %
     10 %                             GGG   IIIII  F                                  %
     11 %                                                                             %
     12 %                                                                             %
     13 %            Read/Write Compuserv Graphics Interchange 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/attribute.h"
     45 #include "MagickCore/blob.h"
     46 #include "MagickCore/blob-private.h"
     47 #include "MagickCore/cache.h"
     48 #include "MagickCore/color.h"
     49 #include "MagickCore/color-private.h"
     50 #include "MagickCore/colormap.h"
     51 #include "MagickCore/colormap-private.h"
     52 #include "MagickCore/colorspace.h"
     53 #include "MagickCore/colorspace-private.h"
     54 #include "MagickCore/exception.h"
     55 #include "MagickCore/exception-private.h"
     56 #include "MagickCore/image.h"
     57 #include "MagickCore/image-private.h"
     58 #include "MagickCore/list.h"
     59 #include "MagickCore/profile.h"
     60 #include "MagickCore/magick.h"
     61 #include "MagickCore/memory_.h"
     62 #include "MagickCore/monitor.h"
     63 #include "MagickCore/monitor-private.h"
     64 #include "MagickCore/option.h"
     65 #include "MagickCore/pixel.h"
     66 #include "MagickCore/pixel-accessor.h"
     67 #include "MagickCore/property.h"
     68 #include "MagickCore/quantize.h"
     69 #include "MagickCore/quantum-private.h"
     70 #include "MagickCore/static.h"
     71 #include "MagickCore/string_.h"
     72 #include "MagickCore/string-private.h"
     73 #include "MagickCore/module.h"
     74 
     75 /*
     77   Define declarations.
     78 */
     79 #define MaximumLZWBits  12
     80 #define MaximumLZWCode  (1UL << MaximumLZWBits)
     81 
     82 /*
     84   Typdef declarations.
     85 */
     86 typedef struct _LZWCodeInfo
     87 {
     88   unsigned char
     89     buffer[280];
     90 
     91   size_t
     92     count,
     93     bit;
     94 
     95   MagickBooleanType
     96     eof;
     97 } LZWCodeInfo;
     98 
     99 typedef struct _LZWStack
    100 {
    101   size_t
    102     *codes,
    103     *index,
    104     *top;
    105 } LZWStack;
    106 
    107 typedef struct _LZWInfo
    108 {
    109   Image
    110     *image;
    111 
    112   LZWStack
    113     *stack;
    114 
    115   MagickBooleanType
    116     genesis;
    117 
    118   size_t
    119     data_size,
    120     maximum_data_value,
    121     clear_code,
    122     end_code,
    123     bits,
    124     first_code,
    125     last_code,
    126     maximum_code,
    127     slot,
    128     *table[2];
    129 
    130   LZWCodeInfo
    131     code_info;
    132 } LZWInfo;
    133 
    134 /*
    136   Forward declarations.
    137 */
    138 static inline int
    139   GetNextLZWCode(LZWInfo *,const size_t);
    140 
    141 static MagickBooleanType
    142   WriteGIFImage(const ImageInfo *,Image *,ExceptionInfo *);
    143 
    144 static ssize_t
    145   ReadBlobBlock(Image *,unsigned char *);
    146 
    147 /*
    149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    150 %                                                                             %
    151 %                                                                             %
    152 %                                                                             %
    153 %   D e c o d e I m a g e                                                     %
    154 %                                                                             %
    155 %                                                                             %
    156 %                                                                             %
    157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    158 %
    159 %  DecodeImage uncompresses an image via GIF-coding.
    160 %
    161 %  The format of the DecodeImage method is:
    162 %
    163 %      MagickBooleanType DecodeImage(Image *image,const ssize_t opacity)
    164 %
    165 %  A description of each parameter follows:
    166 %
    167 %    o image: the address of a structure of type Image.
    168 %
    169 %    o opacity:  The colormap index associated with the transparent color.
    170 %
    171 */
    172 
    173 static LZWInfo *RelinquishLZWInfo(LZWInfo *lzw_info)
    174 {
    175   if (lzw_info->table[0] != (size_t *) NULL)
    176     lzw_info->table[0]=(size_t *) RelinquishMagickMemory(
    177       lzw_info->table[0]);
    178   if (lzw_info->table[1] != (size_t *) NULL)
    179     lzw_info->table[1]=(size_t *) RelinquishMagickMemory(
    180       lzw_info->table[1]);
    181   if (lzw_info->stack != (LZWStack *) NULL)
    182     {
    183       if (lzw_info->stack->codes != (size_t *) NULL)
    184         lzw_info->stack->codes=(size_t *) RelinquishMagickMemory(
    185           lzw_info->stack->codes);
    186       lzw_info->stack=(LZWStack *) RelinquishMagickMemory(lzw_info->stack);
    187     }
    188   lzw_info=(LZWInfo *) RelinquishMagickMemory(lzw_info);
    189   return((LZWInfo *) NULL);
    190 }
    191 
    192 static inline void ResetLZWInfo(LZWInfo *lzw_info)
    193 {
    194   size_t
    195     one;
    196 
    197   lzw_info->bits=lzw_info->data_size+1;
    198   one=1;
    199   lzw_info->maximum_code=one << lzw_info->bits;
    200   lzw_info->slot=lzw_info->maximum_data_value+3;
    201   lzw_info->genesis=MagickTrue;
    202 }
    203 
    204 static LZWInfo *AcquireLZWInfo(Image *image,const size_t data_size)
    205 {
    206   LZWInfo
    207     *lzw_info;
    208 
    209   register ssize_t
    210     i;
    211 
    212   size_t
    213     one;
    214 
    215   lzw_info=(LZWInfo *) AcquireMagickMemory(sizeof(*lzw_info));
    216   if (lzw_info == (LZWInfo *) NULL)
    217     return((LZWInfo *) NULL);
    218   (void) ResetMagickMemory(lzw_info,0,sizeof(*lzw_info));
    219   lzw_info->image=image;
    220   lzw_info->data_size=data_size;
    221   one=1;
    222   lzw_info->maximum_data_value=(one << data_size)-1;
    223   lzw_info->clear_code=lzw_info->maximum_data_value+1;
    224   lzw_info->end_code=lzw_info->maximum_data_value+2;
    225   lzw_info->table[0]=(size_t *) AcquireQuantumMemory(MaximumLZWCode,
    226     sizeof(**lzw_info->table));
    227   lzw_info->table[1]=(size_t *) AcquireQuantumMemory(MaximumLZWCode,
    228     sizeof(**lzw_info->table));
    229   if ((lzw_info->table[0] == (size_t *) NULL) ||
    230       (lzw_info->table[1] == (size_t *) NULL))
    231     {
    232       lzw_info=RelinquishLZWInfo(lzw_info);
    233       return((LZWInfo *) NULL);
    234     }
    235   for (i=0; i <= (ssize_t) lzw_info->maximum_data_value; i++)
    236   {
    237     lzw_info->table[0][i]=0;
    238     lzw_info->table[1][i]=(size_t) i;
    239   }
    240   ResetLZWInfo(lzw_info);
    241   lzw_info->code_info.buffer[0]='\0';
    242   lzw_info->code_info.buffer[1]='\0';
    243   lzw_info->code_info.count=2;
    244   lzw_info->code_info.bit=8*lzw_info->code_info.count;
    245   lzw_info->code_info.eof=MagickFalse;
    246   lzw_info->genesis=MagickTrue;
    247   lzw_info->stack=(LZWStack *) AcquireMagickMemory(sizeof(*lzw_info->stack));
    248   if (lzw_info->stack == (LZWStack *) NULL)
    249     {
    250       lzw_info=RelinquishLZWInfo(lzw_info);
    251       return((LZWInfo *) NULL);
    252     }
    253   lzw_info->stack->codes=(size_t *) AcquireQuantumMemory(2UL*
    254     MaximumLZWCode,sizeof(*lzw_info->stack->codes));
    255   if (lzw_info->stack->codes == (size_t *) NULL)
    256     {
    257       lzw_info=RelinquishLZWInfo(lzw_info);
    258       return((LZWInfo *) NULL);
    259     }
    260   lzw_info->stack->index=lzw_info->stack->codes;
    261   lzw_info->stack->top=lzw_info->stack->codes+2*MaximumLZWCode;
    262   return(lzw_info);
    263 }
    264 
    265 static inline int GetNextLZWCode(LZWInfo *lzw_info,const size_t bits)
    266 {
    267   int
    268     code;
    269 
    270   register ssize_t
    271     i;
    272 
    273   size_t
    274     one;
    275 
    276   while (((lzw_info->code_info.bit+bits) > (8*lzw_info->code_info.count)) &&
    277          (lzw_info->code_info.eof == MagickFalse))
    278   {
    279     ssize_t
    280       count;
    281 
    282     lzw_info->code_info.buffer[0]=lzw_info->code_info.buffer[
    283       lzw_info->code_info.count-2];
    284     lzw_info->code_info.buffer[1]=lzw_info->code_info.buffer[
    285       lzw_info->code_info.count-1];
    286     lzw_info->code_info.bit-=8*(lzw_info->code_info.count-2);
    287     lzw_info->code_info.count=2;
    288     count=ReadBlobBlock(lzw_info->image,&lzw_info->code_info.buffer[
    289       lzw_info->code_info.count]);
    290     if (count > 0)
    291       lzw_info->code_info.count+=count;
    292     else
    293       lzw_info->code_info.eof=MagickTrue;
    294   }
    295   if ((lzw_info->code_info.bit+bits) > (8*lzw_info->code_info.count))
    296     return(-1);
    297   code=0;
    298   one=1;
    299   for (i=0; i < (ssize_t) bits; i++)
    300   {
    301     code|=((lzw_info->code_info.buffer[lzw_info->code_info.bit/8] &
    302       (one << (lzw_info->code_info.bit % 8))) != 0) << i;
    303     lzw_info->code_info.bit++;
    304   }
    305   return(code);
    306 }
    307 
    308 static inline int PopLZWStack(LZWStack *stack_info)
    309 {
    310   if (stack_info->index <= stack_info->codes)
    311     return(-1);
    312   stack_info->index--;
    313   return((int) *stack_info->index);
    314 }
    315 
    316 static inline void PushLZWStack(LZWStack *stack_info,const size_t value)
    317 {
    318   if (stack_info->index >= stack_info->top)
    319     return;
    320   *stack_info->index=value;
    321   stack_info->index++;
    322 }
    323 
    324 static int ReadBlobLZWByte(LZWInfo *lzw_info)
    325 {
    326   int
    327     code;
    328 
    329   size_t
    330     one,
    331     value;
    332 
    333   ssize_t
    334     count;
    335 
    336   if (lzw_info->stack->index != lzw_info->stack->codes)
    337     return(PopLZWStack(lzw_info->stack));
    338   if (lzw_info->genesis != MagickFalse)
    339     {
    340       lzw_info->genesis=MagickFalse;
    341       do
    342       {
    343         lzw_info->first_code=(size_t) GetNextLZWCode(lzw_info,lzw_info->bits);
    344         lzw_info->last_code=lzw_info->first_code;
    345       } while (lzw_info->first_code == lzw_info->clear_code);
    346       return((int) lzw_info->first_code);
    347     }
    348   code=GetNextLZWCode(lzw_info,lzw_info->bits);
    349   if (code < 0)
    350     return(code);
    351   if ((size_t) code == lzw_info->clear_code)
    352     {
    353       ResetLZWInfo(lzw_info);
    354       return(ReadBlobLZWByte(lzw_info));
    355     }
    356   if ((size_t) code == lzw_info->end_code)
    357     return(-1);
    358   if ((size_t) code < lzw_info->slot)
    359     value=(size_t) code;
    360   else
    361     {
    362       PushLZWStack(lzw_info->stack,lzw_info->first_code);
    363       value=lzw_info->last_code;
    364     }
    365   count=0;
    366   while (value > lzw_info->maximum_data_value)
    367   {
    368     if ((size_t) count > MaximumLZWCode)
    369       return(-1);
    370     count++;
    371     if ((size_t) value > MaximumLZWCode)
    372       return(-1);
    373     PushLZWStack(lzw_info->stack,lzw_info->table[1][value]);
    374     value=lzw_info->table[0][value];
    375   }
    376   lzw_info->first_code=lzw_info->table[1][value];
    377   PushLZWStack(lzw_info->stack,lzw_info->first_code);
    378   one=1;
    379   if (lzw_info->slot < MaximumLZWCode)
    380     {
    381       lzw_info->table[0][lzw_info->slot]=lzw_info->last_code;
    382       lzw_info->table[1][lzw_info->slot]=lzw_info->first_code;
    383       lzw_info->slot++;
    384       if ((lzw_info->slot >= lzw_info->maximum_code) &&
    385           (lzw_info->bits < MaximumLZWBits))
    386         {
    387           lzw_info->bits++;
    388           lzw_info->maximum_code=one << lzw_info->bits;
    389         }
    390     }
    391   lzw_info->last_code=(size_t) code;
    392   return(PopLZWStack(lzw_info->stack));
    393 }
    394 
    395 static MagickBooleanType DecodeImage(Image *image,const ssize_t opacity,
    396   ExceptionInfo *exception)
    397 {
    398   int
    399     c;
    400 
    401   LZWInfo
    402     *lzw_info;
    403 
    404   size_t
    405     pass;
    406 
    407   ssize_t
    408     index,
    409     offset,
    410     y;
    411 
    412   unsigned char
    413     data_size;
    414 
    415   /*
    416     Allocate decoder tables.
    417   */
    418   assert(image != (Image *) NULL);
    419   assert(image->signature == MagickCoreSignature);
    420   if (image->debug != MagickFalse)
    421     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    422   data_size=(unsigned char) ReadBlobByte(image);
    423   if (data_size > MaximumLZWBits)
    424     ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
    425   lzw_info=AcquireLZWInfo(image,data_size);
    426   if (lzw_info == (LZWInfo *) NULL)
    427     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
    428       image->filename);
    429   pass=0;
    430   offset=0;
    431   for (y=0; y < (ssize_t) image->rows; y++)
    432   {
    433     register ssize_t
    434       x;
    435 
    436     register Quantum
    437       *magick_restrict q;
    438 
    439     q=QueueAuthenticPixels(image,0,offset,image->columns,1,exception);
    440     if (q == (Quantum *) NULL)
    441       break;
    442     for (x=0; x < (ssize_t) image->columns; )
    443     {
    444       c=ReadBlobLZWByte(lzw_info);
    445       if (c < 0)
    446         break;
    447       index=ConstrainColormapIndex(image,(ssize_t) c,exception);
    448       SetPixelIndex(image,(Quantum) index,q);
    449       SetPixelViaPixelInfo(image,image->colormap+index,q);
    450       SetPixelAlpha(image,index == opacity ? TransparentAlpha : OpaqueAlpha,q);
    451       x++;
    452       q+=GetPixelChannels(image);
    453     }
    454     if (SyncAuthenticPixels(image,exception) == MagickFalse)
    455       break;
    456     if (x < (ssize_t) image->columns)
    457       break;
    458     if (image->interlace == NoInterlace)
    459       offset++;
    460     else
    461       {
    462         switch (pass)
    463         {
    464           case 0:
    465           default:
    466           {
    467             offset+=8;
    468             break;
    469           }
    470           case 1:
    471           {
    472             offset+=8;
    473             break;
    474           }
    475           case 2:
    476           {
    477             offset+=4;
    478             break;
    479           }
    480           case 3:
    481           {
    482             offset+=2;
    483             break;
    484           }
    485         }
    486       if ((pass == 0) && (offset >= (ssize_t) image->rows))
    487         {
    488           pass++;
    489           offset=4;
    490         }
    491       if ((pass == 1) && (offset >= (ssize_t) image->rows))
    492         {
    493           pass++;
    494           offset=2;
    495         }
    496       if ((pass == 2) && (offset >= (ssize_t) image->rows))
    497         {
    498           pass++;
    499           offset=1;
    500         }
    501     }
    502   }
    503   lzw_info=RelinquishLZWInfo(lzw_info);
    504   if (y < (ssize_t) image->rows)
    505     ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
    506   return(MagickTrue);
    507 }
    508 
    509 /*
    511 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    512 %                                                                             %
    513 %                                                                             %
    514 %                                                                             %
    515 %   E n c o d e I m a g e                                                     %
    516 %                                                                             %
    517 %                                                                             %
    518 %                                                                             %
    519 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    520 %
    521 %  EncodeImage compresses an image via GIF-coding.
    522 %
    523 %  The format of the EncodeImage method is:
    524 %
    525 %      MagickBooleanType EncodeImage(const ImageInfo *image_info,Image *image,
    526 %        const size_t data_size)
    527 %
    528 %  A description of each parameter follows:
    529 %
    530 %    o image_info: the image info.
    531 %
    532 %    o image: the address of a structure of type Image.
    533 %
    534 %    o data_size:  The number of bits in the compressed packet.
    535 %
    536 */
    537 static MagickBooleanType EncodeImage(const ImageInfo *image_info,Image *image,
    538   const size_t data_size,ExceptionInfo *exception)
    539 {
    540 #define MaxCode(number_bits)  ((one << (number_bits))-1)
    541 #define MaxHashTable  5003
    542 #define MaxGIFBits  12UL
    543 #define MaxGIFTable  (1UL << MaxGIFBits)
    544 #define GIFOutputCode(code) \
    545 { \
    546   /*  \
    547     Emit a code. \
    548   */ \
    549   if (bits > 0) \
    550     datum|=(code) << bits; \
    551   else \
    552     datum=code; \
    553   bits+=number_bits; \
    554   while (bits >= 8) \
    555   { \
    556     /*  \
    557       Add a character to current packet. \
    558     */ \
    559     packet[length++]=(unsigned char) (datum & 0xff); \
    560     if (length >= 254) \
    561       { \
    562         (void) WriteBlobByte(image,(unsigned char) length); \
    563         (void) WriteBlob(image,length,packet); \
    564         length=0; \
    565       } \
    566     datum>>=8; \
    567     bits-=8; \
    568   } \
    569   if (free_code > max_code)  \
    570     { \
    571       number_bits++; \
    572       if (number_bits == MaxGIFBits) \
    573         max_code=MaxGIFTable; \
    574       else \
    575         max_code=MaxCode(number_bits); \
    576     } \
    577 }
    578 
    579   Quantum
    580     index;
    581 
    582   short
    583     *hash_code,
    584     *hash_prefix,
    585     waiting_code;
    586 
    587   size_t
    588     bits,
    589     clear_code,
    590     datum,
    591     end_of_information_code,
    592     free_code,
    593     length,
    594     max_code,
    595     next_pixel,
    596     number_bits,
    597     one,
    598     pass;
    599 
    600   ssize_t
    601     displacement,
    602     offset,
    603     k,
    604     y;
    605 
    606   unsigned char
    607     *packet,
    608     *hash_suffix;
    609 
    610   /*
    611     Allocate encoder tables.
    612   */
    613   assert(image != (Image *) NULL);
    614   one=1;
    615   packet=(unsigned char *) AcquireQuantumMemory(256,sizeof(*packet));
    616   hash_code=(short *) AcquireQuantumMemory(MaxHashTable,sizeof(*hash_code));
    617   hash_prefix=(short *) AcquireQuantumMemory(MaxHashTable,sizeof(*hash_prefix));
    618   hash_suffix=(unsigned char *) AcquireQuantumMemory(MaxHashTable,
    619     sizeof(*hash_suffix));
    620   if ((packet == (unsigned char *) NULL) || (hash_code == (short *) NULL) ||
    621       (hash_prefix == (short *) NULL) ||
    622       (hash_suffix == (unsigned char *) NULL))
    623     {
    624       if (packet != (unsigned char *) NULL)
    625         packet=(unsigned char *) RelinquishMagickMemory(packet);
    626       if (hash_code != (short *) NULL)
    627         hash_code=(short *) RelinquishMagickMemory(hash_code);
    628       if (hash_prefix != (short *) NULL)
    629         hash_prefix=(short *) RelinquishMagickMemory(hash_prefix);
    630       if (hash_suffix != (unsigned char *) NULL)
    631         hash_suffix=(unsigned char *) RelinquishMagickMemory(hash_suffix);
    632       return(MagickFalse);
    633     }
    634   /*
    635     Initialize GIF encoder.
    636   */
    637   (void) ResetMagickMemory(hash_code,0,MaxHashTable*sizeof(*hash_code));
    638   (void) ResetMagickMemory(hash_prefix,0,MaxHashTable*sizeof(*hash_prefix));
    639   (void) ResetMagickMemory(hash_suffix,0,MaxHashTable*sizeof(*hash_suffix));
    640   number_bits=data_size;
    641   max_code=MaxCode(number_bits);
    642   clear_code=((short) one << (data_size-1));
    643   end_of_information_code=clear_code+1;
    644   free_code=clear_code+2;
    645   length=0;
    646   datum=0;
    647   bits=0;
    648   GIFOutputCode(clear_code);
    649   /*
    650     Encode pixels.
    651   */
    652   offset=0;
    653   pass=0;
    654   waiting_code=0;
    655   for (y=0; y < (ssize_t) image->rows; y++)
    656   {
    657     register const Quantum
    658       *magick_restrict p;
    659 
    660     register ssize_t
    661       x;
    662 
    663     p=GetVirtualPixels(image,0,offset,image->columns,1,exception);
    664     if (p == (const Quantum *) NULL)
    665       break;
    666     if (y == 0)
    667       {
    668         waiting_code=(short) GetPixelIndex(image,p);
    669         p+=GetPixelChannels(image);
    670       }
    671     for (x=(ssize_t) (y == 0 ? 1 : 0); x < (ssize_t) image->columns; x++)
    672     {
    673       /*
    674         Probe hash table.
    675       */
    676       index=(Quantum) ((size_t) GetPixelIndex(image,p) & 0xff);
    677       p+=GetPixelChannels(image);
    678       k=(ssize_t) (((size_t) index << (MaxGIFBits-8))+waiting_code);
    679       if (k >= MaxHashTable)
    680         k-=MaxHashTable;
    681       next_pixel=MagickFalse;
    682       displacement=1;
    683       if (hash_code[k] > 0)
    684         {
    685           if ((hash_prefix[k] == waiting_code) &&
    686               (hash_suffix[k] == (unsigned char) index))
    687             {
    688               waiting_code=hash_code[k];
    689               continue;
    690             }
    691           if (k != 0)
    692             displacement=MaxHashTable-k;
    693           for ( ; ; )
    694           {
    695             k-=displacement;
    696             if (k < 0)
    697               k+=MaxHashTable;
    698             if (hash_code[k] == 0)
    699               break;
    700             if ((hash_prefix[k] == waiting_code) &&
    701                 (hash_suffix[k] == (unsigned char) index))
    702               {
    703                 waiting_code=hash_code[k];
    704                 next_pixel=MagickTrue;
    705                 break;
    706               }
    707           }
    708           if (next_pixel != MagickFalse)
    709             continue;
    710         }
    711       GIFOutputCode((size_t) waiting_code);
    712       if (free_code < MaxGIFTable)
    713         {
    714           hash_code[k]=(short) free_code++;
    715           hash_prefix[k]=waiting_code;
    716           hash_suffix[k]=(unsigned char) index;
    717         }
    718       else
    719         {
    720           /*
    721             Fill the hash table with empty entries.
    722           */
    723           for (k=0; k < MaxHashTable; k++)
    724             hash_code[k]=0;
    725           /*
    726             Reset compressor and issue a clear code.
    727           */
    728           free_code=clear_code+2;
    729           GIFOutputCode(clear_code);
    730           number_bits=data_size;
    731           max_code=MaxCode(number_bits);
    732         }
    733       waiting_code=(short) index;
    734     }
    735     if (image_info->interlace == NoInterlace)
    736       offset++;
    737     else
    738       switch (pass)
    739       {
    740         case 0:
    741         default:
    742         {
    743           offset+=8;
    744           if (offset >= (ssize_t) image->rows)
    745             {
    746               pass++;
    747               offset=4;
    748             }
    749           break;
    750         }
    751         case 1:
    752         {
    753           offset+=8;
    754           if (offset >= (ssize_t) image->rows)
    755             {
    756               pass++;
    757               offset=2;
    758             }
    759           break;
    760         }
    761         case 2:
    762         {
    763           offset+=4;
    764           if (offset >= (ssize_t) image->rows)
    765             {
    766               pass++;
    767               offset=1;
    768             }
    769           break;
    770         }
    771         case 3:
    772         {
    773           offset+=2;
    774           break;
    775         }
    776       }
    777   }
    778   /*
    779     Flush out the buffered code.
    780   */
    781   GIFOutputCode((size_t) waiting_code);
    782   GIFOutputCode(end_of_information_code);
    783   if (bits > 0)
    784     {
    785       /*
    786         Add a character to current packet.
    787       */
    788       packet[length++]=(unsigned char) (datum & 0xff);
    789       if (length >= 254)
    790         {
    791           (void) WriteBlobByte(image,(unsigned char) length);
    792           (void) WriteBlob(image,length,packet);
    793           length=0;
    794         }
    795     }
    796   /*
    797     Flush accumulated data.
    798   */
    799   if (length > 0)
    800     {
    801       (void) WriteBlobByte(image,(unsigned char) length);
    802       (void) WriteBlob(image,length,packet);
    803     }
    804   /*
    805     Free encoder memory.
    806   */
    807   hash_suffix=(unsigned char *) RelinquishMagickMemory(hash_suffix);
    808   hash_prefix=(short *) RelinquishMagickMemory(hash_prefix);
    809   hash_code=(short *) RelinquishMagickMemory(hash_code);
    810   packet=(unsigned char *) RelinquishMagickMemory(packet);
    811   return(MagickTrue);
    812 }
    813 
    814 /*
    816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    817 %                                                                             %
    818 %                                                                             %
    819 %                                                                             %
    820 %   I s G I F                                                                 %
    821 %                                                                             %
    822 %                                                                             %
    823 %                                                                             %
    824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    825 %
    826 %  IsGIF() returns MagickTrue if the image format type, identified by the
    827 %  magick string, is GIF.
    828 %
    829 %  The format of the IsGIF method is:
    830 %
    831 %      MagickBooleanType IsGIF(const unsigned char *magick,const size_t length)
    832 %
    833 %  A description of each parameter follows:
    834 %
    835 %    o magick: compare image format pattern against these bytes.
    836 %
    837 %    o length: Specifies the length of the magick string.
    838 %
    839 */
    840 static MagickBooleanType IsGIF(const unsigned char *magick,const size_t length)
    841 {
    842   if (length < 4)
    843     return(MagickFalse);
    844   if (LocaleNCompare((char *) magick,"GIF8",4) == 0)
    845     return(MagickTrue);
    846   return(MagickFalse);
    847 }
    848 
    849 /*
    851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    852 %                                                                             %
    853 %                                                                             %
    854 %                                                                             %
    855 +  R e a d B l o b B l o c k                                                  %
    856 %                                                                             %
    857 %                                                                             %
    858 %                                                                             %
    859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    860 %
    861 %  ReadBlobBlock() reads data from the image file and returns it.  The
    862 %  amount of data is determined by first reading a count byte.  The number
    863 %  of bytes read is returned.
    864 %
    865 %  The format of the ReadBlobBlock method is:
    866 %
    867 %      ssize_t ReadBlobBlock(Image *image,unsigned char *data)
    868 %
    869 %  A description of each parameter follows:
    870 %
    871 %    o image: the image.
    872 %
    873 %    o data:  Specifies an area to place the information requested from
    874 %      the file.
    875 %
    876 */
    877 static ssize_t ReadBlobBlock(Image *image,unsigned char *data)
    878 {
    879   ssize_t
    880     count;
    881 
    882   unsigned char
    883     block_count;
    884 
    885   assert(image != (Image *) NULL);
    886   assert(image->signature == MagickCoreSignature);
    887   assert(data != (unsigned char *) NULL);
    888   count=ReadBlob(image,1,&block_count);
    889   if (count != 1)
    890     return(0);
    891   count=ReadBlob(image,(size_t) block_count,data);
    892   if (count != (ssize_t) block_count)
    893     return(0);
    894   return(count);
    895 }
    896 
    897 /*
    899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    900 %                                                                             %
    901 %                                                                             %
    902 %                                                                             %
    903 %   R e a d G I F I m a g e                                                   %
    904 %                                                                             %
    905 %                                                                             %
    906 %                                                                             %
    907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    908 %
    909 %  ReadGIFImage() reads a Compuserve Graphics image file and returns it.
    910 %  It allocates the memory necessary for the new Image structure and returns a
    911 %  pointer to the new image.
    912 %
    913 %  The format of the ReadGIFImage method is:
    914 %
    915 %      Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
    916 %
    917 %  A description of each parameter follows:
    918 %
    919 %    o image_info: the image info.
    920 %
    921 %    o exception: return any errors or warnings in this structure.
    922 %
    923 */
    924 static MagickBooleanType PingGIFImage(Image *image,ExceptionInfo *exception)
    925 {
    926   unsigned char
    927     buffer[256],
    928     length,
    929     data_size;
    930 
    931   assert(image != (Image *) NULL);
    932   assert(image->signature == MagickCoreSignature);
    933   if (image->debug != MagickFalse)
    934     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
    935   if (ReadBlob(image,1,&data_size) != 1)
    936     ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
    937   if (data_size > MaximumLZWBits)
    938     ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
    939   if (ReadBlob(image,1,&length) != 1)
    940     ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
    941   while (length != 0)
    942   {
    943     if (ReadBlob(image,length,buffer) != (ssize_t) length)
    944       ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
    945     if (ReadBlob(image,1,&length) != 1)
    946       ThrowBinaryException(CorruptImageError,"CorruptImage",image->filename);
    947   }
    948   return(MagickTrue);
    949 }
    950 
    951 static Image *ReadGIFImage(const ImageInfo *image_info,ExceptionInfo *exception)
    952 {
    953 #define BitSet(byte,bit)  (((byte) & (bit)) == (bit))
    954 #define LSBFirstOrder(x,y)  (((y) << 8) | (x))
    955 
    956   Image
    957     *image,
    958     *meta_image;
    959 
    960   int
    961     number_extensionss=0;
    962 
    963   MagickBooleanType
    964     status;
    965 
    966   RectangleInfo
    967     page;
    968 
    969   register ssize_t
    970     i;
    971 
    972   register unsigned char
    973     *p;
    974 
    975   size_t
    976     delay,
    977     dispose,
    978     duration,
    979     global_colors,
    980     image_count,
    981     iterations,
    982     one;
    983 
    984   ssize_t
    985     count,
    986     opacity;
    987 
    988   unsigned char
    989     background,
    990     c,
    991     flag,
    992     *global_colormap,
    993     buffer[257];
    994 
    995   /*
    996     Open image file.
    997   */
    998   assert(image_info != (const ImageInfo *) NULL);
    999   assert(image_info->signature == MagickCoreSignature);
   1000   if (image_info->debug != MagickFalse)
   1001     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   1002       image_info->filename);
   1003   assert(exception != (ExceptionInfo *) NULL);
   1004   assert(exception->signature == MagickCoreSignature);
   1005   image=AcquireImage(image_info,exception);
   1006   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   1007   if (status == MagickFalse)
   1008     {
   1009       image=DestroyImageList(image);
   1010       return((Image *) NULL);
   1011     }
   1012   /*
   1013     Determine if this a GIF file.
   1014   */
   1015   count=ReadBlob(image,6,buffer);
   1016   if ((count != 6) || ((LocaleNCompare((char *) buffer,"GIF87",5) != 0) &&
   1017       (LocaleNCompare((char *) buffer,"GIF89",5) != 0)))
   1018     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   1019   page.width=ReadBlobLSBShort(image);
   1020   page.height=ReadBlobLSBShort(image);
   1021   flag=(unsigned char) ReadBlobByte(image);
   1022   background=(unsigned char) ReadBlobByte(image);
   1023   c=(unsigned char) ReadBlobByte(image);  /* reserved */
   1024   one=1;
   1025   global_colors=one << (((size_t) flag & 0x07)+1);
   1026   global_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
   1027     MagickMax(global_colors,256),3UL*sizeof(*global_colormap));
   1028   if (global_colormap == (unsigned char *) NULL)
   1029     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1030   if (BitSet((int) flag,0x80) != 0)
   1031     {
   1032       count=ReadBlob(image,(size_t) (3*global_colors),global_colormap);
   1033       if (count != (ssize_t) (3*global_colors))
   1034         {
   1035           global_colormap=(unsigned char *) RelinquishMagickMemory(
   1036             global_colormap);
   1037           ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
   1038         }
   1039     }
   1040   delay=0;
   1041   dispose=0;
   1042   duration=0;
   1043   iterations=1;
   1044   opacity=(-1);
   1045   image_count=0;
   1046   meta_image=AcquireImage(image_info,exception);  /* metadata container */
   1047   for ( ; ; )
   1048   {
   1049     count=ReadBlob(image,1,&c);
   1050     if (count != 1)
   1051       break;
   1052     if (c == (unsigned char) ';')
   1053       break;  /* terminator */
   1054     if (c == (unsigned char) '!')
   1055       {
   1056         /*
   1057           GIF Extension block.
   1058         */
   1059         count=ReadBlob(image,1,&c);
   1060         if (count != 1)
   1061           {
   1062             global_colormap=(unsigned char *) RelinquishMagickMemory(
   1063               global_colormap);
   1064             ThrowReaderException(CorruptImageError,
   1065               "UnableToReadExtensionBlock");
   1066           }
   1067         switch (c)
   1068         {
   1069           case 0xf9:
   1070           {
   1071             /*
   1072               Read graphics control extension.
   1073             */
   1074             while (ReadBlobBlock(image,buffer) != 0) ;
   1075             dispose=(size_t) (buffer[0] >> 2);
   1076             delay=(size_t) ((buffer[2] << 8) | buffer[1]);
   1077             if ((ssize_t) (buffer[0] & 0x01) == 0x01)
   1078               opacity=(ssize_t) buffer[3];
   1079             break;
   1080           }
   1081           case 0xfe:
   1082           {
   1083             char
   1084               *comments;
   1085 
   1086             size_t
   1087               length;
   1088 
   1089             /*
   1090               Read comment extension.
   1091             */
   1092             comments=AcquireString((char *) NULL);
   1093             for (length=0; ; length+=count)
   1094             {
   1095               count=(ssize_t) ReadBlobBlock(image,buffer);
   1096               if (count == 0)
   1097                 break;
   1098               buffer[count]='\0';
   1099               (void) ConcatenateString(&comments,(const char *) buffer);
   1100             }
   1101             (void) SetImageProperty(meta_image,"comment",comments,exception);
   1102             comments=DestroyString(comments);
   1103             break;
   1104           }
   1105           case 0xff:
   1106           {
   1107             MagickBooleanType
   1108               loop;
   1109 
   1110             /*
   1111               Read Netscape Loop extension.
   1112             */
   1113             loop=MagickFalse;
   1114             if (ReadBlobBlock(image,buffer) != 0)
   1115               loop=LocaleNCompare((char *) buffer,"NETSCAPE2.0",11) == 0 ?
   1116                 MagickTrue : MagickFalse;
   1117             if (loop != MagickFalse)
   1118               {
   1119                 while (ReadBlobBlock(image,buffer) != 0)
   1120                   iterations=(size_t) ((buffer[2] << 8) | buffer[1]);
   1121                 break;
   1122               }
   1123             else
   1124               {
   1125                 char
   1126                   name[MagickPathExtent];
   1127 
   1128                 int
   1129                   block_length,
   1130                   info_length,
   1131                   reserved_length;
   1132 
   1133                 MagickBooleanType
   1134                   i8bim,
   1135                   icc,
   1136                   iptc,
   1137                   magick;
   1138 
   1139                 StringInfo
   1140                   *profile;
   1141 
   1142                 unsigned char
   1143                   *info;
   1144 
   1145                 /*
   1146                   Store GIF application extension as a generic profile.
   1147                 */
   1148                 icc=LocaleNCompare((char *) buffer,"ICCRGBG1012",11) == 0 ?
   1149                   MagickTrue : MagickFalse;
   1150                 magick=LocaleNCompare((char *) buffer,"ImageMagick",11) == 0 ?
   1151                   MagickTrue : MagickFalse;
   1152                 i8bim=LocaleNCompare((char *) buffer,"MGK8BIM0000",11) == 0 ?
   1153                   MagickTrue : MagickFalse;
   1154                 iptc=LocaleNCompare((char *) buffer,"MGKIPTC0000",11) == 0 ?
   1155                   MagickTrue : MagickFalse;
   1156                 number_extensionss++;
   1157                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1158                   "    Reading GIF application extension");
   1159                 info=(unsigned char *) AcquireQuantumMemory(255UL,
   1160                   sizeof(*info));
   1161                 if (info == (unsigned char *) NULL)
   1162                   ThrowReaderException(ResourceLimitError,
   1163                     "MemoryAllocationFailed");
   1164                 reserved_length=255;
   1165                 for (info_length=0; ; )
   1166                 {
   1167                   block_length=(int) ReadBlobBlock(image,&info[info_length]);
   1168                   if (block_length == 0)
   1169                     break;
   1170                   info_length+=block_length;
   1171                   if (info_length > (reserved_length-255))
   1172                     {
   1173                       reserved_length+=4096;
   1174                       info=(unsigned char *) ResizeQuantumMemory(info,(size_t)
   1175                         reserved_length,sizeof(*info));
   1176                       if (info == (unsigned char *) NULL)
   1177                         ThrowReaderException(ResourceLimitError,
   1178                           "MemoryAllocationFailed");
   1179                     }
   1180                 }
   1181                 profile=BlobToStringInfo(info,(size_t) info_length);
   1182                 if (profile == (StringInfo *) NULL)
   1183                   ThrowReaderException(ResourceLimitError,
   1184                     "MemoryAllocationFailed");
   1185                 if (i8bim != MagickFalse)
   1186                   (void) CopyMagickString(name,"8bim",sizeof(name));
   1187                 else if (icc != MagickFalse)
   1188                   (void) CopyMagickString(name,"icc",sizeof(name));
   1189                 else if (iptc != MagickFalse)
   1190                   (void) CopyMagickString(name,"iptc",sizeof(name));
   1191                 else if (magick != MagickFalse)
   1192                   {
   1193                     (void) CopyMagickString(name,"magick",sizeof(name));
   1194                     meta_image->gamma=StringToDouble((char *) info+6,
   1195                       (char **) NULL);
   1196                   }
   1197                 else
   1198                   (void) FormatLocaleString(name,sizeof(name),"gif:%.11s",
   1199                     buffer);
   1200                 info=(unsigned char *) RelinquishMagickMemory(info);
   1201                 if (magick == MagickFalse)
   1202                   (void) SetImageProfile(meta_image,name,profile,exception);
   1203                 profile=DestroyStringInfo(profile);
   1204                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1205                   "      profile name=%s",name);
   1206               }
   1207             break;
   1208           }
   1209           default:
   1210           {
   1211             while (ReadBlobBlock(image,buffer) != 0) ;
   1212             break;
   1213           }
   1214         }
   1215       }
   1216     if (c != (unsigned char) ',')
   1217       continue;
   1218     if (image_count != 0)
   1219       {
   1220         /*
   1221           Allocate next image structure.
   1222         */
   1223         AcquireNextImage(image_info,image,exception);
   1224         if (GetNextImageInList(image) == (Image *) NULL)
   1225           {
   1226             image=DestroyImageList(image);
   1227             global_colormap=(unsigned char *) RelinquishMagickMemory(
   1228               global_colormap);
   1229             return((Image *) NULL);
   1230           }
   1231         image=SyncNextImageInList(image);
   1232       }
   1233     image_count++;
   1234     /*
   1235       Read image attributes.
   1236     */
   1237     meta_image->scene=image->scene;
   1238     (void) CloneImageProperties(image,meta_image);
   1239     DestroyImageProperties(meta_image);
   1240     (void) CloneImageProfiles(image,meta_image);
   1241     DestroyImageProfiles(meta_image);
   1242     image->storage_class=PseudoClass;
   1243     image->compression=LZWCompression;
   1244     page.x=(ssize_t) ReadBlobLSBShort(image);
   1245     page.y=(ssize_t) ReadBlobLSBShort(image);
   1246     image->columns=ReadBlobLSBShort(image);
   1247     image->rows=ReadBlobLSBShort(image);
   1248     image->depth=8;
   1249     flag=(unsigned char) ReadBlobByte(image);
   1250     image->interlace=BitSet((int) flag,0x40) != 0 ? GIFInterlace : NoInterlace;
   1251     image->colors=BitSet((int) flag,0x80) == 0 ? global_colors : one <<
   1252       ((size_t) (flag & 0x07)+1);
   1253     if (opacity >= (ssize_t) image->colors)
   1254       opacity=(-1);
   1255     image->page.width=page.width;
   1256     image->page.height=page.height;
   1257     image->page.y=page.y;
   1258     image->page.x=page.x;
   1259     image->delay=delay;
   1260     image->ticks_per_second=100;
   1261     image->dispose=(DisposeType) dispose;
   1262     image->iterations=iterations;
   1263     image->alpha_trait=opacity >= 0 ? BlendPixelTrait : UndefinedPixelTrait;
   1264     delay=0;
   1265     dispose=0;
   1266     if ((image->columns == 0) || (image->rows == 0))
   1267       {
   1268         global_colormap=(unsigned char *) RelinquishMagickMemory(
   1269           global_colormap);
   1270         ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
   1271       }
   1272     /*
   1273       Inititialize colormap.
   1274     */
   1275     if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
   1276       {
   1277         global_colormap=(unsigned char *) RelinquishMagickMemory(global_colormap);
   1278         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1279       }
   1280     if (BitSet((int) flag,0x80) == 0)
   1281       {
   1282         /*
   1283           Use global colormap.
   1284         */
   1285         p=global_colormap;
   1286         for (i=0; i < (ssize_t) image->colors; i++)
   1287         {
   1288           image->colormap[i].red=(double) ScaleCharToQuantum(*p++);
   1289           image->colormap[i].green=(double) ScaleCharToQuantum(*p++);
   1290           image->colormap[i].blue=(double) ScaleCharToQuantum(*p++);
   1291           if (i == opacity)
   1292             {
   1293               image->colormap[i].alpha=(double) TransparentAlpha;
   1294               image->transparent_color=image->colormap[opacity];
   1295             }
   1296         }
   1297         image->background_color=image->colormap[MagickMin((ssize_t) background,
   1298           (ssize_t) image->colors-1)];
   1299       }
   1300     else
   1301       {
   1302         unsigned char
   1303           *colormap;
   1304 
   1305         /*
   1306           Read local colormap.
   1307         */
   1308         colormap=(unsigned char *) AcquireQuantumMemory(image->colors,3*
   1309           sizeof(*colormap));
   1310         if (colormap == (unsigned char *) NULL)
   1311           {
   1312             global_colormap=(unsigned char *) RelinquishMagickMemory(
   1313               global_colormap);
   1314             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1315           }
   1316         count=ReadBlob(image,(3*image->colors)*sizeof(*colormap),colormap);
   1317         if (count != (ssize_t) (3*image->colors))
   1318           {
   1319             global_colormap=(unsigned char *) RelinquishMagickMemory(
   1320               global_colormap);
   1321             colormap=(unsigned char *) RelinquishMagickMemory(colormap);
   1322             ThrowReaderException(CorruptImageError,
   1323               "InsufficientImageDataInFile");
   1324           }
   1325         p=colormap;
   1326         for (i=0; i < (ssize_t) image->colors; i++)
   1327         {
   1328           image->colormap[i].red=(double) ScaleCharToQuantum(*p++);
   1329           image->colormap[i].green=(double) ScaleCharToQuantum(*p++);
   1330           image->colormap[i].blue=(double) ScaleCharToQuantum(*p++);
   1331           if (i == opacity)
   1332             image->colormap[i].alpha=(double) TransparentAlpha;
   1333         }
   1334         colormap=(unsigned char *) RelinquishMagickMemory(colormap);
   1335       }
   1336     if (image->gamma == 1.0)
   1337       {
   1338         for (i=0; i < (ssize_t) image->colors; i++)
   1339           if (IsPixelInfoGray(image->colormap+i) == MagickFalse)
   1340             break;
   1341         (void) SetImageColorspace(image,i == (ssize_t) image->colors ?
   1342           GRAYColorspace : RGBColorspace,exception);
   1343       }
   1344     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
   1345       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
   1346         break;
   1347     status=SetImageExtent(image,image->columns,image->rows,exception);
   1348     if (status == MagickFalse)
   1349       return(DestroyImageList(image));
   1350     /*
   1351       Decode image.
   1352     */
   1353     if (image_info->ping != MagickFalse)
   1354       status=PingGIFImage(image,exception);
   1355     else
   1356       status=DecodeImage(image,opacity,exception);
   1357     if ((image_info->ping == MagickFalse) && (status == MagickFalse))
   1358       {
   1359         global_colormap=(unsigned char *) RelinquishMagickMemory(
   1360           global_colormap);
   1361         ThrowReaderException(CorruptImageError,"CorruptImage");
   1362       }
   1363     duration+=image->delay*image->iterations;
   1364     if (image_info->number_scenes != 0)
   1365       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
   1366         break;
   1367     opacity=(-1);
   1368     status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) image->scene-1,
   1369       image->scene);
   1370     if (status == MagickFalse)
   1371       break;
   1372   }
   1373   image->duration=duration;
   1374   meta_image=DestroyImage(meta_image);
   1375   global_colormap=(unsigned char *) RelinquishMagickMemory(global_colormap);
   1376   if ((image->columns == 0) || (image->rows == 0))
   1377     ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
   1378   (void) CloseBlob(image);
   1379   return(GetFirstImageInList(image));
   1380 }
   1381 
   1382 /*
   1384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1385 %                                                                             %
   1386 %                                                                             %
   1387 %                                                                             %
   1388 %   R e g i s t e r G I F I m a g e                                           %
   1389 %                                                                             %
   1390 %                                                                             %
   1391 %                                                                             %
   1392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1393 %
   1394 %  RegisterGIFImage() adds properties for the GIF image format to
   1395 %  the list of supported formats.  The properties include the image format
   1396 %  tag, a method to read and/or write the format, whether the format
   1397 %  supports the saving of more than one frame to the same file or blob,
   1398 %  whether the format supports native in-memory I/O, and a brief
   1399 %  description of the format.
   1400 %
   1401 %  The format of the RegisterGIFImage method is:
   1402 %
   1403 %      size_t RegisterGIFImage(void)
   1404 %
   1405 */
   1406 ModuleExport size_t RegisterGIFImage(void)
   1407 {
   1408   MagickInfo
   1409     *entry;
   1410 
   1411   entry=AcquireMagickInfo("GIF","GIF",
   1412     "CompuServe graphics interchange format");
   1413   entry->decoder=(DecodeImageHandler *) ReadGIFImage;
   1414   entry->encoder=(EncodeImageHandler *) WriteGIFImage;
   1415   entry->magick=(IsImageFormatHandler *) IsGIF;
   1416   entry->mime_type=ConstantString("image/gif");
   1417   (void) RegisterMagickInfo(entry);
   1418   entry=AcquireMagickInfo("GIF","GIF87",
   1419     "CompuServe graphics interchange format");
   1420   entry->decoder=(DecodeImageHandler *) ReadGIFImage;
   1421   entry->encoder=(EncodeImageHandler *) WriteGIFImage;
   1422   entry->magick=(IsImageFormatHandler *) IsGIF;
   1423   entry->flags^=CoderAdjoinFlag;
   1424   entry->version=ConstantString("version 87a");
   1425   entry->mime_type=ConstantString("image/gif");
   1426   (void) RegisterMagickInfo(entry);
   1427   return(MagickImageCoderSignature);
   1428 }
   1429 
   1430 /*
   1432 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1433 %                                                                             %
   1434 %                                                                             %
   1435 %                                                                             %
   1436 %   U n r e g i s t e r G I F I m a g e                                       %
   1437 %                                                                             %
   1438 %                                                                             %
   1439 %                                                                             %
   1440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1441 %
   1442 %  UnregisterGIFImage() removes format registrations made by the
   1443 %  GIF module from the list of supported formats.
   1444 %
   1445 %  The format of the UnregisterGIFImage method is:
   1446 %
   1447 %      UnregisterGIFImage(void)
   1448 %
   1449 */
   1450 ModuleExport void UnregisterGIFImage(void)
   1451 {
   1452   (void) UnregisterMagickInfo("GIF");
   1453   (void) UnregisterMagickInfo("GIF87");
   1454 }
   1455 
   1456 /*
   1458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1459 %                                                                             %
   1460 %                                                                             %
   1461 %                                                                             %
   1462 %   W r i t e G I F I m a g e                                                 %
   1463 %                                                                             %
   1464 %                                                                             %
   1465 %                                                                             %
   1466 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1467 %
   1468 %  WriteGIFImage() writes an image to a file in the Compuserve Graphics
   1469 %  image format.
   1470 %
   1471 %  The format of the WriteGIFImage method is:
   1472 %
   1473 %      MagickBooleanType WriteGIFImage(const ImageInfo *image_info,
   1474 %        Image *image,ExceptionInfo *exception)
   1475 %
   1476 %  A description of each parameter follows.
   1477 %
   1478 %    o image_info: the image info.
   1479 %
   1480 %    o image:  The image.
   1481 %
   1482 %    o exception: return any errors or warnings in this structure.
   1483 %
   1484 */
   1485 static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image,
   1486   ExceptionInfo *exception)
   1487 {
   1488   int
   1489     c;
   1490 
   1491   ImageInfo
   1492     *write_info;
   1493 
   1494   MagickBooleanType
   1495     status;
   1496 
   1497   MagickOffsetType
   1498     scene;
   1499 
   1500   RectangleInfo
   1501     page;
   1502 
   1503   register ssize_t
   1504     i;
   1505 
   1506   register unsigned char
   1507     *q;
   1508 
   1509   size_t
   1510     bits_per_pixel,
   1511     delay,
   1512     length,
   1513     one;
   1514 
   1515   ssize_t
   1516     j,
   1517     opacity;
   1518 
   1519   unsigned char
   1520     *colormap,
   1521     *global_colormap;
   1522 
   1523   /*
   1524     Open output image file.
   1525   */
   1526   assert(image_info != (const ImageInfo *) NULL);
   1527   assert(image_info->signature == MagickCoreSignature);
   1528   assert(image != (Image *) NULL);
   1529   assert(image->signature == MagickCoreSignature);
   1530   if (image->debug != MagickFalse)
   1531     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   1532   assert(exception != (ExceptionInfo *) NULL);
   1533   assert(exception->signature == MagickCoreSignature);
   1534   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
   1535   if (status == MagickFalse)
   1536     return(status);
   1537   /*
   1538     Allocate colormap.
   1539   */
   1540   global_colormap=(unsigned char *) AcquireQuantumMemory(768UL,
   1541     sizeof(*global_colormap));
   1542   colormap=(unsigned char *) AcquireQuantumMemory(768UL,sizeof(*colormap));
   1543   if ((global_colormap == (unsigned char *) NULL) ||
   1544       (colormap == (unsigned char *) NULL))
   1545     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
   1546   for (i=0; i < 768; i++)
   1547     colormap[i]=(unsigned char) 0;
   1548   /*
   1549     Write GIF header.
   1550   */
   1551   write_info=CloneImageInfo(image_info);
   1552   if (LocaleCompare(write_info->magick,"GIF87") != 0)
   1553     (void) WriteBlob(image,6,(unsigned char *) "GIF89a");
   1554   else
   1555     {
   1556       (void) WriteBlob(image,6,(unsigned char *) "GIF87a");
   1557       write_info->adjoin=MagickFalse;
   1558     }
   1559   /*
   1560     Determine image bounding box.
   1561   */
   1562   page.width=image->columns;
   1563   if (image->page.width > page.width)
   1564     page.width=image->page.width;
   1565   page.height=image->rows;
   1566   if (image->page.height > page.height)
   1567     page.height=image->page.height;
   1568   page.x=image->page.x;
   1569   page.y=image->page.y;
   1570   (void) WriteBlobLSBShort(image,(unsigned short) page.width);
   1571   (void) WriteBlobLSBShort(image,(unsigned short) page.height);
   1572   /*
   1573     Write images to file.
   1574   */
   1575   if ((write_info->adjoin != MagickFalse) &&
   1576       (GetNextImageInList(image) != (Image *) NULL))
   1577     write_info->interlace=NoInterlace;
   1578   scene=0;
   1579   one=1;
   1580   do
   1581   {
   1582     (void) TransformImageColorspace(image,sRGBColorspace,exception);
   1583     opacity=(-1);
   1584     if (IsImageOpaque(image,exception) != MagickFalse)
   1585       {
   1586         if ((image->storage_class == DirectClass) || (image->colors > 256))
   1587           (void) SetImageType(image,PaletteType,exception);
   1588       }
   1589     else
   1590       {
   1591         double
   1592           alpha,
   1593           beta;
   1594 
   1595         /*
   1596           Identify transparent colormap index.
   1597         */
   1598         if ((image->storage_class == DirectClass) || (image->colors > 256))
   1599           (void) SetImageType(image,PaletteBilevelAlphaType,exception);
   1600         for (i=0; i < (ssize_t) image->colors; i++)
   1601           if (image->colormap[i].alpha != OpaqueAlpha)
   1602             {
   1603               if (opacity < 0)
   1604                 {
   1605                   opacity=i;
   1606                   continue;
   1607                 }
   1608               alpha=fabs(image->colormap[i].alpha-TransparentAlpha);
   1609               beta=fabs(image->colormap[opacity].alpha-TransparentAlpha);
   1610               if (alpha < beta)
   1611                 opacity=i;
   1612             }
   1613         if (opacity == -1)
   1614           {
   1615             (void) SetImageType(image,PaletteBilevelAlphaType,exception);
   1616             for (i=0; i < (ssize_t) image->colors; i++)
   1617               if (image->colormap[i].alpha != OpaqueAlpha)
   1618                 {
   1619                   if (opacity < 0)
   1620                     {
   1621                       opacity=i;
   1622                       continue;
   1623                     }
   1624                   alpha=fabs(image->colormap[i].alpha-TransparentAlpha);
   1625                   beta=fabs(image->colormap[opacity].alpha-TransparentAlpha);
   1626                   if (alpha < beta)
   1627                     opacity=i;
   1628                 }
   1629           }
   1630         if (opacity >= 0)
   1631           {
   1632             image->colormap[opacity].red=image->transparent_color.red;
   1633             image->colormap[opacity].green=image->transparent_color.green;
   1634             image->colormap[opacity].blue=image->transparent_color.blue;
   1635           }
   1636       }
   1637     if ((image->storage_class == DirectClass) || (image->colors > 256))
   1638       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
   1639     for (bits_per_pixel=1; bits_per_pixel < 8; bits_per_pixel++)
   1640       if ((one << bits_per_pixel) >= image->colors)
   1641         break;
   1642     q=colormap;
   1643     for (i=0; i < (ssize_t) image->colors; i++)
   1644     {
   1645       *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
   1646       *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
   1647       *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));
   1648     }
   1649     for ( ; i < (ssize_t) (one << bits_per_pixel); i++)
   1650     {
   1651       *q++=(unsigned char) 0x0;
   1652       *q++=(unsigned char) 0x0;
   1653       *q++=(unsigned char) 0x0;
   1654     }
   1655     if ((GetPreviousImageInList(image) == (Image *) NULL) ||
   1656         (write_info->adjoin == MagickFalse))
   1657       {
   1658         /*
   1659           Write global colormap.
   1660         */
   1661         c=0x80;
   1662         c|=(8-1) << 4;  /* color resolution */
   1663         c|=(bits_per_pixel-1);   /* size of global colormap */
   1664         (void) WriteBlobByte(image,(unsigned char) c);
   1665         for (j=0; j < (ssize_t) image->colors; j++)
   1666           if (IsPixelInfoEquivalent(&image->background_color,image->colormap+j))
   1667             break;
   1668         (void) WriteBlobByte(image,(unsigned char)
   1669           (j == (ssize_t) image->colors ? 0 : j));  /* background color */
   1670         (void) WriteBlobByte(image,(unsigned char) 0x00);  /* reserved */
   1671         length=(size_t) (3*(one << bits_per_pixel));
   1672         (void) WriteBlob(image,length,colormap);
   1673         for (j=0; j < 768; j++)
   1674           global_colormap[j]=colormap[j];
   1675       }
   1676     if (LocaleCompare(write_info->magick,"GIF87") != 0)
   1677       {
   1678         const char
   1679           *value;
   1680 
   1681         /*
   1682           Write graphics control extension.
   1683         */
   1684         (void) WriteBlobByte(image,(unsigned char) 0x21);
   1685         (void) WriteBlobByte(image,(unsigned char) 0xf9);
   1686         (void) WriteBlobByte(image,(unsigned char) 0x04);
   1687         c=image->dispose << 2;
   1688         if (opacity >= 0)
   1689           c|=0x01;
   1690         (void) WriteBlobByte(image,(unsigned char) c);
   1691         delay=(size_t) (100*image->delay/MagickMax((size_t)
   1692           image->ticks_per_second,1));
   1693         (void) WriteBlobLSBShort(image,(unsigned short) delay);
   1694         (void) WriteBlobByte(image,(unsigned char) (opacity >= 0 ? opacity :
   1695           0));
   1696         (void) WriteBlobByte(image,(unsigned char) 0x00);
   1697         value=GetImageProperty(image,"comment",exception);
   1698         if ((LocaleCompare(write_info->magick,"GIF87") != 0) &&
   1699             (value != (const char *) NULL))
   1700           {
   1701             register const char
   1702               *p;
   1703 
   1704             size_t
   1705               count;
   1706 
   1707             /*
   1708               Write comment extension.
   1709             */
   1710             (void) WriteBlobByte(image,(unsigned char) 0x21);
   1711             (void) WriteBlobByte(image,(unsigned char) 0xfe);
   1712             for (p=value; *p != '\0'; )
   1713             {
   1714               count=MagickMin(strlen(p),255);
   1715               (void) WriteBlobByte(image,(unsigned char) count);
   1716               for (i=0; i < (ssize_t) count; i++)
   1717                 (void) WriteBlobByte(image,(unsigned char) *p++);
   1718             }
   1719             (void) WriteBlobByte(image,(unsigned char) 0x00);
   1720           }
   1721         if ((GetPreviousImageInList(image) == (Image *) NULL) &&
   1722             (GetNextImageInList(image) != (Image *) NULL) &&
   1723             (image->iterations != 1))
   1724           {
   1725             /*
   1726               Write Netscape Loop extension.
   1727             */
   1728             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1729                "  Writing GIF Extension %s","NETSCAPE2.0");
   1730             (void) WriteBlobByte(image,(unsigned char) 0x21);
   1731             (void) WriteBlobByte(image,(unsigned char) 0xff);
   1732             (void) WriteBlobByte(image,(unsigned char) 0x0b);
   1733             (void) WriteBlob(image,11,(unsigned char *) "NETSCAPE2.0");
   1734             (void) WriteBlobByte(image,(unsigned char) 0x03);
   1735             (void) WriteBlobByte(image,(unsigned char) 0x01);
   1736             (void) WriteBlobLSBShort(image,(unsigned short) image->iterations);
   1737             (void) WriteBlobByte(image,(unsigned char) 0x00);
   1738           }
   1739         if ((image->gamma != 1.0f/2.2f))
   1740           {
   1741             char
   1742               attributes[MagickPathExtent];
   1743 
   1744             ssize_t
   1745               count;
   1746 
   1747             /*
   1748               Write ImageMagick extension.
   1749             */
   1750             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1751                "  Writing GIF Extension %s","ImageMagick");
   1752             (void) WriteBlobByte(image,(unsigned char) 0x21);
   1753             (void) WriteBlobByte(image,(unsigned char) 0xff);
   1754             (void) WriteBlobByte(image,(unsigned char) 0x0b);
   1755             (void) WriteBlob(image,11,(unsigned char *) "ImageMagick");
   1756             count=FormatLocaleString(attributes,MagickPathExtent,"gamma=%g",
   1757               image->gamma);
   1758             (void) WriteBlobByte(image,(unsigned char) count);
   1759             (void) WriteBlob(image,(size_t) count,(unsigned char *) attributes);
   1760             (void) WriteBlobByte(image,(unsigned char) 0x00);
   1761           }
   1762         ResetImageProfileIterator(image);
   1763         for ( ; ; )
   1764         {
   1765           char
   1766             *name;
   1767 
   1768           const StringInfo
   1769             *profile;
   1770 
   1771           name=GetNextImageProfile(image);
   1772           if (name == (const char *) NULL)
   1773             break;
   1774           profile=GetImageProfile(image,name);
   1775           if (profile != (StringInfo *) NULL)
   1776           {
   1777             if ((LocaleCompare(name,"ICC") == 0) ||
   1778                 (LocaleCompare(name,"ICM") == 0) ||
   1779                 (LocaleCompare(name,"IPTC") == 0) ||
   1780                 (LocaleCompare(name,"8BIM") == 0) ||
   1781                 (LocaleNCompare(name,"gif:",4) == 0))
   1782             {
   1783                ssize_t
   1784                  offset;
   1785 
   1786                unsigned char
   1787                  *datum;
   1788 
   1789                datum=GetStringInfoDatum(profile);
   1790                length=GetStringInfoLength(profile);
   1791                (void) WriteBlobByte(image,(unsigned char) 0x21);
   1792                (void) WriteBlobByte(image,(unsigned char) 0xff);
   1793                (void) WriteBlobByte(image,(unsigned char) 0x0b);
   1794                if ((LocaleCompare(name,"ICC") == 0) ||
   1795                    (LocaleCompare(name,"ICM") == 0))
   1796                  {
   1797                    /*
   1798                      Write ICC extension.
   1799                    */
   1800                    (void) WriteBlob(image,11,(unsigned char *) "ICCRGBG1012");
   1801                    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1802                      "  Writing GIF Extension %s","ICCRGBG1012");
   1803                  }
   1804                else
   1805                  if ((LocaleCompare(name,"IPTC") == 0))
   1806                    {
   1807                      /*
   1808                        Write IPTC extension.
   1809                      */
   1810                      (void) WriteBlob(image,11,(unsigned char *) "MGKIPTC0000");
   1811                      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1812                        "  Writing GIF Extension %s","MGKIPTC0000");
   1813                    }
   1814                  else
   1815                    if ((LocaleCompare(name,"8BIM") == 0))
   1816                      {
   1817                        /*
   1818                          Write 8BIM extension.
   1819                        */
   1820                         (void) WriteBlob(image,11,(unsigned char *)
   1821                           "MGK8BIM0000");
   1822                         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1823                           "  Writing GIF Extension %s","MGK8BIM0000");
   1824                      }
   1825                    else
   1826                      {
   1827                        char
   1828                          extension[MagickPathExtent];
   1829 
   1830                        /*
   1831                          Write generic extension.
   1832                        */
   1833                        (void) CopyMagickString(extension,name+4,
   1834                          sizeof(extension));
   1835                        (void) WriteBlob(image,11,(unsigned char *) extension);
   1836                        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1837                          "  Writing GIF Extension %s",name);
   1838                      }
   1839                offset=0;
   1840                while ((ssize_t) length > offset)
   1841                {
   1842                  size_t
   1843                    block_length;
   1844 
   1845                  if ((length-offset) < 255)
   1846                    block_length=length-offset;
   1847                  else
   1848                    block_length=255;
   1849                  (void) WriteBlobByte(image,(unsigned char) block_length);
   1850                  (void) WriteBlob(image,(size_t) block_length,datum+offset);
   1851                  offset+=(ssize_t) block_length;
   1852                }
   1853                (void) WriteBlobByte(image,(unsigned char) 0x00);
   1854             }
   1855           }
   1856         }
   1857       }
   1858     (void) WriteBlobByte(image,',');  /* image separator */
   1859     /*
   1860       Write the image header.
   1861     */
   1862     page.x=image->page.x;
   1863     page.y=image->page.y;
   1864     if ((image->page.width != 0) && (image->page.height != 0))
   1865       page=image->page;
   1866     (void) WriteBlobLSBShort(image,(unsigned short) (page.x < 0 ? 0 : page.x));
   1867     (void) WriteBlobLSBShort(image,(unsigned short) (page.y < 0 ? 0 : page.y));
   1868     (void) WriteBlobLSBShort(image,(unsigned short) image->columns);
   1869     (void) WriteBlobLSBShort(image,(unsigned short) image->rows);
   1870     c=0x00;
   1871     if (write_info->interlace != NoInterlace)
   1872       c|=0x40;  /* pixel data is interlaced */
   1873     for (j=0; j < (ssize_t) (3*image->colors); j++)
   1874       if (colormap[j] != global_colormap[j])
   1875         break;
   1876     if (j == (ssize_t) (3*image->colors))
   1877       (void) WriteBlobByte(image,(unsigned char) c);
   1878     else
   1879       {
   1880         c|=0x80;
   1881         c|=(bits_per_pixel-1);   /* size of local colormap */
   1882         (void) WriteBlobByte(image,(unsigned char) c);
   1883         length=(size_t) (3*(one << bits_per_pixel));
   1884         (void) WriteBlob(image,length,colormap);
   1885       }
   1886     /*
   1887       Write the image data.
   1888     */
   1889     c=(int) MagickMax(bits_per_pixel,2);
   1890     (void) WriteBlobByte(image,(unsigned char) c);
   1891     status=EncodeImage(write_info,image,(size_t) MagickMax(bits_per_pixel,2)+1,
   1892       exception);
   1893     if (status == MagickFalse)
   1894       {
   1895         global_colormap=(unsigned char *) RelinquishMagickMemory(
   1896           global_colormap);
   1897         colormap=(unsigned char *) RelinquishMagickMemory(colormap);
   1898         write_info=DestroyImageInfo(write_info);
   1899         ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
   1900       }
   1901     (void) WriteBlobByte(image,(unsigned char) 0x00);
   1902     if (GetNextImageInList(image) == (Image *) NULL)
   1903       break;
   1904     image=SyncNextImageInList(image);
   1905     scene++;
   1906     status=SetImageProgress(image,SaveImagesTag,scene,
   1907       GetImageListLength(image));
   1908     if (status == MagickFalse)
   1909       break;
   1910   } while (write_info->adjoin != MagickFalse);
   1911   (void) WriteBlobByte(image,';'); /* terminator */
   1912   global_colormap=(unsigned char *) RelinquishMagickMemory(global_colormap);
   1913   colormap=(unsigned char *) RelinquishMagickMemory(colormap);
   1914   write_info=DestroyImageInfo(write_info);
   1915   (void) CloseBlob(image);
   1916   return(MagickTrue);
   1917 }
   1918