Coverage Report

Created: 2026-06-30 07:12

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