Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                            RRRR   L      EEEEE                              %
      7 %                            R   R  L      E                                  %
      8 %                            RRRR   L      EEE                                %
      9 %                            R R    L      E                                  %
     10 %                            R  R   LLLLL  EEEEE                              %
     11 %                                                                             %
     12 %                                                                             %
     13 %                          Read URT RLE 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/colormap.h"
     48 #include "MagickCore/colormap-private.h"
     49 #include "MagickCore/exception.h"
     50 #include "MagickCore/exception-private.h"
     51 #include "MagickCore/image.h"
     52 #include "MagickCore/image-private.h"
     53 #include "MagickCore/list.h"
     54 #include "MagickCore/magick.h"
     55 #include "MagickCore/memory_.h"
     56 #include "MagickCore/monitor.h"
     57 #include "MagickCore/monitor-private.h"
     58 #include "MagickCore/pixel-accessor.h"
     59 #include "MagickCore/pixel.h"
     60 #include "MagickCore/property.h"
     61 #include "MagickCore/quantum-private.h"
     62 #include "MagickCore/static.h"
     63 #include "MagickCore/string_.h"
     64 #include "MagickCore/module.h"
     65 
     66 /*
     68 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     69 %                                                                             %
     70 %                                                                             %
     71 %                                                                             %
     72 %   I s R L E                                                                 %
     73 %                                                                             %
     74 %                                                                             %
     75 %                                                                             %
     76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     77 %
     78 %  IsRLE() returns MagickTrue if the image format type, identified by the
     79 %  magick string, is RLE.
     80 %
     81 %  The format of the ReadRLEImage method is:
     82 %
     83 %      MagickBooleanType IsRLE(const unsigned char *magick,const size_t length)
     84 %
     85 %  A description of each parameter follows:
     86 %
     87 %    o magick: compare image format pattern against these bytes.
     88 %
     89 %    o length: Specifies the length of the magick string.
     90 %
     91 %
     92 */
     93 static MagickBooleanType IsRLE(const unsigned char *magick,const size_t length)
     94 {
     95   if (length < 2)
     96     return(MagickFalse);
     97   if (memcmp(magick,"\122\314",2) == 0)
     98     return(MagickTrue);
     99   return(MagickFalse);
    100 }
    101 
    102 /*
    104 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    105 %                                                                             %
    106 %                                                                             %
    107 %                                                                             %
    108 %   R e a d R L E I m a g e                                                   %
    109 %                                                                             %
    110 %                                                                             %
    111 %                                                                             %
    112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    113 %
    114 %  ReadRLEImage() reads a run-length encoded Utah Raster Toolkit
    115 %  image file and returns it.  It allocates the memory necessary for the new
    116 %  Image structure and returns a pointer to the new image.
    117 %
    118 %  The format of the ReadRLEImage method is:
    119 %
    120 %      Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
    121 %
    122 %  A description of each parameter follows:
    123 %
    124 %    o image_info: the image info.
    125 %
    126 %    o exception: return any errors or warnings in this structure.
    127 %
    128 %
    129 */
    130 static Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
    131 {
    132 #define SkipLinesOp  0x01
    133 #define SetColorOp  0x02
    134 #define SkipPixelsOp  0x03
    135 #define ByteDataOp  0x05
    136 #define RunDataOp  0x06
    137 #define EOFOp  0x07
    138 
    139   char
    140     magick[12];
    141 
    142   Image
    143     *image;
    144 
    145   int
    146     opcode,
    147     operand,
    148     status;
    149 
    150   MagickStatusType
    151     flags;
    152 
    153   MagickSizeType
    154     number_pixels;
    155 
    156   MemoryInfo
    157     *pixel_info;
    158 
    159   Quantum
    160     index;
    161 
    162   register ssize_t
    163     x;
    164 
    165   register Quantum
    166     *q;
    167 
    168   register ssize_t
    169     i;
    170 
    171   register unsigned char
    172     *p;
    173 
    174   size_t
    175     bits_per_pixel,
    176     map_length,
    177     number_colormaps,
    178     number_planes,
    179     number_planes_filled,
    180     one,
    181     pixel_info_length;
    182 
    183   ssize_t
    184     count,
    185     offset,
    186     y;
    187 
    188   unsigned char
    189     background_color[256],
    190     *colormap,
    191     pixel,
    192     plane,
    193     *pixels;
    194 
    195   /*
    196     Open image file.
    197   */
    198   assert(image_info != (const ImageInfo *) NULL);
    199   assert(image_info->signature == MagickCoreSignature);
    200   if (image_info->debug != MagickFalse)
    201     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    202       image_info->filename);
    203   assert(exception != (ExceptionInfo *) NULL);
    204   assert(exception->signature == MagickCoreSignature);
    205   image=AcquireImage(image_info,exception);
    206   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    207   if (status == MagickFalse)
    208     return(DestroyImageList(image));
    209   /*
    210     Determine if this a RLE file.
    211   */
    212   count=ReadBlob(image,2,(unsigned char *) magick);
    213   if ((count != 2) || (memcmp(magick,"\122\314",2) != 0))
    214     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    215   do
    216   {
    217     /*
    218       Read image header.
    219     */
    220     image->page.x=ReadBlobLSBShort(image);
    221     image->page.y=ReadBlobLSBShort(image);
    222     image->columns=ReadBlobLSBShort(image);
    223     image->rows=ReadBlobLSBShort(image);
    224     flags=(MagickStatusType) ReadBlobByte(image);
    225     image->alpha_trait=flags & 0x04 ? BlendPixelTrait : UndefinedPixelTrait;
    226     number_planes=(size_t) ReadBlobByte(image);
    227     bits_per_pixel=(size_t) ReadBlobByte(image);
    228     number_colormaps=(size_t) ReadBlobByte(image);
    229     map_length=(unsigned char) ReadBlobByte(image);
    230     if (map_length >= 64)
    231       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    232     one=1;
    233     map_length=one << map_length;
    234     if ((number_planes == 0) || (number_planes == 2) ||
    235         ((flags & 0x04) && (number_colormaps > 254)) || (bits_per_pixel != 8) ||
    236         (image->columns == 0))
    237       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    238     if (flags & 0x02)
    239       {
    240         /*
    241           No background color-- initialize to black.
    242         */
    243         for (i=0; i < (ssize_t) number_planes; i++)
    244           background_color[i]=0;
    245         (void) ReadBlobByte(image);
    246       }
    247     else
    248       {
    249         /*
    250           Initialize background color.
    251         */
    252         p=background_color;
    253         for (i=0; i < (ssize_t) number_planes; i++)
    254           *p++=(unsigned char) ReadBlobByte(image);
    255       }
    256     if ((number_planes & 0x01) == 0)
    257       (void) ReadBlobByte(image);
    258     if (EOFBlob(image) != MagickFalse)
    259       {
    260         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
    261           image->filename);
    262         break;
    263       }
    264     colormap=(unsigned char *) NULL;
    265     if (number_colormaps != 0)
    266       {
    267         /*
    268           Read image colormaps.
    269         */
    270         colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps,
    271           3*map_length*sizeof(*colormap));
    272         if (colormap == (unsigned char *) NULL)
    273           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    274         p=colormap;
    275         for (i=0; i < (ssize_t) number_colormaps; i++)
    276           for (x=0; x < (ssize_t) map_length; x++)
    277             *p++=(unsigned char) ScaleShortToQuantum(ReadBlobLSBShort(image));
    278       }
    279     if ((flags & 0x08) != 0)
    280       {
    281         char
    282           *comment;
    283 
    284         size_t
    285           length;
    286 
    287         /*
    288           Read image comment.
    289         */
    290         length=ReadBlobLSBShort(image);
    291         if (length != 0)
    292           {
    293             comment=(char *) AcquireQuantumMemory(length,sizeof(*comment));
    294             if (comment == (char *) NULL)
    295               ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    296             count=ReadBlob(image,length-1,(unsigned char *) comment);
    297             comment[length-1]='\0';
    298             (void) SetImageProperty(image,"comment",comment,exception);
    299             comment=DestroyString(comment);
    300             if ((length & 0x01) == 0)
    301               (void) ReadBlobByte(image);
    302           }
    303       }
    304     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
    305       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
    306         break;
    307     status=SetImageExtent(image,image->columns,image->rows,exception);
    308     if (status == MagickFalse)
    309       return(DestroyImageList(image));
    310     /*
    311       Allocate RLE pixels.
    312     */
    313     if (image->alpha_trait != UndefinedPixelTrait)
    314       number_planes++;
    315     number_pixels=(MagickSizeType) image->columns*image->rows;
    316     number_planes_filled=(number_planes % 2 == 0) ? number_planes :
    317       number_planes+1;
    318     if ((number_pixels*number_planes_filled) != (size_t) (number_pixels*
    319          number_planes_filled))
    320       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    321     pixel_info=AcquireVirtualMemory(image->columns,image->rows*
    322       MagickMax(number_planes_filled,4)*sizeof(*pixels));
    323     if (pixel_info == (MemoryInfo *) NULL)
    324       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    325     pixel_info_length=image->columns*image->rows*
    326       MagickMax(number_planes_filled,4);
    327     pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
    328     if ((flags & 0x01) && !(flags & 0x02))
    329       {
    330         ssize_t
    331           j;
    332 
    333         /*
    334           Set background color.
    335         */
    336         p=pixels;
    337         for (i=0; i < (ssize_t) number_pixels; i++)
    338         {
    339           if (image->alpha_trait == UndefinedPixelTrait)
    340             for (j=0; j < (ssize_t) number_planes; j++)
    341               *p++=background_color[j];
    342           else
    343             {
    344               for (j=0; j < (ssize_t) (number_planes-1); j++)
    345                 *p++=background_color[j];
    346               *p++=0;  /* initialize matte channel */
    347             }
    348         }
    349       }
    350     /*
    351       Read runlength-encoded image.
    352     */
    353     plane=0;
    354     x=0;
    355     y=0;
    356     opcode=ReadBlobByte(image);
    357     do
    358     {
    359       switch (opcode & 0x3f)
    360       {
    361         case SkipLinesOp:
    362         {
    363           operand=ReadBlobByte(image);
    364           if (opcode & 0x40)
    365             operand=ReadBlobLSBSignedShort(image);
    366           x=0;
    367           y+=operand;
    368           break;
    369         }
    370         case SetColorOp:
    371         {
    372           operand=ReadBlobByte(image);
    373           plane=(unsigned char) operand;
    374           if (plane == 255)
    375             plane=(unsigned char) (number_planes-1);
    376           x=0;
    377           break;
    378         }
    379         case SkipPixelsOp:
    380         {
    381           operand=ReadBlobByte(image);
    382           if (opcode & 0x40)
    383             operand=ReadBlobLSBSignedShort(image);
    384           x+=operand;
    385           break;
    386         }
    387         case ByteDataOp:
    388         {
    389           operand=ReadBlobByte(image);
    390           if (opcode & 0x40)
    391             operand=ReadBlobLSBSignedShort(image);
    392           offset=((image->rows-y-1)*image->columns*number_planes)+x*
    393             number_planes+plane;
    394           operand++;
    395           if ((offset < 0) ||
    396               (offset+((size_t) operand*number_planes) > pixel_info_length))
    397             {
    398               if (number_colormaps != 0)
    399                 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
    400               pixel_info=RelinquishVirtualMemory(pixel_info);
    401               ThrowReaderException(CorruptImageError,"UnableToReadImageData");
    402             }
    403           p=pixels+offset;
    404           for (i=0; i < (ssize_t) operand; i++)
    405           {
    406             pixel=(unsigned char) ReadBlobByte(image);
    407             if ((y < (ssize_t) image->rows) &&
    408                 ((x+i) < (ssize_t) image->columns))
    409               *p=pixel;
    410             p+=number_planes;
    411           }
    412           if (operand & 0x01)
    413             (void) ReadBlobByte(image);
    414           x+=operand;
    415           break;
    416         }
    417         case RunDataOp:
    418         {
    419           operand=ReadBlobByte(image);
    420           if (opcode & 0x40)
    421             operand=ReadBlobLSBSignedShort(image);
    422           pixel=(unsigned char) ReadBlobByte(image);
    423           (void) ReadBlobByte(image);
    424           offset=((image->rows-y-1)*image->columns*number_planes)+x*
    425             number_planes+plane;
    426           operand++;
    427           if ((offset < 0) ||
    428               (offset+((size_t) operand*number_planes) > pixel_info_length))
    429             {
    430               if (number_colormaps != 0)
    431                 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
    432               pixel_info=RelinquishVirtualMemory(pixel_info);
    433               ThrowReaderException(CorruptImageError,"UnableToReadImageData");
    434             }
    435           p=pixels+offset;
    436           for (i=0; i < (ssize_t) operand; i++)
    437           {
    438             if ((y < (ssize_t) image->rows) &&
    439                 ((x+i) < (ssize_t) image->columns))
    440               *p=pixel;
    441             p+=number_planes;
    442           }
    443           x+=operand;
    444           break;
    445         }
    446         default:
    447           break;
    448       }
    449       opcode=ReadBlobByte(image);
    450     } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
    451     if (number_colormaps != 0)
    452       {
    453         MagickStatusType
    454           mask;
    455 
    456         /*
    457           Apply colormap affineation to image.
    458         */
    459         mask=(MagickStatusType) (map_length-1);
    460         p=pixels;
    461         x=(ssize_t) number_planes;
    462         if (number_colormaps == 1)
    463           for (i=0; i < (ssize_t) number_pixels; i++)
    464           {
    465             ValidateColormapValue(image,*p & mask,&index,exception);
    466             *p=colormap[(ssize_t) index];
    467             p++;
    468           }
    469         else
    470           if ((number_planes >= 3) && (number_colormaps >= 3))
    471             for (i=0; i < (ssize_t) number_pixels; i++)
    472               for (x=0; x < (ssize_t) number_planes; x++)
    473               {
    474                 ValidateColormapValue(image,(size_t) (x*map_length+
    475                     (*p & mask)),&index,exception);
    476                 *p=colormap[(ssize_t) index];
    477                 p++;
    478               }
    479         if ((i < (ssize_t) number_pixels) || (x < (ssize_t) number_planes))
    480           {
    481             colormap=(unsigned char *) RelinquishMagickMemory(colormap);
    482             pixel_info=RelinquishVirtualMemory(pixel_info);
    483             ThrowReaderException(CorruptImageError,"UnableToReadImageData");
    484           }
    485       }
    486     /*
    487       Initialize image structure.
    488     */
    489     if (number_planes >= 3)
    490       {
    491         /*
    492           Convert raster image to DirectClass pixel packets.
    493         */
    494         p=pixels;
    495         for (y=0; y < (ssize_t) image->rows; y++)
    496         {
    497           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    498           if (q == (Quantum *) NULL)
    499             break;
    500           for (x=0; x < (ssize_t) image->columns; x++)
    501           {
    502             SetPixelRed(image,ScaleCharToQuantum(*p++),q);
    503             SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
    504             SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
    505             if (image->alpha_trait != UndefinedPixelTrait)
    506               SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
    507             q+=GetPixelChannels(image);
    508           }
    509           if (SyncAuthenticPixels(image,exception) == MagickFalse)
    510             break;
    511           if (image->previous == (Image *) NULL)
    512             {
    513               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
    514                 image->rows);
    515               if (status == MagickFalse)
    516                 break;
    517             }
    518         }
    519       }
    520     else
    521       {
    522         /*
    523           Create colormap.
    524         */
    525         if (number_colormaps == 0)
    526           map_length=256;
    527         if (AcquireImageColormap(image,map_length,exception) == MagickFalse)
    528           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
    529         p=colormap;
    530         if (number_colormaps == 1)
    531           for (i=0; i < (ssize_t) image->colors; i++)
    532           {
    533             /*
    534               Pseudocolor.
    535             */
    536             image->colormap[i].red=(MagickRealType)
    537               ScaleCharToQuantum((unsigned char) i);
    538             image->colormap[i].green=(MagickRealType)
    539               ScaleCharToQuantum((unsigned char) i);
    540             image->colormap[i].blue=(MagickRealType)
    541               ScaleCharToQuantum((unsigned char) i);
    542           }
    543         else
    544           if (number_colormaps > 1)
    545             for (i=0; i < (ssize_t) image->colors; i++)
    546             {
    547               image->colormap[i].red=(MagickRealType)
    548                 ScaleCharToQuantum(*p);
    549               image->colormap[i].green=(MagickRealType)
    550                 ScaleCharToQuantum(*(p+map_length));
    551               image->colormap[i].blue=(MagickRealType)
    552                 ScaleCharToQuantum(*(p+map_length*2));
    553               p++;
    554             }
    555         p=pixels;
    556         if (image->alpha_trait == UndefinedPixelTrait)
    557           {
    558             /*
    559               Convert raster image to PseudoClass pixel packets.
    560             */
    561             for (y=0; y < (ssize_t) image->rows; y++)
    562             {
    563               q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    564               if (q == (Quantum *) NULL)
    565                 break;
    566               for (x=0; x < (ssize_t) image->columns; x++)
    567               {
    568                 SetPixelIndex(image,*p++,q);
    569                 q+=GetPixelChannels(image);
    570               }
    571               if (SyncAuthenticPixels(image,exception) == MagickFalse)
    572                 break;
    573               if (image->previous == (Image *) NULL)
    574                 {
    575                   status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
    576                     y,image->rows);
    577                   if (status == MagickFalse)
    578                     break;
    579                 }
    580             }
    581             (void) SyncImage(image,exception);
    582           }
    583         else
    584           {
    585             /*
    586               Image has a matte channel-- promote to DirectClass.
    587             */
    588             for (y=0; y < (ssize_t) image->rows; y++)
    589             {
    590               q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    591               if (q == (Quantum *) NULL)
    592                 break;
    593               for (x=0; x < (ssize_t) image->columns; x++)
    594               {
    595                 ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
    596                 SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t)
    597                   index].red),q);
    598                 ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
    599                 SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t)
    600                   index].green),q);
    601                 ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
    602                 SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t)
    603                   index].blue),q);
    604                 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
    605                 q+=GetPixelChannels(image);
    606               }
    607               if (x < (ssize_t) image->columns)
    608                 break;
    609               if (SyncAuthenticPixels(image,exception) == MagickFalse)
    610                 break;
    611               if (image->previous == (Image *) NULL)
    612                 {
    613                   status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
    614                     y,image->rows);
    615                   if (status == MagickFalse)
    616                     break;
    617                 }
    618             }
    619             image->colormap=(PixelInfo *) RelinquishMagickMemory(
    620               image->colormap);
    621             image->storage_class=DirectClass;
    622             image->colors=0;
    623           }
    624       }
    625     if (number_colormaps != 0)
    626       colormap=(unsigned char *) RelinquishMagickMemory(colormap);
    627     pixel_info=RelinquishVirtualMemory(pixel_info);
    628     if (EOFBlob(image) != MagickFalse)
    629       {
    630         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
    631           image->filename);
    632         break;
    633       }
    634     /*
    635       Proceed to next image.
    636     */
    637     if (image_info->number_scenes != 0)
    638       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
    639         break;
    640     (void) ReadBlobByte(image);
    641     count=ReadBlob(image,2,(unsigned char *) magick);
    642     if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
    643       {
    644         /*
    645           Allocate next image structure.
    646         */
    647         AcquireNextImage(image_info,image,exception);
    648         if (GetNextImageInList(image) == (Image *) NULL)
    649           {
    650             image=DestroyImageList(image);
    651             return((Image *) NULL);
    652           }
    653         image=SyncNextImageInList(image);
    654         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
    655           GetBlobSize(image));
    656         if (status == MagickFalse)
    657           break;
    658       }
    659   } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
    660   (void) CloseBlob(image);
    661   return(GetFirstImageInList(image));
    662 }
    663 
    664 /*
    666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    667 %                                                                             %
    668 %                                                                             %
    669 %                                                                             %
    670 %   R e g i s t e r R L E I m a g e                                           %
    671 %                                                                             %
    672 %                                                                             %
    673 %                                                                             %
    674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    675 %
    676 %  RegisterRLEImage() adds attributes for the RLE image format to
    677 %  the list of supported formats.  The attributes include the image format
    678 %  tag, a method to read and/or write the format, whether the format
    679 %  supports the saving of more than one frame to the same file or blob,
    680 %  whether the format supports native in-memory I/O, and a brief
    681 %  description of the format.
    682 %
    683 %  The format of the RegisterRLEImage method is:
    684 %
    685 %      size_t RegisterRLEImage(void)
    686 %
    687 */
    688 ModuleExport size_t RegisterRLEImage(void)
    689 {
    690   MagickInfo
    691     *entry;
    692 
    693   entry=AcquireMagickInfo("RLE","RLE","Utah Run length encoded image");
    694   entry->decoder=(DecodeImageHandler *) ReadRLEImage;
    695   entry->magick=(IsImageFormatHandler *) IsRLE;
    696   entry->flags^=CoderAdjoinFlag;
    697   (void) RegisterMagickInfo(entry);
    698   return(MagickImageCoderSignature);
    699 }
    700 
    701 /*
    703 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    704 %                                                                             %
    705 %                                                                             %
    706 %                                                                             %
    707 %   U n r e g i s t e r R L E I m a g e                                       %
    708 %                                                                             %
    709 %                                                                             %
    710 %                                                                             %
    711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    712 %
    713 %  UnregisterRLEImage() removes format registrations made by the
    714 %  RLE module from the list of supported formats.
    715 %
    716 %  The format of the UnregisterRLEImage method is:
    717 %
    718 %      UnregisterRLEImage(void)
    719 %
    720 */
    721 ModuleExport void UnregisterRLEImage(void)
    722 {
    723   (void) UnregisterMagickInfo("RLE");
    724 }
    725