Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                              CCC  U   U  TTTTT                              %
      6 %                             C     U   U    T                                %
      7 %                             C     U   U    T                                %
      8 %                             C     U   U    T                                %
      9 %                              CCC   UUU     T                                %
     10 %                                                                             %
     11 %                                                                             %
     12 %                         Read DR Halo Image Format                           %
     13 %                                                                             %
     14 %                              Software Design                                %
     15 %                              Jaroslav Fojtik                                %
     16 %                                 June 2000                                   %
     17 %                                                                             %
     18 %                                                                             %
     19 %  Permission is hereby granted, free of charge, to any person obtaining a    %
     20 %  copy of this software and associated documentation files ("ImageMagick"),  %
     21 %  to deal in ImageMagick without restriction, including without limitation   %
     22 %  the rights to use, copy, modify, merge, publish, distribute, sublicense,   %
     23 %  and/or sell copies of ImageMagick, and to permit persons to whom the       %
     24 %  ImageMagick is furnished to do so, subject to the following conditions:    %
     25 %                                                                             %
     26 %  The above copyright notice and this permission notice shall be included in %
     27 %  all copies or substantial portions of ImageMagick.                         %
     28 %                                                                             %
     29 %  The software is provided "as is", without warranty of any kind, express or %
     30 %  implied, including but not limited to the warranties of merchantability,   %
     31 %  fitness for a particular purpose and noninfringement.  In no event shall   %
     32 %  ImageMagick Studio be liable for any claim, damages or other liability,    %
     33 %  whether in an action of contract, tort or otherwise, arising from, out of  %
     34 %  or in connection with ImageMagick or the use or other dealings in          %
     35 %  ImageMagick.                                                               %
     36 %                                                                             %
     37 %  Except as contained in this notice, the name of the ImageMagick Studio     %
     38 %  shall not be used in advertising or otherwise to promote the sale, use or  %
     39 %  other dealings in ImageMagick without prior written authorization from the %
     40 %  ImageMagick Studio.                                                        %
     41 %                                                                             %
     42 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     43 %
     44 %
     45 */
     46 
     47 /*
     49   Include declarations.
     50 */
     51 #include "MagickCore/studio.h"
     52 #include "MagickCore/attribute.h"
     53 #include "MagickCore/blob.h"
     54 #include "MagickCore/blob-private.h"
     55 #include "MagickCore/cache.h"
     56 #include "MagickCore/color.h"
     57 #include "MagickCore/color-private.h"
     58 #include "MagickCore/colormap.h"
     59 #include "MagickCore/colormap-private.h"
     60 #include "MagickCore/exception.h"
     61 #include "MagickCore/exception-private.h"
     62 #include "MagickCore/image.h"
     63 #include "MagickCore/image-private.h"
     64 #include "MagickCore/list.h"
     65 #include "MagickCore/magick.h"
     66 #include "MagickCore/memory_.h"
     67 #include "MagickCore/pixel-accessor.h"
     68 #include "MagickCore/quantum-private.h"
     69 #include "MagickCore/static.h"
     70 #include "MagickCore/string_.h"
     71 #include "MagickCore/module.h"
     72 #include "MagickCore/utility.h"
     73 #include "MagickCore/utility-private.h"
     74 
     75 typedef struct
     77 {
     78   unsigned Width;
     79   unsigned Height;
     80   unsigned Reserved;
     81 } CUTHeader;
     82 
     83 typedef struct
     84 {
     85   char FileId[2];
     86   unsigned Version;
     87   unsigned Size;
     88   char FileType;
     89   char SubType;
     90   unsigned BoardID;
     91   unsigned GraphicsMode;
     92   unsigned MaxIndex;
     93   unsigned MaxRed;
     94   unsigned MaxGreen;
     95   unsigned MaxBlue;
     96   char PaletteId[20];
     97 } CUTPalHeader;
     98 
     99 
    100 static MagickBooleanType InsertRow(Image *image,ssize_t bpp,unsigned char *p,
    102   ssize_t y,ExceptionInfo *exception)
    103 {
    104   int
    105     bit;
    106 
    107   Quantum
    108     index;
    109 
    110   register Quantum
    111     *q;
    112 
    113   ssize_t
    114     x;
    115 
    116   q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
    117   if (q == (Quantum *) NULL)
    118     return(MagickFalse);
    119   switch (bpp)
    120     {
    121     case 1:  /* Convert bitmap scanline. */
    122       {
    123         for (x=0; x < ((ssize_t) image->columns-7); x+=8)
    124         {
    125           for (bit=0; bit < 8; bit++)
    126           {
    127             index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
    128             SetPixelIndex(image,index,q);
    129             if (index < image->colors)
    130               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    131             q+=GetPixelChannels(image);
    132           }
    133           p++;
    134         }
    135         if ((image->columns % 8) != 0)
    136           {
    137             for (bit=0; bit < (ssize_t) (image->columns % 8); bit++)
    138             {
    139               index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
    140               SetPixelIndex(image,index,q);
    141               if (index < image->colors)
    142                 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    143               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    144               q+=GetPixelChannels(image);
    145             }
    146             p++;
    147           }
    148         break;
    149       }
    150     case 2:  /* Convert PseudoColor scanline. */
    151       {
    152         for (x=0; x < ((ssize_t) image->columns-3); x+=4)
    153         {
    154             index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
    155             SetPixelIndex(image,index,q);
    156             if (index < image->colors)
    157               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    158             q+=GetPixelChannels(image);
    159             index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
    160             SetPixelIndex(image,index,q);
    161             if (index < image->colors)
    162               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    163             q+=GetPixelChannels(image);
    164             index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,exception);
    165             SetPixelIndex(image,index,q);
    166             if (index < image->colors)
    167               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    168             q+=GetPixelChannels(image);
    169             index=ConstrainColormapIndex(image,(*p) & 0x3,exception);
    170             SetPixelIndex(image,index,q);
    171             if (index < image->colors)
    172               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    173             q+=GetPixelChannels(image);
    174             p++;
    175         }
    176        if ((image->columns % 4) != 0)
    177           {
    178             index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
    179             SetPixelIndex(image,index,q);
    180             if (index < image->colors)
    181               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    182             q+=GetPixelChannels(image);
    183             if ((image->columns % 4) > 1)
    184               {
    185                 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
    186                 SetPixelIndex(image,index,q);
    187                 if (index < image->colors)
    188                   SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    189                 q+=GetPixelChannels(image);
    190                 if ((image->columns % 4) > 2)
    191                   {
    192                     index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,
    193                       exception);
    194                     SetPixelIndex(image,index,q);
    195                     if (index < image->colors)
    196                       SetPixelViaPixelInfo(image,image->colormap+(ssize_t)
    197                         index,q);
    198                     q+=GetPixelChannels(image);
    199                   }
    200               }
    201             p++;
    202           }
    203         break;
    204       }
    205 
    206     case 4:  /* Convert PseudoColor scanline. */
    207       {
    208         for (x=0; x < ((ssize_t) image->columns-1); x+=2)
    209           {
    210             index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
    211             SetPixelIndex(image,index,q);
    212             if (index < image->colors)
    213               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    214             q+=GetPixelChannels(image);
    215             index=ConstrainColormapIndex(image,(*p) & 0x0f,exception);
    216             SetPixelIndex(image,index,q);
    217             if (index < image->colors)
    218               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    219             p++;
    220             q+=GetPixelChannels(image);
    221           }
    222         if ((image->columns % 2) != 0)
    223           {
    224             index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
    225             SetPixelIndex(image,index,q);
    226             if (index < image->colors)
    227               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    228             p++;
    229             q+=GetPixelChannels(image);
    230           }
    231         break;
    232       }
    233     case 8: /* Convert PseudoColor scanline. */
    234       {
    235         for (x=0; x < (ssize_t) image->columns; x++)
    236           {
    237             index=ConstrainColormapIndex(image,*p,exception);
    238             SetPixelIndex(image,index,q);
    239             if (index < image->colors)
    240               SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
    241             p++;
    242             q+=GetPixelChannels(image);
    243           }
    244       }
    245       break;
    246 
    247     case 24:     /*  Convert DirectColor scanline.  */
    248       for (x=0; x < (ssize_t) image->columns; x++)
    249         {
    250           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
    251           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
    252           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
    253           q+=GetPixelChannels(image);
    254         }
    255       break;
    256     }
    257   if (!SyncAuthenticPixels(image,exception))
    258     return(MagickFalse);
    259   return(MagickTrue);
    260 }
    261 
    262 /*
    263    Compute the number of colors in Grayed R[i]=G[i]=B[i] image
    264 */
    265 static int GetCutColors(Image *image,ExceptionInfo *exception)
    266 {
    267   Quantum
    268     intensity,
    269     scale_intensity;
    270 
    271   register Quantum
    272     *q;
    273 
    274   ssize_t
    275     x,
    276     y;
    277 
    278   intensity=0;
    279   scale_intensity=ScaleCharToQuantum(16);
    280   for (y=0; y < (ssize_t) image->rows; y++)
    281   {
    282     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
    283     if (q == (Quantum *) NULL)
    284       break;
    285     for (x=0; x < (ssize_t) image->columns; x++)
    286     {
    287       if (intensity < GetPixelRed(image,q))
    288         intensity=GetPixelRed(image,q);
    289       if (intensity >= scale_intensity)
    290         return(255);
    291       q+=GetPixelChannels(image);
    292     }
    293   }
    294   if (intensity < ScaleCharToQuantum(2))
    295     return(2);
    296   if (intensity < ScaleCharToQuantum(16))
    297     return(16);
    298   return((int) intensity);
    299 }
    300 
    301 /*
    303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    304 %                                                                             %
    305 %                                                                             %
    306 %                                                                             %
    307 %   R e a d C U T I m a g e                                                   %
    308 %                                                                             %
    309 %                                                                             %
    310 %                                                                             %
    311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    312 %
    313 %  ReadCUTImage() reads an CUT X image file and returns it.  It
    314 %  allocates the memory necessary for the new Image structure and returns a
    315 %  pointer to the new image.
    316 %
    317 %  The format of the ReadCUTImage method is:
    318 %
    319 %      Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
    320 %
    321 %  A description of each parameter follows:
    322 %
    323 %    o image_info: the image info.
    324 %
    325 %    o exception: return any errors or warnings in this structure.
    326 %
    327 */
    328 static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
    329 {
    330 #define ThrowCUTReaderException(severity,tag) \
    331 { \
    332   if (palette != NULL) \
    333     palette=DestroyImage(palette); \
    334   if (clone_info != NULL) \
    335     clone_info=DestroyImageInfo(clone_info); \
    336   ThrowReaderException(severity,tag); \
    337 }
    338 
    339   Image *image,*palette;
    340   ImageInfo *clone_info;
    341   MagickBooleanType status;
    342 
    343   MagickOffsetType
    344     offset;
    345 
    346   size_t EncodedByte;
    347   unsigned char RunCount,RunValue,RunCountMasked;
    348   CUTHeader  Header;
    349   CUTPalHeader PalHeader;
    350   ssize_t depth;
    351   ssize_t i,j;
    352   ssize_t ldblk;
    353   unsigned char *BImgBuff=NULL,*ptrB;
    354   register Quantum *q;
    355 
    356   /*
    357     Open image file.
    358   */
    359   assert(image_info != (const ImageInfo *) NULL);
    360   assert(image_info->signature == MagickCoreSignature);
    361   if (image_info->debug != MagickFalse)
    362     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    363       image_info->filename);
    364   assert(exception != (ExceptionInfo *) NULL);
    365   assert(exception->signature == MagickCoreSignature);
    366   image=AcquireImage(image_info,exception);
    367   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    368   if (status == MagickFalse)
    369     {
    370       image=DestroyImageList(image);
    371       return((Image *) NULL);
    372     }
    373   /*
    374     Read CUT image.
    375   */
    376   palette=NULL;
    377   clone_info=NULL;
    378   Header.Width=ReadBlobLSBShort(image);
    379   Header.Height=ReadBlobLSBShort(image);
    380   Header.Reserved=ReadBlobLSBShort(image);
    381 
    382   if (Header.Width==0 || Header.Height==0 || Header.Reserved!=0)
    383     CUT_KO:  ThrowCUTReaderException(CorruptImageError,"ImproperImageHeader");
    384 
    385   /*---This code checks first line of image---*/
    386   EncodedByte=ReadBlobLSBShort(image);
    387   RunCount=(unsigned char) ReadBlobByte(image);
    388   RunCountMasked=RunCount & 0x7F;
    389   ldblk=0;
    390   while((int) RunCountMasked!=0)  /*end of line?*/
    391     {
    392       i=1;
    393       if((int) RunCount<0x80) i=(ssize_t) RunCountMasked;
    394       offset=SeekBlob(image,TellBlob(image)+i,SEEK_SET);
    395       if (offset < 0)
    396         ThrowCUTReaderException(CorruptImageError,"ImproperImageHeader");
    397       if(EOFBlob(image) != MagickFalse) goto CUT_KO;  /*wrong data*/
    398       EncodedByte-=i+1;
    399       ldblk+=(ssize_t) RunCountMasked;
    400 
    401       RunCount=(unsigned char) ReadBlobByte(image);
    402       if(EOFBlob(image) != MagickFalse)  goto CUT_KO;  /*wrong data: unexpected eof in line*/
    403       RunCountMasked=RunCount & 0x7F;
    404     }
    405   if(EncodedByte!=1) goto CUT_KO;  /*wrong data: size incorrect*/
    406   i=0;        /*guess a number of bit planes*/
    407   if(ldblk==(int) Header.Width)   i=8;
    408   if(2*ldblk==(int) Header.Width) i=4;
    409   if(8*ldblk==(int) Header.Width) i=1;
    410   if(i==0) goto CUT_KO;    /*wrong data: incorrect bit planes*/
    411   depth=i;
    412 
    413   image->columns=Header.Width;
    414   image->rows=Header.Height;
    415   image->depth=8;
    416   image->colors=(size_t) (GetQuantumRange(1UL*i)+1);
    417 
    418   if (image_info->ping != MagickFalse) goto Finish;
    419   status=SetImageExtent(image,image->columns,image->rows,exception);
    420   if (status == MagickFalse)
    421     return(DestroyImageList(image));
    422 
    423   /* ----- Do something with palette ----- */
    424   if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette;
    425 
    426 
    427   i=(ssize_t) strlen(clone_info->filename);
    428   j=i;
    429   while(--i>0)
    430     {
    431       if(clone_info->filename[i]=='.')
    432         {
    433           break;
    434         }
    435       if(clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' ||
    436          clone_info->filename[i]==':' )
    437         {
    438           i=j;
    439           break;
    440         }
    441     }
    442 
    443   (void) CopyMagickString(clone_info->filename+i,".PAL",(size_t)
    444     (MagickPathExtent-i));
    445   if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL)
    446     {
    447       (void) CopyMagickString(clone_info->filename+i,".pal",(size_t)
    448         (MagickPathExtent-i));
    449       if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL)
    450         {
    451           clone_info->filename[i]='\0';
    452           if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL)
    453             {
    454               clone_info=DestroyImageInfo(clone_info);
    455               clone_info=NULL;
    456               goto NoPalette;
    457             }
    458         }
    459     }
    460 
    461   if( (palette=AcquireImage(clone_info,exception))==NULL ) goto NoPalette;
    462   status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception);
    463   if (status == MagickFalse)
    464     {
    465     ErasePalette:
    466       palette=DestroyImage(palette);
    467       palette=NULL;
    468       goto NoPalette;
    469     }
    470 
    471 
    472   if(palette!=NULL)
    473     {
    474       (void) ReadBlob(palette,2,(unsigned char *) PalHeader.FileId);
    475       if(strncmp(PalHeader.FileId,"AH",2) != 0) goto ErasePalette;
    476       PalHeader.Version=ReadBlobLSBShort(palette);
    477       PalHeader.Size=ReadBlobLSBShort(palette);
    478       PalHeader.FileType=(char) ReadBlobByte(palette);
    479       PalHeader.SubType=(char) ReadBlobByte(palette);
    480       PalHeader.BoardID=ReadBlobLSBShort(palette);
    481       PalHeader.GraphicsMode=ReadBlobLSBShort(palette);
    482       PalHeader.MaxIndex=ReadBlobLSBShort(palette);
    483       PalHeader.MaxRed=ReadBlobLSBShort(palette);
    484       PalHeader.MaxGreen=ReadBlobLSBShort(palette);
    485       PalHeader.MaxBlue=ReadBlobLSBShort(palette);
    486       (void) ReadBlob(palette,20,(unsigned char *) PalHeader.PaletteId);
    487       if (EOFBlob(image))
    488         ThrowCUTReaderException(CorruptImageError,"UnexpectedEndOfFile");
    489 
    490       if(PalHeader.MaxIndex<1) goto ErasePalette;
    491       image->colors=PalHeader.MaxIndex+1;
    492       if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) goto NoMemory;
    493 
    494       if(PalHeader.MaxRed==0) PalHeader.MaxRed=(unsigned int) QuantumRange;  /*avoid division by 0*/
    495       if(PalHeader.MaxGreen==0) PalHeader.MaxGreen=(unsigned int) QuantumRange;
    496       if(PalHeader.MaxBlue==0) PalHeader.MaxBlue=(unsigned int) QuantumRange;
    497 
    498       for(i=0;i<=(int) PalHeader.MaxIndex;i++)
    499         {      /*this may be wrong- I don't know why is palette such strange*/
    500           j=(ssize_t) TellBlob(palette);
    501           if((j % 512)>512-6)
    502             {
    503               j=((j / 512)+1)*512;
    504               offset=SeekBlob(palette,j,SEEK_SET);
    505               if (offset < 0)
    506                 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    507             }
    508           image->colormap[i].red=(Quantum) ReadBlobLSBShort(palette);
    509           if (QuantumRange != (Quantum) PalHeader.MaxRed)
    510             {
    511               image->colormap[i].red=ClampToQuantum(((double)
    512                 image->colormap[i].red*QuantumRange+(PalHeader.MaxRed>>1))/
    513                 PalHeader.MaxRed);
    514             }
    515           image->colormap[i].green=(Quantum) ReadBlobLSBShort(palette);
    516           if (QuantumRange != (Quantum) PalHeader.MaxGreen)
    517             {
    518               image->colormap[i].green=ClampToQuantum
    519                 (((double) image->colormap[i].green*QuantumRange+(PalHeader.MaxGreen>>1))/PalHeader.MaxGreen);
    520             }
    521           image->colormap[i].blue=(Quantum) ReadBlobLSBShort(palette);
    522           if (QuantumRange != (Quantum) PalHeader.MaxBlue)
    523             {
    524               image->colormap[i].blue=ClampToQuantum
    525                 (((double)image->colormap[i].blue*QuantumRange+(PalHeader.MaxBlue>>1))/PalHeader.MaxBlue);
    526             }
    527 
    528         }
    529       if (EOFBlob(image))
    530         ThrowCUTReaderException(CorruptImageError,"UnexpectedEndOfFile");
    531     }
    532 
    533 
    534 
    535  NoPalette:
    536   if(palette==NULL)
    537     {
    538 
    539       image->colors=256;
    540       if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
    541         {
    542         NoMemory:
    543           ThrowCUTReaderException(ResourceLimitError,"MemoryAllocationFailed");
    544             }
    545 
    546       for (i=0; i < (ssize_t)image->colors; i++)
    547         {
    548           image->colormap[i].red=ScaleCharToQuantum((unsigned char) i);
    549           image->colormap[i].green=ScaleCharToQuantum((unsigned char) i);
    550           image->colormap[i].blue=ScaleCharToQuantum((unsigned char) i);
    551         }
    552     }
    553 
    554 
    555   /* ----- Load RLE compressed raster ----- */
    556   BImgBuff=(unsigned char *) AcquireQuantumMemory((size_t) ldblk,
    557     sizeof(*BImgBuff));  /*Ldblk was set in the check phase*/
    558   if(BImgBuff==NULL) goto NoMemory;
    559 
    560   offset=SeekBlob(image,6 /*sizeof(Header)*/,SEEK_SET);
    561   if (offset < 0)
    562     {
    563       if (palette != NULL)
    564         palette=DestroyImage(palette);
    565       if (clone_info != NULL)
    566         clone_info=DestroyImageInfo(clone_info);
    567       BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
    568       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
    569     }
    570   for (i=0; i < (int) Header.Height; i++)
    571   {
    572       EncodedByte=ReadBlobLSBShort(image);
    573 
    574       ptrB=BImgBuff;
    575       j=ldblk;
    576 
    577       RunCount=(unsigned char) ReadBlobByte(image);
    578       RunCountMasked=RunCount & 0x7F;
    579 
    580       while ((int) RunCountMasked != 0)
    581       {
    582           if((ssize_t) RunCountMasked>j)
    583             {    /*Wrong Data*/
    584               RunCountMasked=(unsigned char) j;
    585               if(j==0)
    586                 {
    587                   break;
    588                 }
    589             }
    590 
    591           if((int) RunCount>0x80)
    592             {
    593               RunValue=(unsigned char) ReadBlobByte(image);
    594               (void) memset(ptrB,(int) RunValue,(size_t) RunCountMasked);
    595             }
    596           else {
    597             (void) ReadBlob(image,(size_t) RunCountMasked,ptrB);
    598           }
    599 
    600           ptrB+=(int) RunCountMasked;
    601           j-=(int) RunCountMasked;
    602 
    603           if (EOFBlob(image) != MagickFalse) goto Finish;  /* wrong data: unexpected eof in line */
    604           RunCount=(unsigned char) ReadBlobByte(image);
    605           RunCountMasked=RunCount & 0x7F;
    606         }
    607 
    608       InsertRow(image,depth,BImgBuff,i,exception);
    609     }
    610   (void) SyncImage(image,exception);
    611 
    612 
    613   /*detect monochrome image*/
    614 
    615   if(palette==NULL)
    616     {    /*attempt to detect binary (black&white) images*/
    617       if ((image->storage_class == PseudoClass) &&
    618           (SetImageGray(image,exception) != MagickFalse))
    619         {
    620           if(GetCutColors(image,exception)==2)
    621             {
    622               for (i=0; i < (ssize_t)image->colors; i++)
    623                 {
    624                   register Quantum
    625                     sample;
    626                   sample=ScaleCharToQuantum((unsigned char) i);
    627                   if(image->colormap[i].red!=sample) goto Finish;
    628                   if(image->colormap[i].green!=sample) goto Finish;
    629                   if(image->colormap[i].blue!=sample) goto Finish;
    630                 }
    631 
    632               image->colormap[1].red=image->colormap[1].green=
    633                 image->colormap[1].blue=QuantumRange;
    634               for (i=0; i < (ssize_t)image->rows; i++)
    635                 {
    636                   q=QueueAuthenticPixels(image,0,i,image->columns,1,exception);
    637                   if (q == (Quantum *) NULL)
    638                     break;
    639                   for (j=0; j < (ssize_t)image->columns; j++)
    640                     {
    641                       if (GetPixelRed(image,q) == ScaleCharToQuantum(1))
    642                         {
    643                           SetPixelRed(image,QuantumRange,q);
    644                           SetPixelGreen(image,QuantumRange,q);
    645                           SetPixelBlue(image,QuantumRange,q);
    646                         }
    647                       q+=GetPixelChannels(image);
    648                     }
    649                   if (SyncAuthenticPixels(image,exception) == MagickFalse) goto Finish;
    650                 }
    651             }
    652         }
    653     }
    654 
    655  Finish:
    656   if (BImgBuff != NULL)
    657     BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
    658   if (palette != NULL)
    659     palette=DestroyImage(palette);
    660   if (clone_info != NULL)
    661     clone_info=DestroyImageInfo(clone_info);
    662   if (EOFBlob(image) != MagickFalse)
    663     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
    664       image->filename);
    665   (void) CloseBlob(image);
    666   return(GetFirstImageInList(image));
    667 }
    668 
    669 /*
    671 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    672 %                                                                             %
    673 %                                                                             %
    674 %                                                                             %
    675 %   R e g i s t e r C U T I m a g e                                           %
    676 %                                                                             %
    677 %                                                                             %
    678 %                                                                             %
    679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    680 %
    681 %  RegisterCUTImage() adds attributes for the CUT image format to
    682 %  the list of supported formats.  The attributes include the image format
    683 %  tag, a method to read and/or write the format, whether the format
    684 %  supports the saving of more than one frame to the same file or blob,
    685 %  whether the format supports native in-memory I/O, and a brief
    686 %  description of the format.
    687 %
    688 %  The format of the RegisterCUTImage method is:
    689 %
    690 %      size_t RegisterCUTImage(void)
    691 %
    692 */
    693 ModuleExport size_t RegisterCUTImage(void)
    694 {
    695   MagickInfo
    696     *entry;
    697 
    698   entry=AcquireMagickInfo("CUT","CUT","DR Halo");
    699   entry->decoder=(DecodeImageHandler *) ReadCUTImage;
    700   entry->flags|=CoderDecoderSeekableStreamFlag;
    701   (void) RegisterMagickInfo(entry);
    702   return(MagickImageCoderSignature);
    703 }
    704 
    705 /*
    707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    708 %                                                                             %
    709 %                                                                             %
    710 %                                                                             %
    711 %   U n r e g i s t e r C U T I m a g e                                       %
    712 %                                                                             %
    713 %                                                                             %
    714 %                                                                             %
    715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    716 %
    717 %  UnregisterCUTImage() removes format registrations made by the
    718 %  CUT module from the list of supported formats.
    719 %
    720 %  The format of the UnregisterCUTImage method is:
    721 %
    722 %      UnregisterCUTImage(void)
    723 %
    724 */
    725 ModuleExport void UnregisterCUTImage(void)
    726 {
    727   (void) UnregisterMagickInfo("CUT");
    728 }
    729