Coverage Report

Created: 2026-01-20 07:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/cut.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2025 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
%
5
% This program is covered by multiple licenses, which are described in
6
% Copyright.txt. You should have received a copy of Copyright.txt with this
7
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
8
%
9
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10
%                                                                             %
11
%                                                                             %
12
%                              CCC  U   U  TTTTT                              %
13
%                             C     U   U    T                                %
14
%                             C     U   U    T                                %
15
%                             C     U   U    T                                %
16
%                              CCC   UUU     T                                %
17
%                                                                             %
18
%                                                                             %
19
%                         Read DR Halo Image Format.                          %
20
%                                                                             %
21
%                                                                             %
22
%                              Software Design                                %
23
%                              Jaroslav Fojtik                                %
24
%                              June 2000 - 2007                               %
25
%                                                                             %
26
%                                                                             %
27
%                                                                             %
28
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
29
%
30
%
31
*/
32

33
/*
34
  Include declarations.
35
*/
36
#include "magick/studio.h"
37
#include "magick/analyze.h"
38
#include "magick/blob.h"
39
#include "magick/color.h"
40
#include "magick/colormap.h"
41
#include "magick/magick.h"
42
#include "magick/pixel_cache.h"
43
#include "magick/utility.h"
44
#include "magick/static.h"
45
46
typedef struct
47
{
48
  unsigned Width;
49
  unsigned Height;
50
  unsigned Reserved;
51
}CUTHeader;      /*Dr Halo*/
52
typedef struct
53
{
54
  char FileId[2];
55
  unsigned Version;
56
  unsigned Size;
57
  char FileType;
58
  char SubType;
59
  unsigned BoardID;
60
  unsigned GraphicsMode;
61
  unsigned MaxIndex;
62
  unsigned MaxRed;
63
  unsigned MaxGreen;
64
  unsigned MaxBlue;
65
  char PaletteId[20];
66
}CUTPalHeader;
67
68

69
static void InsertRow(unsigned char *p,long y,Image *image)
70
89.5k
{
71
89.5k
  int bit; long x;
72
89.5k
  register PixelPacket *q;
73
89.5k
  IndexPacket index;
74
89.5k
  register IndexPacket *indexes;
75
76
77
89.5k
  switch (image->depth)
78
89.5k
    {
79
6.51k
    case 1:  /* Convert bitmap scanline. */
80
6.51k
      {
81
6.51k
        q=SetImagePixels(image,0,y,image->columns,1);
82
6.51k
        if (q == (PixelPacket *) NULL)
83
0
          break;
84
6.51k
        indexes=AccessMutableIndexes(image);
85
173k
        for (x=0; x < ((long) image->columns-7); x+=8)
86
166k
          {
87
1.49M
            for (bit=0; bit < 8; bit++)
88
1.33M
              {
89
1.33M
                index=((*p) & (0x80U >> bit) ? 0x01U : 0x00U);
90
1.33M
                indexes[x+bit]=index;
91
1.33M
                *q++=image->colormap[index];
92
1.33M
              }
93
166k
            p++;
94
166k
          }
95
6.51k
        if ((image->columns % 8) != 0)
96
0
          {
97
0
            for (bit=0; bit < (long) (image->columns % 8); bit++)
98
0
              {
99
0
                index=((*p) & (0x80 >> bit) ? 0x01U : 0x00U);
100
0
                indexes[x+bit]=index;
101
0
                *q++=image->colormap[index];
102
0
              }
103
0
            p++;
104
0
          }
105
6.51k
        if (!SyncImagePixels(image))
106
0
          break;
107
        /*            if (image->previous == (Image *) NULL)
108
                      if (QuantumTick(y,image->rows))
109
                      ProgressMonitor(LoadImageText,image->rows-y-1,image->rows);*/
110
6.51k
        break;
111
6.51k
      }
112
6.51k
    case 2:  /* Convert PseudoColor scanline. */
113
0
      {
114
0
        q=SetImagePixels(image,0,y,image->columns,1);
115
0
        if (q == (PixelPacket *) NULL)
116
0
          break;
117
0
        indexes=AccessMutableIndexes(image);
118
0
        for (x=0; x < ((long) image->columns-1); x+=2)
119
0
          {
120
0
            index=(IndexPacket) ((*p >> 6U) & 0x3U);
121
0
            VerifyColormapIndex(image,index);
122
0
            indexes[x]=index;
123
0
            *q++=image->colormap[index];
124
0
            index=(IndexPacket) ((*p >> 4U) & 0x3U);
125
0
            VerifyColormapIndex(image,index);
126
0
            indexes[x]=index;
127
0
            *q++=image->colormap[index];
128
0
            index=(IndexPacket) ((*p >> 2U) & 0x3U);
129
0
            VerifyColormapIndex(image,index);
130
0
            indexes[x]=index;
131
0
            *q++=image->colormap[index];
132
0
            index=(IndexPacket) ((*p) & 0x3U);
133
0
            VerifyColormapIndex(image,index);
134
0
            indexes[x+1]=index;
135
0
            *q++=image->colormap[index];
136
0
            p++;
137
0
          }
138
0
        if ((image->columns % 4) != 0)
139
0
          {
140
0
            index=(IndexPacket) ((*p >> 6U) & 0x3U);
141
0
            VerifyColormapIndex(image,index);
142
0
            indexes[x]=index;
143
0
            *q++=image->colormap[index];
144
0
            if ((image->columns % 4) >= 1)
145
146
0
              {
147
0
                index=(IndexPacket) ((*p >> 4U) & 0x3U);
148
0
                VerifyColormapIndex(image,index);
149
0
                indexes[x]=index;
150
0
                *q++=image->colormap[index];
151
0
                if ((image->columns % 4) >= 2U)
152
153
0
                  {
154
0
                    index=(IndexPacket) ((*p >> 2U) & 0x3U);
155
0
                    VerifyColormapIndex(image,index);
156
0
                    indexes[x]=index;
157
0
                    *q++=image->colormap[index];
158
0
                  }
159
0
              }
160
0
            p++;
161
0
          }
162
0
        if (!SyncImagePixels(image))
163
0
          break;
164
        /*         if (image->previous == (Image *) NULL)
165
                   if (QuantumTick(y,image->rows))
166
                   ProgressMonitor(LoadImageText,image->rows-y-1,image->rows);*/
167
0
        break;
168
0
      }
169
170
33.5k
    case 4:  /* Convert PseudoColor scanline. */
171
33.5k
      {
172
33.5k
        q=SetImagePixels(image,0,y,image->columns,1);
173
33.5k
        if (q == (PixelPacket *) NULL)
174
0
          break;
175
33.5k
        indexes=AccessMutableIndexes(image);
176
11.1M
        for (x=0; x < ((long) image->columns-1); x+=2)
177
11.1M
          {
178
11.1M
            index=(IndexPacket) ((*p >> 4U) & 0xfU);
179
11.1M
            VerifyColormapIndex(image,index);
180
11.1M
            indexes[x]=index;
181
11.1M
            *q++=image->colormap[index];
182
11.1M
            index=(IndexPacket) ((*p) & 0xfU);
183
11.1M
            VerifyColormapIndex(image,index);
184
11.1M
            indexes[x+1]=index;
185
11.1M
            *q++=image->colormap[index];
186
11.1M
            p++;
187
11.1M
          }
188
33.5k
        if ((image->columns % 2) != 0)
189
0
          {
190
0
            index=(IndexPacket) ((*p >> 4U) & 0xfU);
191
0
            VerifyColormapIndex(image,index);
192
0
            indexes[x]=index;
193
0
            *q++=image->colormap[index];
194
0
            p++;
195
0
          }
196
33.5k
        if (!SyncImagePixels(image))
197
0
          break;
198
        /*         if (image->previous == (Image *) NULL)
199
                   if (QuantumTick(y,image->rows))
200
                   ProgressMonitor(LoadImageText,image->rows-y-1,image->rows);*/
201
33.5k
        break;
202
33.5k
      }
203
49.3k
    case 8: /* Convert PseudoColor scanline. */
204
49.3k
      {
205
49.3k
        q=SetImagePixels(image,0,y,image->columns,1);
206
49.3k
        if (q == (PixelPacket *) NULL) break;
207
49.3k
        indexes=AccessMutableIndexes(image);
208
209
53.9M
        for (x=0; x < (long) image->columns; x++)
210
53.9M
          {
211
53.9M
            index=(IndexPacket) (*p);
212
53.9M
            VerifyColormapIndex(image,index);
213
53.9M
            indexes[x]=index;
214
53.9M
            *q++=image->colormap[index];
215
53.9M
            p++;
216
53.9M
          }
217
49.3k
        if (!SyncImagePixels(image))
218
0
          break;
219
        /*           if (image->previous == (Image *) NULL)
220
                     if (QuantumTick(y,image->rows))
221
                     ProgressMonitor(LoadImageText,image->rows-y-1,image->rows);*/
222
49.3k
      }
223
49.3k
      break;
224
225
89.5k
    }
226
89.5k
}
227
228
static unsigned int GetCutColors(Image *image)
229
76
{
230
76
  unsigned long
231
76
    x,
232
76
    y;
233
234
76
  PixelPacket
235
76
    *q;
236
237
76
  Quantum
238
76
    MaxColor,
239
76
    ScaleCharToQuantum16;
240
241
  /* Compute the number of colors in Grayed R[i]=G[i]=B[i] image */
242
76
  ScaleCharToQuantum16=ScaleCharToQuantum(16U);
243
76
  MaxColor=0U;
244
12.0k
  for (y=0; y < image->rows; y++)
245
11.9k
    {
246
247
11.9k
      q=SetImagePixels(image,0,y,image->columns,1);
248
11.9k
      if (q == (PixelPacket *) NULL)
249
0
          break;
250
2.21M
      for (x=image->columns; x != 0; x--)
251
2.19M
        {
252
2.19M
          if (MaxColor < q->red)
253
88
            MaxColor=q->red;
254
2.19M
          if (MaxColor >= ScaleCharToQuantum16)
255
10
            return(255U);
256
2.19M
          q++;
257
2.19M
        }
258
11.9k
    }
259
66
  if (MaxColor < ScaleCharToQuantum(2))
260
49
    MaxColor=2U;
261
17
  else if (MaxColor < ScaleCharToQuantum(16U))
262
17
    MaxColor=16U;
263
66
  return (MaxColor);
264
76
}
265

266
/*
267
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268
%                                                                             %
269
%                                                                             %
270
%                                                                             %
271
%   R e a d C U T I m a g e                                                   %
272
%                                                                             %
273
%                                                                             %
274
%                                                                             %
275
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276
%
277
%  Method ReadCUTImage reads an CUT X image file and returns it.  It
278
%  allocates the memory necessary for the new Image structure and returns a
279
%  pointer to the new image.
280
%
281
%  The format of the ReadCUTImage method is:
282
%
283
%      Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
284
%
285
%  A description of each parameter follows:
286
%
287
%    o image:  Method ReadCUTImage returns a pointer to the image after
288
%      reading. A null image is returned if there is a memory shortage or if
289
%      the image cannot be read.
290
%
291
%    o image_info: Specifies a pointer to a ImageInfo structure.
292
%
293
%    o exception: return any errors or warnings in this structure.
294
%
295
%
296
*/
297
570
#define ThrowCUTReaderException(code_,reason_,image_) \
298
570
{ \
299
570
  if (palette != (Image *) NULL)              \
300
570
    DestroyImage(palette);                    \
301
570
  if (clone_info != (ImageInfo *) NULL)       \
302
570
    DestroyImageInfo(clone_info);             \
303
570
  ThrowReaderException(code_,reason_,image_); \
304
0
}
305
static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
306
639
{
307
639
  Image *image,*palette = (Image *) NULL;
308
639
  ImageInfo *clone_info = (ImageInfo *) NULL;
309
639
  unsigned int status;
310
639
  unsigned long EncodedByte;
311
639
  unsigned char RunCount,RunValue,RunCountMasked;
312
639
  CUTHeader  Header;
313
639
  CUTPalHeader PalHeader;
314
639
  long i,j;
315
639
  long ldblk;
316
639
  unsigned char *BImgBuff=NULL,*ptrB;
317
639
  PixelPacket *q;
318
319
  /*
320
    Open image file.
321
  */
322
639
  assert(image_info != (const ImageInfo *) NULL);
323
639
  assert(image_info->signature == MagickSignature);
324
639
  assert(exception != (ExceptionInfo *) NULL);
325
639
  assert(exception->signature == MagickSignature);
326
639
  image=AllocateImage(image_info);
327
639
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
328
639
  if (status == False)
329
639
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
330
  /*
331
    Read CUT image.
332
  */
333
639
  Header.Width=ReadBlobLSBShort(image);
334
639
  Header.Height=ReadBlobLSBShort(image);
335
639
  Header.Reserved=ReadBlobLSBShort(image);
336
337
639
  if (Header.Width==0 || Header.Height==0 || Header.Reserved!=0 ||
338
596
      (Header.Width > INT_MAX) || (Header.Height > INT_MAX) )
339
596
  CUT_KO:  ThrowCUTReaderException(CorruptImageError,ImproperImageHeader,image);
340
341
  /*---This code checks first line of image---*/
342
596
  EncodedByte=ReadBlobLSBShort(image);
343
596
  RunCount=ReadBlobByte(image);
344
596
  RunCountMasked=RunCount & 0x7F;
345
596
  ldblk=0;
346
1.20M
  while (RunCountMasked != 0)  /*end of line?*/
347
1.20M
    {
348
1.20M
      i=1;
349
1.20M
      if (RunCount<0x80) i=RunCountMasked;
350
1.20M
      (void) SeekBlob(image,TellBlob(image)+i,SEEK_SET);
351
1.20M
      if (EOFBlob(image)) goto CUT_KO;  /*wrong data*/
352
1.20M
      EncodedByte-=i+1;
353
1.20M
      ldblk+=RunCountMasked;
354
355
1.20M
      RunCount=ReadBlobByte(image);
356
1.20M
      if (EOFBlob(image))  goto CUT_KO;  /*wrong data: unexpected eof in line*/
357
1.20M
      RunCountMasked=RunCount & 0x7F;
358
1.20M
    }
359
512
  if (EncodedByte!=1) goto CUT_KO;  /*wrong data: size incorrect*/
360
476
  i=0;        /*guess a number of bit planes*/
361
476
  if (ldblk==(int) Header.Width)   i=8;
362
476
  if (2*ldblk==(int) Header.Width) i=4;
363
476
  if (8*ldblk==(int) Header.Width) i=1;
364
476
  if (i==0) goto CUT_KO;    /*wrong data: incorrect bit planes*/
365
366
426
  image->columns=Header.Width;
367
426
  image->rows=Header.Height;
368
426
  image->depth=i;
369
426
  image->colors=1l >> i;
370
371
  /* If ping is true, then only set image size and colors without reading any image data. */
372
426
  if (image_info->ping) goto Finish;
373
374
426
  if (CheckImagePixelLimits(image, exception) != MagickPass)
375
400
    ThrowCUTReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
376
377
  /* ----- Do something with palette ----- */
378
400
  if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette;
379
380
400
  i=(long) strlen(clone_info->filename);
381
400
  j=i;
382
400
  while (--i>0)
383
0
    {
384
0
      if (clone_info->filename[i]=='.')
385
0
        {
386
0
          break;
387
0
        }
388
0
      if (clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' ||
389
0
          clone_info->filename[i]==':' )
390
0
        {
391
0
          i=j;
392
0
          break;
393
0
        }
394
0
    }
395
396
400
  if (i <= 0)
397
400
    goto NoPalette;
398
399
0
  (void) strlcpy(clone_info->filename+i,".PAL",sizeof(clone_info->filename)-i);
400
0
  if ((clone_info->file=fopen(clone_info->filename,"rb"))==NULL)
401
0
    {
402
0
      (void) strlcpy(clone_info->filename+i,".pal",sizeof(clone_info->filename)-i);
403
0
      if ((clone_info->file=fopen(clone_info->filename,"rb"))==NULL)
404
0
        {
405
0
          clone_info->filename[i]=0;
406
0
          if ((clone_info->file=fopen(clone_info->filename,"rb"))==NULL)
407
0
            {
408
0
              DestroyImageInfo(clone_info);
409
0
              clone_info=NULL;
410
0
              goto NoPalette;
411
0
            }
412
0
        }
413
0
    }
414
415
0
  if ( (palette=AllocateImage(clone_info))==NULL ) goto NoPalette;
416
0
  status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception);
417
0
  if (status == False)
418
0
    {
419
0
    ErasePalette:
420
0
      DestroyImage(palette);
421
0
      palette=NULL;
422
0
      goto NoPalette;
423
0
    }
424
425
426
0
  if (palette!=NULL)
427
0
    {
428
0
      (void) ReadBlob(palette,2,PalHeader.FileId);
429
0
      if (strncmp(PalHeader.FileId,"AH",2)) goto ErasePalette;
430
0
      PalHeader.Version=ReadBlobLSBShort(palette);
431
0
      PalHeader.Size=ReadBlobLSBShort(palette);
432
0
      PalHeader.FileType=ReadBlobByte(palette);
433
0
      PalHeader.SubType=ReadBlobByte(palette);
434
0
      PalHeader.BoardID=ReadBlobLSBShort(palette);
435
0
      PalHeader.GraphicsMode=ReadBlobLSBShort(palette);
436
0
      PalHeader.MaxIndex=ReadBlobLSBShort(palette);
437
0
      PalHeader.MaxRed=ReadBlobLSBShort(palette);
438
0
      PalHeader.MaxGreen=ReadBlobLSBShort(palette);
439
0
      PalHeader.MaxBlue=ReadBlobLSBShort(palette);
440
0
      (void) ReadBlob(palette,20,PalHeader.PaletteId);
441
442
0
      if (EOFBlob(image))
443
0
        ThrowCUTReaderException(CorruptImageError,UnexpectedEndOfFile,image);
444
445
0
      if (PalHeader.MaxIndex<1) goto ErasePalette;
446
0
      image->colors=PalHeader.MaxIndex+1;
447
0
      if (!AllocateImageColormap(image,image->colors)) goto NoMemory;
448
449
0
      if (PalHeader.MaxRed==0) PalHeader.MaxRed=MaxRGB;  /*avoid division by 0*/
450
0
      if (PalHeader.MaxGreen==0) PalHeader.MaxGreen=MaxRGB;
451
0
      if (PalHeader.MaxBlue==0) PalHeader.MaxBlue=MaxRGB;
452
453
0
      for (i=0;i<=(int) PalHeader.MaxIndex;i++)
454
0
        {
455
          /*this may be wrong- I don't know why is palette such strange*/
456
0
          j=(long) TellBlob(palette);
457
0
          if ((j % 512)>512-6)
458
0
            {
459
0
              j=((j / 512)+1)*512;
460
0
              (void) SeekBlob(palette,j,SEEK_SET);
461
0
            }
462
0
          image->colormap[i].red=ReadBlobLSBShort(palette);
463
0
          if (MaxRGB!=PalHeader.MaxRed)
464
0
            {
465
0
              image->colormap[i].red=(Quantum)
466
0
                (((double)image->colormap[i].red*MaxRGB+(PalHeader.MaxRed>>1))/PalHeader.MaxRed+0.5);
467
0
            }
468
0
          image->colormap[i].green=ReadBlobLSBShort(palette);
469
0
          if (MaxRGB!=PalHeader.MaxGreen)
470
0
            {
471
0
              image->colormap[i].green=(Quantum)
472
0
                (((double)image->colormap[i].green*MaxRGB+(PalHeader.MaxGreen>>1))/PalHeader.MaxGreen+0.5);
473
0
            }
474
0
          image->colormap[i].blue=ReadBlobLSBShort(palette);
475
0
          if (MaxRGB!=PalHeader.MaxBlue)
476
0
            {
477
0
              image->colormap[i].blue=(Quantum)
478
0
                (((double)image->colormap[i].blue*MaxRGB+(PalHeader.MaxBlue>>1))/PalHeader.MaxBlue+0.5);
479
0
            }
480
481
0
        }
482
0
      if (EOFBlob(image))
483
0
        ThrowCUTReaderException(CorruptImageError,UnexpectedEndOfFile,image);
484
0
    }
485
486
487
488
400
 NoPalette:
489
400
  if (palette==NULL)
490
400
    {
491
492
400
      image->colors=256;
493
400
      if (!AllocateImageColormap(image,image->colors))
494
0
        {
495
0
        NoMemory:
496
0
          if (clone_info != NULL)
497
0
            {
498
0
              DestroyImageInfo(clone_info);
499
0
              clone_info=(ImageInfo *) NULL;
500
0
            }
501
0
          ThrowCUTReaderException(ResourceLimitError,MemoryAllocationFailed,image);
502
0
        }
503
504
102k
      for (i=0; i < (long)image->colors; i++)
505
102k
        {
506
102k
          image->colormap[i].red=ScaleCharToQuantum(i);
507
102k
          image->colormap[i].green=ScaleCharToQuantum(i);
508
102k
          image->colormap[i].blue=ScaleCharToQuantum(i);
509
102k
        }
510
400
    }
511
512
513
  /* ----- Load RLE compressed raster ----- */
514
400
  BImgBuff=MagickAllocateResourceLimitedMemory(unsigned char *,(size_t) (ldblk));  /*Ldblk was set in the check phase*/
515
400
  if (BImgBuff==NULL) goto NoMemory;
516
517
400
  (void) SeekBlob(image,6 /*sizeof(Header)*/,SEEK_SET);
518
89.9k
  for (i=0;i<(int) Header.Height;i++)
519
89.8k
    {
520
89.8k
      EncodedByte=ReadBlobLSBShort(image);
521
522
89.8k
      ptrB=BImgBuff;
523
89.8k
      j=ldblk;
524
525
89.8k
      RunCount=ReadBlobByte(image);
526
89.8k
      RunCountMasked=RunCount & 0x7F;
527
528
1.87M
      while (RunCountMasked!=0)
529
1.85M
        {
530
1.85M
          if (RunCountMasked>j)
531
117k
            {    /*Wrong Data*/
532
117k
              RunCountMasked=(unsigned char) j;
533
117k
              if (j==0)
534
60.9k
                {
535
60.9k
                  break;
536
60.9k
                }
537
117k
            }
538
539
1.78M
          if (RunCount>0x80)
540
1.19M
            {
541
1.19M
              RunValue=ReadBlobByte(image);
542
1.19M
              (void) memset(ptrB,RunValue,RunCountMasked);
543
1.19M
            }
544
591k
          else {
545
591k
            (void) ReadBlob(image,RunCountMasked,ptrB);
546
591k
          }
547
548
1.78M
          ptrB+=RunCountMasked;
549
1.78M
          j-=RunCountMasked;
550
551
1.78M
          if (EOFBlob(image)) goto Finish;  /* wrong data: unexpected eof in line */
552
1.78M
          RunCount=ReadBlobByte(image);
553
1.78M
          RunCountMasked=RunCount & 0x7F;
554
1.78M
        }
555
556
89.5k
      InsertRow(BImgBuff,i,image);
557
89.5k
    }
558
559
560
  /*detect monochrome image*/
561
562
76
  if (palette==NULL)
563
76
    {    /*attempt to detect binary (black&white) images*/
564
76
      if ((image->storage_class == PseudoClass) && IsGrayImage(image,&image->exception))
565
76
        {
566
76
          if (GetCutColors(image)==2)
567
49
            {
568
12.5k
              for (i=0; i < (long)image->colors; i++)
569
12.5k
                {
570
12.5k
                  register Quantum
571
12.5k
                    sample;
572
12.5k
                  sample=ScaleCharToQuantum(i);
573
12.5k
                  if (image->colormap[i].red!=sample) goto Finish;
574
12.5k
                  if (image->colormap[i].green!=sample) goto Finish;
575
12.5k
                  if (image->colormap[i].blue!=sample) goto Finish;
576
12.5k
                }
577
578
49
              image->colormap[1].red=image->colormap[1].green=image->colormap[1].blue=MaxRGB;
579
6.81k
              for (i=0; i < (long)image->rows; i++)
580
6.77k
                {
581
6.77k
                  q=SetImagePixels(image,0,i,image->columns,1);
582
6.77k
                  if (q == (PixelPacket *) NULL)
583
0
                    break;
584
1.41M
                  for (j=0; j < (long)image->columns; j++)
585
1.41M
                    {
586
1.41M
                      if (q->red==ScaleCharToQuantum(1))
587
949k
                        {
588
949k
                          q->red=q->green=q->blue=MaxRGB;
589
949k
                        }
590
1.41M
                      q++;
591
1.41M
                    }
592
6.77k
                  if (!SyncImagePixels(image)) goto Finish;
593
6.77k
                }
594
49
            }
595
76
        }
596
76
    }
597
598
400
 Finish:
599
400
  if (BImgBuff!=NULL) MagickFreeResourceLimitedMemory(unsigned char *,BImgBuff);
600
400
  if (palette!=NULL)
601
0
    {
602
0
      DestroyImage(palette);
603
0
      palette=(Image *) NULL;
604
0
    }
605
400
  if (clone_info!=NULL)
606
400
    {
607
400
      DestroyImageInfo(clone_info);
608
400
      clone_info=(ImageInfo *) NULL;
609
400
    }
610
400
  if (EOFBlob(image))
611
331
    ThrowCUTReaderException(CorruptImageError,UnexpectedEndOfFile,image);
612
69
  CloseBlob(image);
613
69
  StopTimer(&image->timer);
614
69
  return(image);
615
400
}
616

617
/*
618
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619
%                                                                             %
620
%                                                                             %
621
%                                                                             %
622
%   R e g i s t e r C U T I m a g e                                           %
623
%                                                                             %
624
%                                                                             %
625
%                                                                             %
626
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627
%
628
%  Method RegisterCUTImage adds attributes for the CUT image format to
629
%  the list of supported formats.  The attributes include the image format
630
%  tag, a method to read and/or write the format, whether the format
631
%  supports the saving of more than one frame to the same file or blob,
632
%  whether the format supports native in-memory I/O, and a brief
633
%  description of the format.
634
%
635
%  The format of the RegisterCUTImage method is:
636
%
637
%      RegisterCUTImage(void)
638
%
639
*/
640
ModuleExport void RegisterCUTImage(void)
641
1
{
642
1
  MagickInfo
643
1
    *entry;
644
645
1
  entry=SetMagickInfo("CUT");
646
1
  entry->decoder=(DecoderHandler) ReadCUTImage;
647
1
  entry->seekable_stream=True;
648
1
  entry->description="DR Halo";
649
1
  entry->module="CUT";
650
1
  (void) RegisterMagickInfo(entry);
651
1
}
652

653
/*
654
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
655
%                                                                             %
656
%                                                                             %
657
%                                                                             %
658
%   U n r e g i s t e r C U T I m a g e                                       %
659
%                                                                             %
660
%                                                                             %
661
%                                                                             %
662
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
663
%
664
%  Method UnregisterCUTImage removes format registrations made by the
665
%  CUT module from the list of supported formats.
666
%
667
%  The format of the UnregisterCUTImage method is:
668
%
669
%      UnregisterCUTImage(void)
670
%
671
*/
672
ModuleExport void UnregisterCUTImage(void)
673
0
{
674
0
  (void) UnregisterMagickInfo("CUT");
675
0
}