Coverage Report

Created: 2026-07-25 07:06

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-2026 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
95.0k
{
71
95.0k
  int bit; long x;
72
95.0k
  register PixelPacket *q;
73
95.0k
  IndexPacket index;
74
95.0k
  register IndexPacket *indexes;
75
95.0k
  MagickPassFail status = MagickPass;
76
77
95.0k
  switch (image->depth)
78
95.0k
    {
79
5.55k
    case 1:  /* Convert bitmap scanline. */
80
5.55k
      {
81
5.55k
        q=SetImagePixels(image,0,y,image->columns,1);
82
5.55k
        if (q == (PixelPacket *) NULL)
83
0
          break;
84
5.55k
        indexes=AccessMutableIndexes(image);
85
285k
        for (x=0; x < ((long) image->columns-7); x+=8)
86
279k
          {
87
2.51M
            for (bit=0; bit < 8; bit++)
88
2.23M
              {
89
2.23M
                index=((*p) & (0x80U >> bit) ? 0x01U : 0x00U);
90
2.23M
                indexes[x+bit]=index;
91
2.23M
                *q++=image->colormap[index];
92
2.23M
              }
93
279k
            p++;
94
279k
          }
95
5.55k
        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
5.55k
        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
5.55k
        break;
111
5.55k
      }
112
5.55k
    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(status,image,index);
122
0
            indexes[x]=index;
123
0
            *q++=image->colormap[index];
124
0
            index=(IndexPacket) ((*p >> 4U) & 0x3U);
125
0
            VerifyColormapIndex(status,image,index);
126
0
            indexes[x]=index;
127
0
            *q++=image->colormap[index];
128
0
            index=(IndexPacket) ((*p >> 2U) & 0x3U);
129
0
            VerifyColormapIndex(status,image,index);
130
0
            indexes[x]=index;
131
0
            *q++=image->colormap[index];
132
0
            index=(IndexPacket) ((*p) & 0x3U);
133
0
            VerifyColormapIndex(status,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(status,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(status,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(status,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
28.9k
    case 4:  /* Convert PseudoColor scanline. */
171
28.9k
      {
172
28.9k
        q=SetImagePixels(image,0,y,image->columns,1);
173
28.9k
        if (q == (PixelPacket *) NULL)
174
0
          break;
175
28.9k
        indexes=AccessMutableIndexes(image);
176
5.72M
        for (x=0; x < ((long) image->columns-1); x+=2)
177
5.69M
          {
178
5.69M
            index=(IndexPacket) ((*p >> 4U) & 0xfU);
179
5.69M
            VerifyColormapIndex(status,image,index);
180
5.69M
            indexes[x]=index;
181
5.69M
            *q++=image->colormap[index];
182
5.69M
            index=(IndexPacket) ((*p) & 0xfU);
183
5.69M
            VerifyColormapIndex(status,image,index);
184
5.69M
            indexes[x+1]=index;
185
5.69M
            *q++=image->colormap[index];
186
5.69M
            p++;
187
5.69M
          }
188
28.9k
        if ((image->columns % 2) != 0)
189
0
          {
190
0
            index=(IndexPacket) ((*p >> 4U) & 0xfU);
191
0
            VerifyColormapIndex(status,image,index);
192
0
            indexes[x]=index;
193
0
            *q++=image->colormap[index];
194
0
            p++;
195
0
          }
196
28.9k
        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
28.9k
        break;
202
28.9k
      }
203
60.5k
    case 8: /* Convert PseudoColor scanline. */
204
60.5k
      {
205
60.5k
        q=SetImagePixels(image,0,y,image->columns,1);
206
60.5k
        if (q == (PixelPacket *) NULL) break;
207
60.5k
        indexes=AccessMutableIndexes(image);
208
209
69.2M
        for (x=0; x < (long) image->columns; x++)
210
69.1M
          {
211
69.1M
            index=(IndexPacket) (*p);
212
69.1M
            VerifyColormapIndex(status,image,index);
213
69.1M
            indexes[x]=index;
214
69.1M
            *q++=image->colormap[index];
215
69.1M
            p++;
216
69.1M
          }
217
60.5k
        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
60.5k
      }
223
60.5k
      break;
224
225
95.0k
    }
226
95.0k
}
227
228
static unsigned int GetCutColors(Image *image)
229
82
{
230
82
  unsigned long
231
82
    x,
232
82
    y;
233
234
82
  PixelPacket
235
82
    *q;
236
237
82
  Quantum
238
82
    MaxColor,
239
82
    ScaleCharToQuantum16;
240
241
  /* Compute the number of colors in Grayed R[i]=G[i]=B[i] image */
242
82
  ScaleCharToQuantum16=ScaleCharToQuantum(16U);
243
82
  MaxColor=0U;
244
9.27k
  for (y=0; y < image->rows; y++)
245
9.20k
    {
246
247
9.20k
      q=SetImagePixels(image,0,y,image->columns,1);
248
9.20k
      if (q == (PixelPacket *) NULL)
249
0
          break;
250
1.09M
      for (x=image->columns; x != 0; x--)
251
1.08M
        {
252
1.08M
          if (MaxColor < q->red)
253
89
            MaxColor=q->red;
254
1.08M
          if (MaxColor >= ScaleCharToQuantum16)
255
12
            return(255U);
256
1.08M
          q++;
257
1.08M
        }
258
9.20k
    }
259
70
  if (MaxColor < ScaleCharToQuantum(2))
260
52
    MaxColor=2U;
261
18
  else if (MaxColor < ScaleCharToQuantum(16U))
262
18
    MaxColor=16U;
263
70
  return (MaxColor);
264
82
}
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
617
#define ThrowCUTReaderException(code_,reason_,image_) \
298
617
{ \
299
617
  if (palette != (Image *) NULL)              \
300
617
    DestroyImage(palette);                    \
301
617
  if (clone_info != (ImageInfo *) NULL)       \
302
617
    DestroyImageInfo(clone_info);             \
303
617
  ThrowReaderException(code_,reason_,image_); \
304
0
}
305
static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
306
693
{
307
693
  Image *image,*palette = (Image *) NULL;
308
693
  ImageInfo *clone_info = (ImageInfo *) NULL;
309
693
  unsigned int status;
310
693
  unsigned long EncodedByte;
311
693
  unsigned char RunCount,RunValue,RunCountMasked;
312
693
  CUTHeader  Header;
313
693
  CUTPalHeader PalHeader;
314
693
  long i,j;
315
693
  long ldblk;
316
693
  unsigned char *BImgBuff=NULL,*ptrB;
317
693
  PixelPacket *q;
318
319
  /*
320
    Open image file.
321
  */
322
693
  assert(image_info != (const ImageInfo *) NULL);
323
693
  assert(image_info->signature == MagickSignature);
324
693
  assert(exception != (ExceptionInfo *) NULL);
325
693
  assert(exception->signature == MagickSignature);
326
693
  image=AllocateImage(image_info);
327
693
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
328
693
  if (status == False)
329
693
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
330
  /*
331
    Read CUT image.
332
  */
333
693
  Header.Width=ReadBlobLSBShort(image);
334
693
  Header.Height=ReadBlobLSBShort(image);
335
693
  Header.Reserved=ReadBlobLSBShort(image);
336
337
693
  if (Header.Width==0 || Header.Height==0 || Header.Reserved!=0 ||
338
649
      (Header.Width > INT_MAX) || (Header.Height > INT_MAX) )
339
649
  CUT_KO:  ThrowCUTReaderException(CorruptImageError,ImproperImageHeader,image);
340
341
  /*---This code checks first line of image---*/
342
649
  EncodedByte=ReadBlobLSBShort(image);
343
649
  RunCount=ReadBlobByte(image);
344
649
  RunCountMasked=RunCount & 0x7F;
345
649
  ldblk=0;
346
1.06M
  while (RunCountMasked != 0)  /*end of line?*/
347
1.06M
    {
348
1.06M
      i=1;
349
1.06M
      if (RunCount<0x80) i=RunCountMasked;
350
1.06M
      (void) SeekBlob(image,TellBlob(image)+i,SEEK_SET);
351
1.06M
      if (EOFBlob(image)) goto CUT_KO;  /*wrong data*/
352
1.06M
      EncodedByte-=i+1;
353
1.06M
      ldblk+=RunCountMasked;
354
355
1.06M
      RunCount=ReadBlobByte(image);
356
1.06M
      if (EOFBlob(image))  goto CUT_KO;  /*wrong data: unexpected eof in line*/
357
1.06M
      RunCountMasked=RunCount & 0x7F;
358
1.06M
    }
359
566
  if (EncodedByte!=1) goto CUT_KO;  /*wrong data: size incorrect*/
360
525
  i=0;        /*guess a number of bit planes*/
361
525
  if (ldblk==(int) Header.Width)   i=8;
362
525
  if (2*ldblk==(int) Header.Width) i=4;
363
525
  if (8*ldblk==(int) Header.Width) i=1;
364
525
  if (i==0) goto CUT_KO;    /*wrong data: incorrect bit planes*/
365
366
475
  image->columns=Header.Width;
367
475
  image->rows=Header.Height;
368
475
  image->depth=i;
369
475
  image->colors=1l >> i;
370
371
  /* If ping is true, then only set image size and colors without reading any image data. */
372
475
  if (image_info->ping) goto Finish;
373
374
475
  if (CheckImagePixelLimits(image, exception) != MagickPass)
375
447
    ThrowCUTReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
376
377
  /* ----- Do something with palette ----- */
378
447
  if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette;
379
380
447
  i=(long) strlen(clone_info->filename);
381
447
  j=i;
382
447
  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
447
  if (i <= 0)
397
447
    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
447
 NoPalette:
489
447
  if (palette==NULL)
490
447
    {
491
492
447
      image->colors=256;
493
447
      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
114k
      for (i=0; i < (long)image->colors; i++)
505
114k
        {
506
114k
          image->colormap[i].red=ScaleCharToQuantum(i);
507
114k
          image->colormap[i].green=ScaleCharToQuantum(i);
508
114k
          image->colormap[i].blue=ScaleCharToQuantum(i);
509
114k
        }
510
447
    }
511
512
513
  /* ----- Load RLE compressed raster ----- */
514
447
  BImgBuff=MagickAllocateResourceLimitedMemory(unsigned char *,(size_t) (ldblk));  /*Ldblk was set in the check phase*/
515
447
  if (BImgBuff==NULL) goto NoMemory;
516
517
447
  (void) SeekBlob(image,6 /*sizeof(Header)*/,SEEK_SET);
518
95.5k
  for (i=0;i<(int) Header.Height;i++)
519
95.4k
    {
520
95.4k
      EncodedByte=ReadBlobLSBShort(image);
521
522
95.4k
      ptrB=BImgBuff;
523
95.4k
      j=ldblk;
524
525
95.4k
      RunCount=ReadBlobByte(image);
526
95.4k
      RunCountMasked=RunCount & 0x7F;
527
528
2.99M
      while (RunCountMasked!=0)
529
2.96M
        {
530
2.96M
          if (RunCountMasked>j)
531
126k
            {    /*Wrong Data*/
532
126k
              RunCountMasked=(unsigned char) j;
533
126k
              if (j==0)
534
65.8k
                {
535
65.8k
                  break;
536
65.8k
                }
537
126k
            }
538
539
2.90M
          if (RunCount>0x80)
540
2.24M
            {
541
2.24M
              RunValue=ReadBlobByte(image);
542
2.24M
              (void) memset(ptrB,RunValue,RunCountMasked);
543
2.24M
            }
544
661k
          else {
545
661k
            (void) ReadBlob(image,RunCountMasked,ptrB);
546
661k
          }
547
548
2.90M
          ptrB+=RunCountMasked;
549
2.90M
          j-=RunCountMasked;
550
551
2.90M
          if (EOFBlob(image)) goto Finish;  /* wrong data: unexpected eof in line */
552
2.90M
          RunCount=ReadBlobByte(image);
553
2.90M
          RunCountMasked=RunCount & 0x7F;
554
2.90M
        }
555
556
95.0k
      InsertRow(BImgBuff,i,image);
557
95.0k
    }
558
559
560
  /*detect monochrome image*/
561
562
82
  if (palette==NULL)
563
82
    {    /*attempt to detect binary (black&white) images*/
564
82
      if ((image->storage_class == PseudoClass) && IsGrayImage(image,&image->exception))
565
82
        {
566
82
          if (GetCutColors(image)==2)
567
52
            {
568
13.3k
              for (i=0; i < (long)image->colors; i++)
569
13.3k
                {
570
13.3k
                  register Quantum
571
13.3k
                    sample;
572
13.3k
                  sample=ScaleCharToQuantum(i);
573
13.3k
                  if (image->colormap[i].red!=sample) goto Finish;
574
13.3k
                  if (image->colormap[i].green!=sample) goto Finish;
575
13.3k
                  if (image->colormap[i].blue!=sample) goto Finish;
576
13.3k
                }
577
578
52
              image->colormap[1].red=image->colormap[1].green=image->colormap[1].blue=MaxRGB;
579
5.03k
              for (i=0; i < (long)image->rows; i++)
580
4.98k
                {
581
4.98k
                  q=SetImagePixels(image,0,i,image->columns,1);
582
4.98k
                  if (q == (PixelPacket *) NULL)
583
0
                    break;
584
560k
                  for (j=0; j < (long)image->columns; j++)
585
555k
                    {
586
555k
                      if (q->red==ScaleCharToQuantum(1))
587
116k
                        {
588
116k
                          q->red=q->green=q->blue=MaxRGB;
589
116k
                        }
590
555k
                      q++;
591
555k
                    }
592
4.98k
                  if (!SyncImagePixels(image)) goto Finish;
593
4.98k
                }
594
52
            }
595
82
        }
596
82
    }
597
598
447
 Finish:
599
447
  if (BImgBuff!=NULL) MagickFreeResourceLimitedMemory(unsigned char *,BImgBuff);
600
447
  if (palette!=NULL)
601
0
    {
602
0
      DestroyImage(palette);
603
0
      palette=(Image *) NULL;
604
0
    }
605
447
  if (clone_info!=NULL)
606
447
    {
607
447
      DestroyImageInfo(clone_info);
608
447
      clone_info=(ImageInfo *) NULL;
609
447
    }
610
447
  if (EOFBlob(image))
611
371
    ThrowCUTReaderException(CorruptImageError,UnexpectedEndOfFile,image);
612
76
  CloseBlob(image);
613
76
  StopTimer(&image->timer);
614
76
  return(image);
615
447
}
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
}