Coverage Report

Created: 2025-10-12 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/rle.c
Line
Count
Source
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                                                                             %
6
%                            RRRR   L      EEEEE                              %
7
%                            R   R  L      E                                  %
8
%                            RRRR   L      EEE                                %
9
%                            R R    L      E                                  %
10
%                            R  R   LLLLL  EEEEE                              %
11
%                                                                             %
12
%                                                                             %
13
%                          Read URT RLE Image Format                          %
14
%                                                                             %
15
%                              Software Design                                %
16
%                                   Cristy                                    %
17
%                                 July 1992                                   %
18
%                                                                             %
19
%                                                                             %
20
%  Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization         %
21
%  dedicated to making software imaging solutions freely available.           %
22
%                                                                             %
23
%  You may not use this file except in compliance with the License.  You may  %
24
%  obtain a copy of the License at                                            %
25
%                                                                             %
26
%    https://imagemagick.org/script/license.php                               %
27
%                                                                             %
28
%  Unless required by applicable law or agreed to in writing, software        %
29
%  distributed under the License is distributed on an "AS IS" BASIS,          %
30
%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31
%  See the License for the specific language governing permissions and        %
32
%  limitations under the License.                                             %
33
%                                                                             %
34
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35
%
36
%
37
*/
38

39
/*
40
  Include declarations.
41
*/
42
#include "MagickCore/studio.h"
43
#include "MagickCore/blob.h"
44
#include "MagickCore/blob-private.h"
45
#include "MagickCore/cache.h"
46
#include "MagickCore/colormap.h"
47
#include "MagickCore/colormap-private.h"
48
#include "MagickCore/exception.h"
49
#include "MagickCore/exception-private.h"
50
#include "MagickCore/image.h"
51
#include "MagickCore/image-private.h"
52
#include "MagickCore/list.h"
53
#include "MagickCore/magick.h"
54
#include "MagickCore/memory_.h"
55
#include "MagickCore/monitor.h"
56
#include "MagickCore/monitor-private.h"
57
#include "MagickCore/pixel-accessor.h"
58
#include "MagickCore/pixel.h"
59
#include "MagickCore/property.h"
60
#include "MagickCore/quantum-private.h"
61
#include "MagickCore/static.h"
62
#include "MagickCore/string_.h"
63
#include "MagickCore/module.h"
64

65
/*
66
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67
%                                                                             %
68
%                                                                             %
69
%                                                                             %
70
%   I s R L E                                                                 %
71
%                                                                             %
72
%                                                                             %
73
%                                                                             %
74
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75
%
76
%  IsRLE() returns MagickTrue if the image format type, identified by the
77
%  magick string, is RLE.
78
%
79
%  The format of the ReadRLEImage method is:
80
%
81
%      MagickBooleanType IsRLE(const unsigned char *magick,const size_t length)
82
%
83
%  A description of each parameter follows:
84
%
85
%    o magick: compare image format pattern against these bytes.
86
%
87
%    o length: Specifies the length of the magick string.
88
%
89
%
90
*/
91
static MagickBooleanType IsRLE(const unsigned char *magick,const size_t length)
92
0
{
93
0
  if (length < 2)
94
0
    return(MagickFalse);
95
0
  if (memcmp(magick,"\122\314",2) == 0)
96
0
    return(MagickTrue);
97
0
  return(MagickFalse);
98
0
}
99

100
/*
101
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102
%                                                                             %
103
%                                                                             %
104
%                                                                             %
105
%   R e a d R L E I m a g e                                                   %
106
%                                                                             %
107
%                                                                             %
108
%                                                                             %
109
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110
%
111
%  ReadRLEImage() reads a run-length encoded Utah Raster Toolkit
112
%  image file and returns it.  It allocates the memory necessary for the new
113
%  Image structure and returns a pointer to the new image.
114
%
115
%  The format of the ReadRLEImage method is:
116
%
117
%      Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
118
%
119
%  A description of each parameter follows:
120
%
121
%    o image_info: the image info.
122
%
123
%    o exception: return any errors or warnings in this structure.
124
%
125
%
126
*/
127
static Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
128
2.14k
{
129
30.9k
#define SkipLinesOp  0x01
130
2.14k
#define SetColorOp  0x02
131
4.22k
#define SkipPixelsOp  0x03
132
2.61k
#define ByteDataOp  0x05
133
2.37k
#define RunDataOp  0x06
134
118k
#define EOFOp  0x07
135
2.14k
#define ThrowRLEException(exception,message) \
136
1.54k
{ \
137
1.54k
  if (colormap != (unsigned char *) NULL) \
138
1.54k
    colormap=(unsigned char *) RelinquishMagickMemory(colormap); \
139
1.54k
  if (pixel_info != (MemoryInfo *) NULL) \
140
1.54k
    pixel_info=RelinquishVirtualMemory(pixel_info); \
141
1.54k
  ThrowReaderException((exception),(message)); \
142
0
}
143
144
2.14k
  char
145
2.14k
    magick[12];
146
147
2.14k
  Image
148
2.14k
    *image;
149
150
2.14k
  int
151
2.14k
    opcode,
152
2.14k
    operand;
153
154
2.14k
  MagickStatusType
155
2.14k
    flags,
156
2.14k
    status;
157
158
2.14k
  MagickSizeType
159
2.14k
    number_pixels;
160
161
2.14k
  MemoryInfo
162
2.14k
    *pixel_info;
163
164
2.14k
  Quantum
165
2.14k
    index,
166
2.14k
    *q;
167
168
2.14k
  size_t
169
2.14k
    bits_per_pixel,
170
2.14k
    map_length,
171
2.14k
    number_colormaps,
172
2.14k
    number_planes,
173
2.14k
    number_planes_filled,
174
2.14k
    one,
175
2.14k
    pixel_info_length;
176
177
2.14k
  ssize_t
178
2.14k
    count,
179
2.14k
    i,
180
2.14k
    offset,
181
2.14k
    x,
182
2.14k
    y;
183
184
2.14k
  unsigned char
185
2.14k
    background_color[256] = { 0 },
186
2.14k
    *colormap,
187
2.14k
    *p,
188
2.14k
    pixel,
189
2.14k
    plane,
190
2.14k
    *pixels;
191
192
  /*
193
    Open image file.
194
  */
195
2.14k
  assert(image_info != (const ImageInfo *) NULL);
196
2.14k
  assert(image_info->signature == MagickCoreSignature);
197
2.14k
  assert(exception != (ExceptionInfo *) NULL);
198
2.14k
  assert(exception->signature == MagickCoreSignature);
199
2.14k
  if (IsEventLogging() != MagickFalse)
200
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
201
0
      image_info->filename);
202
2.14k
  image=AcquireImage(image_info,exception);
203
2.14k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
204
2.14k
  if (status == MagickFalse)
205
0
    return(DestroyImageList(image));
206
  /*
207
    Determine if this a RLE file.
208
  */
209
2.14k
  colormap=(unsigned char *) NULL;
210
2.14k
  pixel_info=(MemoryInfo *) NULL;
211
2.14k
  count=ReadBlob(image,2,(unsigned char *) magick);
212
2.14k
  if ((count != 2) || (memcmp(magick,"\122\314",2) != 0))
213
2.11k
    ThrowRLEException(CorruptImageError,"ImproperImageHeader");
214
2.11k
  do
215
4.37k
  {
216
    /*
217
      Read image header.
218
    */
219
4.37k
    image->page.x=(ssize_t) ReadBlobLSBShort(image);
220
4.37k
    image->page.y=(ssize_t) ReadBlobLSBShort(image);
221
4.37k
    image->columns=ReadBlobLSBShort(image);
222
4.37k
    image->rows=ReadBlobLSBShort(image);
223
4.37k
    flags=(MagickStatusType) ReadBlobByte(image);
224
4.37k
    image->alpha_trait=flags & 0x04 ? BlendPixelTrait : UndefinedPixelTrait;
225
4.37k
    number_planes=(size_t) ReadBlobByte(image);
226
4.37k
    bits_per_pixel=(size_t) ReadBlobByte(image);
227
4.37k
    number_colormaps=(size_t) ReadBlobByte(image);
228
4.37k
    map_length=(unsigned char) ReadBlobByte(image);
229
4.37k
    if (map_length >= 22)
230
4.26k
      ThrowRLEException(CorruptImageError,"ImproperImageHeader");
231
4.26k
    if (EOFBlob(image) != MagickFalse)
232
4.26k
      ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
233
4.26k
    one=1;
234
4.26k
    map_length=one << map_length;
235
4.26k
    if ((number_planes == 0) || (number_planes == 2) || ((flags & 0x04) &&
236
4.24k
        ((number_planes <= 2) || number_planes > 254)) || (bits_per_pixel != 8))
237
4.22k
      ThrowRLEException(CorruptImageError,"ImproperImageHeader");
238
4.22k
    if (number_planes > 4)
239
4.21k
      ThrowRLEException(CorruptImageError,"ImproperImageHeader");
240
4.21k
    if ((image->columns == 0) || (image->columns >= 32768) ||
241
4.20k
        (image->rows == 0) || (image->rows >= 32768))
242
4.19k
      ThrowRLEException(CorruptImageError,"ImproperImageHeader");
243
4.19k
    if (flags & 0x02)
244
1.51k
      {
245
        /*
246
          No background color-- initialize to black.
247
        */
248
5.06k
        for (i=0; i < (ssize_t) number_planes; i++)
249
3.55k
          background_color[i]=0;
250
1.51k
        (void) ReadBlobByte(image);
251
1.51k
      }
252
2.68k
    else
253
2.68k
      {
254
        /*
255
          Initialize background color.
256
        */
257
2.68k
        p=background_color;
258
6.04k
        for (i=0; i < (ssize_t) number_planes; i++)
259
3.36k
          *p++=(unsigned char) ReadBlobByte(image);
260
2.68k
      }
261
4.19k
    if ((number_planes & 0x01) == 0)
262
346
      (void) ReadBlobByte(image);
263
4.19k
    if (EOFBlob(image) != MagickFalse)
264
4.14k
      ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
265
4.14k
    if (image->alpha_trait != UndefinedPixelTrait)
266
779
      number_planes++;
267
4.14k
    number_pixels=(MagickSizeType) image->columns*image->rows;
268
4.14k
    if ((GetBlobSize(image) == 0) || ((((MagickSizeType) number_pixels*
269
4.14k
         number_planes*bits_per_pixel/8)/GetBlobSize(image)) > 254))
270
28
      ThrowRLEException(CorruptImageError,"InsufficientImageDataInFile")
271
4.11k
    if (((MagickSizeType) number_colormaps*map_length) > GetBlobSize(image))
272
42
      ThrowRLEException(CorruptImageError,"InsufficientImageDataInFile")
273
4.07k
    if (number_colormaps != 0)
274
1.72k
      {
275
        /*
276
          Read image colormaps.
277
        */
278
1.72k
        colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps,
279
1.72k
          3*map_length*sizeof(*colormap));
280
1.72k
        if (colormap == (unsigned char *) NULL)
281
1.72k
          ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed");
282
1.72k
        (void) memset(colormap,0,number_colormaps*3*map_length*
283
1.72k
          sizeof(*colormap));
284
1.72k
        p=colormap;
285
12.6k
        for (i=0; i < (ssize_t) number_colormaps; i++)
286
39.4k
          for (x=0; x < (ssize_t) map_length; x++)
287
28.5k
          {
288
28.5k
            *p++=(unsigned char) ScaleQuantumToChar(ScaleShortToQuantum(
289
28.5k
              ReadBlobLSBShort(image)));
290
28.5k
            if (EOFBlob(image) != MagickFalse)
291
28.4k
              ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
292
28.4k
          }
293
1.72k
      }
294
3.98k
    if ((flags & 0x08) != 0)
295
616
      {
296
616
        char
297
616
          *comment;
298
299
616
        size_t
300
616
          length;
301
302
        /*
303
          Read image comment.
304
        */
305
616
        length=ReadBlobLSBShort(image);
306
616
        if (length != 0)
307
525
          {
308
525
            comment=(char *) AcquireQuantumMemory(length,sizeof(*comment));
309
525
            if (comment == (char *) NULL)
310
525
              ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed");
311
525
            count=ReadBlob(image,length-1,(unsigned char *) comment);
312
525
            if (count != (ssize_t) (length-1))
313
42
              {
314
42
                comment=DestroyString(comment);
315
42
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
316
0
              }
317
483
            comment[length-1]='\0';
318
483
            (void) SetImageProperty(image,"comment",comment,exception);
319
483
            comment=DestroyString(comment);
320
483
            if ((length & 0x01) == 0)
321
122
              (void) ReadBlobByte(image);
322
483
          }
323
616
      }
324
3.94k
    if (EOFBlob(image) != MagickFalse)
325
3.91k
      ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
326
3.91k
    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
327
0
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
328
0
        break;
329
3.91k
    status=SetImageExtent(image,image->columns,image->rows,exception);
330
3.91k
    if (status == MagickFalse)
331
80
      {
332
80
        if (colormap != (unsigned char *) NULL)
333
15
          colormap=(unsigned char *) RelinquishMagickMemory(colormap);
334
80
        if (pixel_info != (MemoryInfo *) NULL)
335
0
          pixel_info=RelinquishVirtualMemory(pixel_info);
336
80
        return(DestroyImageList(image));
337
80
      }
338
    /*
339
      Allocate RLE pixels.
340
    */
341
3.83k
    number_planes_filled=(number_planes % 2 == 0) ? number_planes :
342
3.83k
      number_planes+1;
343
3.83k
    if (HeapOverflowSanityCheckGetSize(number_planes_filled,
344
3.83k
         (size_t) number_pixels,(size_t *) NULL) != MagickFalse)
345
3.83k
      ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed");
346
3.83k
    pixel_info=AcquireVirtualMemory(image->columns,image->rows*
347
3.83k
      MagickMax(number_planes_filled,4)*sizeof(*pixels));
348
3.83k
    if (pixel_info == (MemoryInfo *) NULL)
349
3.83k
      ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed");
350
3.83k
    pixel_info_length=image->columns*image->rows*
351
3.83k
      MagickMax(number_planes_filled,4);
352
3.83k
    pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
353
3.83k
    (void) memset(pixels,0,pixel_info_length);
354
3.83k
    if ((flags & 0x01) && !(flags & 0x02))
355
1.25k
      {
356
1.25k
        ssize_t
357
1.25k
          j;
358
359
        /*
360
          Set background color.
361
        */
362
1.25k
        p=pixels;
363
37.4M
        for (i=0; i < (ssize_t) number_pixels; i++)
364
37.4M
        {
365
37.4M
          if ((image->alpha_trait & BlendPixelTrait) == 0)
366
75.9M
            for (j=0; j < (ssize_t) number_planes; j++)
367
38.6M
              *p++=background_color[j];
368
35.4k
          else
369
35.4k
            {
370
156k
              for (j=0; j < (ssize_t) (number_planes-1); j++)
371
120k
                *p++=background_color[j];
372
35.4k
              *p++=0;  /* initialize matte channel */
373
35.4k
            }
374
37.4M
        }
375
1.25k
      }
376
    /*
377
      Read runlength-encoded image.
378
    */
379
3.83k
    plane=0;
380
3.83k
    x=0;
381
3.83k
    y=0;
382
3.83k
    opcode=ReadBlobByte(image);
383
3.83k
    if (opcode == EOF)
384
110
      {
385
110
        if (number_colormaps != 0)
386
16
          colormap=(unsigned char *) RelinquishMagickMemory(colormap);
387
110
        ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
388
0
      }
389
3.72k
    do
390
119k
    {
391
119k
      switch (opcode & 0x3f)
392
119k
      {
393
30.9k
        case SkipLinesOp:
394
30.9k
        {
395
30.9k
          operand=ReadBlobByte(image);
396
30.9k
          if (operand == EOF)
397
30.9k
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
398
30.9k
          if (opcode & 0x40)
399
27.8k
            {
400
27.8k
              operand=ReadBlobLSBSignedShort(image);
401
27.8k
              if (operand == EOF)
402
27.8k
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
403
27.8k
            }
404
30.9k
          x=0;
405
30.9k
          y+=operand;
406
30.9k
          break;
407
30.9k
        }
408
1.78k
        case SetColorOp:
409
1.78k
        {
410
1.78k
          operand=ReadBlobByte(image);
411
1.78k
          if (operand == EOF)
412
1.77k
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
413
1.77k
          plane=(unsigned char) operand;
414
1.77k
          if (plane == 255)
415
322
            plane=(unsigned char) (number_planes-1);
416
1.77k
          x=0;
417
1.77k
          break;
418
1.78k
        }
419
4.22k
        case SkipPixelsOp:
420
4.22k
        {
421
4.22k
          operand=ReadBlobByte(image);
422
4.22k
          if (operand == EOF)
423
4.22k
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
424
4.22k
          if (opcode & 0x40)
425
2.84k
            {
426
2.84k
              operand=ReadBlobLSBSignedShort(image);
427
2.84k
              if (operand == EOF)
428
2.84k
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
429
2.84k
            }
430
4.21k
          x+=operand;
431
4.21k
          break;
432
4.22k
        }
433
2.61k
        case ByteDataOp:
434
2.61k
        {
435
2.61k
          operand=ReadBlobByte(image);
436
2.61k
          if (operand == EOF)
437
2.60k
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
438
2.60k
          if (opcode & 0x40)
439
1.44k
            {
440
1.44k
              operand=ReadBlobLSBSignedShort(image);
441
1.44k
              if (operand == EOF)
442
1.43k
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
443
1.43k
            }
444
2.60k
          offset=(ssize_t) ((((ssize_t) image->rows-y-1)*(ssize_t)
445
2.60k
            image->columns*(ssize_t) number_planes)+x*(ssize_t)
446
2.60k
            number_planes+plane);
447
2.60k
          operand++;
448
2.60k
          if ((offset < 0) ||
449
2.54k
              ((size_t) (offset+operand*(ssize_t) number_planes) > pixel_info_length))
450
2.44k
            ThrowRLEException(CorruptImageError,"UnableToReadImageData");
451
2.44k
          p=pixels+offset;
452
386k
          for (i=0; i < (ssize_t) operand; i++)
453
383k
          {
454
383k
            pixel=(unsigned char) ReadBlobByte(image);
455
383k
            if ((y < (ssize_t) image->rows) &&
456
376k
                ((x+i) < (ssize_t) image->columns))
457
96.4k
              *p=pixel;
458
383k
            p+=(ptrdiff_t) number_planes;
459
383k
          }
460
2.44k
          if (operand & 0x01)
461
1.05k
            (void) ReadBlobByte(image);
462
2.44k
          x+=operand;
463
2.44k
          break;
464
2.60k
        }
465
2.37k
        case RunDataOp:
466
2.37k
        {
467
2.37k
          operand=ReadBlobByte(image);
468
2.37k
          if (operand == EOF)
469
2.36k
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
470
2.36k
          if (opcode & 0x40)
471
1.53k
            {
472
1.53k
              operand=ReadBlobLSBSignedShort(image);
473
1.53k
              if (operand == EOF)
474
1.53k
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
475
1.53k
            }
476
2.36k
          pixel=(unsigned char) ReadBlobByte(image);
477
2.36k
          (void) ReadBlobByte(image);
478
2.36k
          offset=(((ssize_t) image->rows-y-1)*(ssize_t) image->columns*
479
2.36k
            (ssize_t) number_planes)+x*(ssize_t) number_planes+plane;
480
2.36k
          operand++;
481
2.36k
          if ((offset < 0) ||
482
2.30k
              ((size_t) (offset+operand*(ssize_t) number_planes) > pixel_info_length))
483
2.20k
            ThrowRLEException(CorruptImageError,"UnableToReadImageData");
484
2.20k
          p=pixels+offset;
485
9.35M
          for (i=0; i < (ssize_t) operand; i++)
486
9.35M
          {
487
9.35M
            if ((y < (ssize_t) image->rows) &&
488
9.33M
                ((x+i) < (ssize_t) image->columns))
489
894k
              *p=pixel;
490
9.35M
            p+=(ptrdiff_t) number_planes;
491
9.35M
          }
492
2.20k
          x+=operand;
493
2.20k
          break;
494
2.36k
        }
495
77.2k
        default:
496
77.2k
          break;
497
119k
      }
498
118k
      opcode=ReadBlobByte(image);
499
118k
      if (opcode == EOF)
500
118k
        ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
501
118k
    } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
502
2.81k
    if (number_colormaps != 0)
503
1.43k
      {
504
1.43k
        MagickStatusType
505
1.43k
          mask;
506
507
        /*
508
          Apply colormap affineation to image.
509
        */
510
1.43k
        mask=(MagickStatusType) (map_length-1);
511
1.43k
        p=pixels;
512
1.43k
        x=(ssize_t) number_planes;
513
1.43k
        if (number_colormaps == 1)
514
23.2M
          for (i=0; i < (ssize_t) number_pixels; i++)
515
23.2M
          {
516
23.2M
            ValidateColormapValue(image,(ssize_t) (*p & mask),&index,exception);
517
23.2M
            *p=colormap[(ssize_t) index];
518
23.2M
            p++;
519
23.2M
          }
520
325
        else
521
325
          if ((number_planes >= 3) && (number_colormaps >= 3))
522
1.46M
            for (i=0; i < (ssize_t) number_pixels; i++)
523
6.01M
              for (x=0; x < (ssize_t) number_planes; x++)
524
4.55M
              {
525
4.55M
                ValidateColormapValue(image,x*(ssize_t) map_length+
526
4.55M
                  (*p & mask),&index,exception);
527
4.55M
                *p=colormap[(ssize_t) index];
528
4.55M
                p++;
529
4.55M
              }
530
1.43k
        if ((i < (ssize_t) number_pixels) || (x < (ssize_t) number_planes))
531
1.40k
          ThrowRLEException(CorruptImageError,"UnableToReadImageData");
532
1.40k
      }
533
    /*
534
      Initialize image structure.
535
    */
536
2.78k
    if (number_planes >= 3)
537
690
      {
538
        /*
539
          Convert raster image to DirectClass pixel packets.
540
        */
541
690
        p=pixels;
542
39.9k
        for (y=0; y < (ssize_t) image->rows; y++)
543
39.2k
        {
544
39.2k
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
545
39.2k
          if (q == (Quantum *) NULL)
546
0
            break;
547
1.99M
          for (x=0; x < (ssize_t) image->columns; x++)
548
1.95M
          {
549
1.95M
            SetPixelRed(image,ScaleCharToQuantum(*p++),q);
550
1.95M
            SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
551
1.95M
            SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
552
1.95M
            if (image->alpha_trait != UndefinedPixelTrait)
553
499k
              SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
554
1.95M
            q+=(ptrdiff_t) GetPixelChannels(image);
555
1.95M
          }
556
39.2k
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
557
0
            break;
558
39.2k
          if (image->previous == (Image *) NULL)
559
22.9k
            {
560
22.9k
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
561
22.9k
                image->rows);
562
22.9k
              if (status == MagickFalse)
563
0
                break;
564
22.9k
            }
565
39.2k
        }
566
690
      }
567
2.09k
    else
568
2.09k
      {
569
        /*
570
          Create colormap.
571
        */
572
2.09k
        if (number_colormaps == 0)
573
905
          map_length=256;
574
2.09k
        if (AcquireImageColormap(image,map_length,exception) == MagickFalse)
575
2.09k
          ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed");
576
2.09k
        p=colormap;
577
2.09k
        if (number_colormaps == 1)
578
9.77k
          for (i=0; i < (ssize_t) image->colors; i++)
579
8.73k
          {
580
            /*
581
              Pseudocolor.
582
            */
583
8.73k
            image->colormap[i].red=(MagickRealType)
584
8.73k
              ScaleCharToQuantum((unsigned char) i);
585
8.73k
            image->colormap[i].green=(MagickRealType)
586
8.73k
              ScaleCharToQuantum((unsigned char) i);
587
8.73k
            image->colormap[i].blue=(MagickRealType)
588
8.73k
              ScaleCharToQuantum((unsigned char) i);
589
8.73k
          }
590
1.05k
        else
591
1.05k
          if (number_colormaps > 1)
592
547
            for (i=0; i < (ssize_t) image->colors; i++)
593
394
            {
594
394
              image->colormap[i].red=(MagickRealType)
595
394
                ScaleCharToQuantum(*p);
596
394
              image->colormap[i].green=(MagickRealType)
597
394
                ScaleCharToQuantum(*(p+map_length));
598
394
              image->colormap[i].blue=(MagickRealType)
599
394
                ScaleCharToQuantum(*(p+map_length*2));
600
394
              p++;
601
394
            }
602
2.09k
        p=pixels;
603
2.09k
        if ((image->alpha_trait & BlendPixelTrait) == 0)
604
2.09k
          {
605
            /*
606
              Convert raster image to PseudoClass pixel packets.
607
            */
608
301k
            for (y=0; y < (ssize_t) image->rows; y++)
609
299k
            {
610
299k
              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
611
299k
              if (q == (Quantum *) NULL)
612
0
                break;
613
34.2M
              for (x=0; x < (ssize_t) image->columns; x++)
614
33.9M
              {
615
33.9M
                SetPixelIndex(image,(Quantum) *p++,q);
616
33.9M
                q+=(ptrdiff_t) GetPixelChannels(image);
617
33.9M
              }
618
299k
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
619
0
                break;
620
299k
              if (image->previous == (Image *) NULL)
621
96.4k
                {
622
96.4k
                  status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
623
96.4k
                    y,image->rows);
624
96.4k
                  if (status == MagickFalse)
625
0
                    break;
626
96.4k
                }
627
299k
            }
628
2.09k
            (void) SyncImage(image,exception);
629
2.09k
          }
630
0
        else
631
0
          {
632
            /*
633
              Image has a matte channel-- promote to DirectClass.
634
            */
635
0
            for (y=0; y < (ssize_t) image->rows; y++)
636
0
            {
637
0
              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
638
0
              if (q == (Quantum *) NULL)
639
0
                break;
640
0
              for (x=0; x < (ssize_t) image->columns; x++)
641
0
              {
642
0
                ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
643
0
                SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t)
644
0
                  index].red),q);
645
0
                ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
646
0
                SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t)
647
0
                  index].green),q);
648
0
                ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
649
0
                SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t)
650
0
                  index].blue),q);
651
0
                SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
652
0
                q+=(ptrdiff_t) GetPixelChannels(image);
653
0
              }
654
0
              if (x < (ssize_t) image->columns)
655
0
                break;
656
0
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
657
0
                break;
658
0
              if (image->previous == (Image *) NULL)
659
0
                {
660
0
                  status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
661
0
                    y,image->rows);
662
0
                  if (status == MagickFalse)
663
0
                    break;
664
0
                }
665
0
            }
666
0
            image->colormap=(PixelInfo *) RelinquishMagickMemory(
667
0
              image->colormap);
668
0
            image->storage_class=DirectClass;
669
0
            image->colors=0;
670
0
          }
671
2.09k
      }
672
2.78k
    if (colormap != (unsigned char *) NULL)
673
1.40k
      colormap=(unsigned char *) RelinquishMagickMemory(colormap);
674
2.78k
    pixel_info=RelinquishVirtualMemory(pixel_info);
675
2.78k
    if (EOFBlob(image) != MagickFalse)
676
0
      {
677
0
        ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
678
0
          image->filename);
679
0
        break;
680
0
      }
681
    /*
682
      Proceed to next image.
683
    */
684
2.78k
    if (image_info->number_scenes != 0)
685
15
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
686
0
        break;
687
2.78k
    (void) ReadBlobByte(image);
688
2.78k
    count=ReadBlob(image,2,(unsigned char *) magick);
689
2.78k
    if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
690
2.26k
      {
691
        /*
692
          Allocate next image structure.
693
        */
694
2.26k
        AcquireNextImage(image_info,image,exception);
695
2.26k
        if (GetNextImageInList(image) == (Image *) NULL)
696
0
          {
697
0
            status=MagickFalse;
698
0
            break;
699
0
          }
700
2.26k
        image=SyncNextImageInList(image);
701
2.26k
        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
702
2.26k
          GetBlobSize(image));
703
2.26k
        if (status == MagickFalse)
704
0
          break;
705
2.26k
      }
706
2.78k
  } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
707
523
  if (colormap != (unsigned char *) NULL)
708
0
    colormap=(unsigned char *) RelinquishMagickMemory(colormap);
709
523
  if (CloseBlob(image) == MagickFalse)
710
0
    status=MagickFalse;
711
523
  if (status == MagickFalse)
712
0
    return(DestroyImageList(image));
713
523
  return(GetFirstImageInList(image));
714
523
}
715

716
/*
717
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
718
%                                                                             %
719
%                                                                             %
720
%                                                                             %
721
%   R e g i s t e r R L E I m a g e                                           %
722
%                                                                             %
723
%                                                                             %
724
%                                                                             %
725
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
726
%
727
%  RegisterRLEImage() adds attributes for the RLE image format to
728
%  the list of supported formats.  The attributes include the image format
729
%  tag, a method to read and/or write the format, whether the format
730
%  supports the saving of more than one frame to the same file or blob,
731
%  whether the format supports native in-memory I/O, and a brief
732
%  description of the format.
733
%
734
%  The format of the RegisterRLEImage method is:
735
%
736
%      size_t RegisterRLEImage(void)
737
%
738
*/
739
ModuleExport size_t RegisterRLEImage(void)
740
10
{
741
10
  MagickInfo
742
10
    *entry;
743
744
10
  entry=AcquireMagickInfo("RLE","RLE","Utah Run length encoded image");
745
10
  entry->decoder=(DecodeImageHandler *) ReadRLEImage;
746
10
  entry->magick=(IsImageFormatHandler *) IsRLE;
747
10
  entry->flags|=CoderDecoderSeekableStreamFlag;
748
10
  entry->flags^=CoderAdjoinFlag;
749
10
  (void) RegisterMagickInfo(entry);
750
10
  return(MagickImageCoderSignature);
751
10
}
752

753
/*
754
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
755
%                                                                             %
756
%                                                                             %
757
%                                                                             %
758
%   U n r e g i s t e r R L E I m a g e                                       %
759
%                                                                             %
760
%                                                                             %
761
%                                                                             %
762
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
763
%
764
%  UnregisterRLEImage() removes format registrations made by the
765
%  RLE module from the list of supported formats.
766
%
767
%  The format of the UnregisterRLEImage method is:
768
%
769
%      UnregisterRLEImage(void)
770
%
771
*/
772
ModuleExport void UnregisterRLEImage(void)
773
0
{
774
0
  (void) UnregisterMagickInfo("RLE");
775
0
}