Coverage Report

Created: 2025-06-16 07:00

/src/imagemagick/coders/rle.c
Line
Count
Source (jump to first uncovered line)
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.63k
{
129
27.3k
#define SkipLinesOp  0x01
130
3.71k
#define SetColorOp  0x02
131
6.10k
#define SkipPixelsOp  0x03
132
2.82k
#define ByteDataOp  0x05
133
3.26k
#define RunDataOp  0x06
134
134k
#define EOFOp  0x07
135
2.63k
#define ThrowRLEException(exception,message) \
136
1.91k
{ \
137
1.91k
  if (colormap != (unsigned char *) NULL) \
138
1.91k
    colormap=(unsigned char *) RelinquishMagickMemory(colormap); \
139
1.91k
  if (pixel_info != (MemoryInfo *) NULL) \
140
1.91k
    pixel_info=RelinquishVirtualMemory(pixel_info); \
141
1.91k
  ThrowReaderException((exception),(message)); \
142
0
}
143
144
2.63k
  char
145
2.63k
    magick[12];
146
147
2.63k
  Image
148
2.63k
    *image;
149
150
2.63k
  int
151
2.63k
    opcode,
152
2.63k
    operand;
153
154
2.63k
  MagickStatusType
155
2.63k
    flags,
156
2.63k
    status;
157
158
2.63k
  MagickSizeType
159
2.63k
    number_pixels;
160
161
2.63k
  MemoryInfo
162
2.63k
    *pixel_info;
163
164
2.63k
  Quantum
165
2.63k
    index,
166
2.63k
    *q;
167
168
2.63k
  size_t
169
2.63k
    bits_per_pixel,
170
2.63k
    map_length,
171
2.63k
    number_colormaps,
172
2.63k
    number_planes,
173
2.63k
    number_planes_filled,
174
2.63k
    one,
175
2.63k
    pixel_info_length;
176
177
2.63k
  ssize_t
178
2.63k
    count,
179
2.63k
    i,
180
2.63k
    offset,
181
2.63k
    x,
182
2.63k
    y;
183
184
2.63k
  unsigned char
185
2.63k
    background_color[256] = { 0 },
186
2.63k
    *colormap,
187
2.63k
    *p,
188
2.63k
    pixel,
189
2.63k
    plane,
190
2.63k
    *pixels;
191
192
  /*
193
    Open image file.
194
  */
195
2.63k
  assert(image_info != (const ImageInfo *) NULL);
196
2.63k
  assert(image_info->signature == MagickCoreSignature);
197
2.63k
  assert(exception != (ExceptionInfo *) NULL);
198
2.63k
  assert(exception->signature == MagickCoreSignature);
199
2.63k
  if (IsEventLogging() != MagickFalse)
200
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
201
0
      image_info->filename);
202
2.63k
  image=AcquireImage(image_info,exception);
203
2.63k
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
204
2.63k
  if (status == MagickFalse)
205
0
    return(DestroyImageList(image));
206
  /*
207
    Determine if this a RLE file.
208
  */
209
2.63k
  colormap=(unsigned char *) NULL;
210
2.63k
  pixel_info=(MemoryInfo *) NULL;
211
2.63k
  count=ReadBlob(image,2,(unsigned char *) magick);
212
2.63k
  if ((count != 2) || (memcmp(magick,"\122\314",2) != 0))
213
2.58k
    ThrowRLEException(CorruptImageError,"ImproperImageHeader");
214
2.58k
  do
215
5.18k
  {
216
    /*
217
      Read image header.
218
    */
219
5.18k
    image->page.x=(ssize_t) ReadBlobLSBShort(image);
220
5.18k
    image->page.y=(ssize_t) ReadBlobLSBShort(image);
221
5.18k
    image->columns=ReadBlobLSBShort(image);
222
5.18k
    image->rows=ReadBlobLSBShort(image);
223
5.18k
    flags=(MagickStatusType) ReadBlobByte(image);
224
5.18k
    image->alpha_trait=flags & 0x04 ? BlendPixelTrait : UndefinedPixelTrait;
225
5.18k
    number_planes=(size_t) ReadBlobByte(image);
226
5.18k
    bits_per_pixel=(size_t) ReadBlobByte(image);
227
5.18k
    number_colormaps=(size_t) ReadBlobByte(image);
228
5.18k
    map_length=(unsigned char) ReadBlobByte(image);
229
5.18k
    if (map_length >= 22)
230
5.05k
      ThrowRLEException(CorruptImageError,"ImproperImageHeader");
231
5.05k
    if (EOFBlob(image) != MagickFalse)
232
5.05k
      ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
233
5.05k
    one=1;
234
5.05k
    map_length=one << map_length;
235
5.05k
    if ((number_planes == 0) || (number_planes == 2) || ((flags & 0x04) &&
236
5.03k
        ((number_planes <= 2) || number_planes > 254)) || (bits_per_pixel != 8))
237
5.00k
      ThrowRLEException(CorruptImageError,"ImproperImageHeader");
238
5.00k
    if (number_planes > 4)
239
4.99k
      ThrowRLEException(CorruptImageError,"ImproperImageHeader");
240
4.99k
    if ((image->columns == 0) || (image->columns >= 32768) ||
241
4.99k
        (image->rows == 0) || (image->rows >= 32768))
242
4.96k
      ThrowRLEException(CorruptImageError,"ImproperImageHeader");
243
4.96k
    if (flags & 0x02)
244
1.81k
      {
245
        /*
246
          No background color-- initialize to black.
247
        */
248
5.79k
        for (i=0; i < (ssize_t) number_planes; i++)
249
3.98k
          background_color[i]=0;
250
1.81k
        (void) ReadBlobByte(image);
251
1.81k
      }
252
3.15k
    else
253
3.15k
      {
254
        /*
255
          Initialize background color.
256
        */
257
3.15k
        p=background_color;
258
7.05k
        for (i=0; i < (ssize_t) number_planes; i++)
259
3.90k
          *p++=(unsigned char) ReadBlobByte(image);
260
3.15k
      }
261
4.96k
    if ((number_planes & 0x01) == 0)
262
356
      (void) ReadBlobByte(image);
263
4.96k
    if (EOFBlob(image) != MagickFalse)
264
4.91k
      ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
265
4.91k
    if (image->alpha_trait != UndefinedPixelTrait)
266
793
      number_planes++;
267
4.91k
    number_pixels=(MagickSizeType) image->columns*image->rows;
268
4.91k
    if ((GetBlobSize(image) == 0) || ((((MagickSizeType) number_pixels*
269
4.91k
         number_planes*bits_per_pixel/8)/GetBlobSize(image)) > 254))
270
32
      ThrowRLEException(CorruptImageError,"InsufficientImageDataInFile")
271
4.88k
    if (((MagickSizeType) number_colormaps*map_length) > GetBlobSize(image))
272
58
      ThrowRLEException(CorruptImageError,"InsufficientImageDataInFile")
273
4.82k
    if (number_colormaps != 0)
274
2.10k
      {
275
        /*
276
          Read image colormaps.
277
        */
278
2.10k
        colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps,
279
2.10k
          3*map_length*sizeof(*colormap));
280
2.10k
        if (colormap == (unsigned char *) NULL)
281
2.10k
          ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed");
282
2.10k
        (void) memset(colormap,0,number_colormaps*3*map_length*
283
2.10k
          sizeof(*colormap));
284
2.10k
        p=colormap;
285
18.5k
        for (i=0; i < (ssize_t) number_colormaps; i++)
286
55.8k
          for (x=0; x < (ssize_t) map_length; x++)
287
39.4k
          {
288
39.4k
            *p++=(unsigned char) ScaleQuantumToChar(ScaleShortToQuantum(
289
39.4k
              ReadBlobLSBShort(image)));
290
39.4k
            if (EOFBlob(image) != MagickFalse)
291
39.3k
              ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
292
39.3k
          }
293
2.10k
      }
294
4.71k
    if ((flags & 0x08) != 0)
295
779
      {
296
779
        char
297
779
          *comment;
298
299
779
        size_t
300
779
          length;
301
302
        /*
303
          Read image comment.
304
        */
305
779
        length=ReadBlobLSBShort(image);
306
779
        if (length != 0)
307
588
          {
308
588
            comment=(char *) AcquireQuantumMemory(length,sizeof(*comment));
309
588
            if (comment == (char *) NULL)
310
588
              ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed");
311
588
            count=ReadBlob(image,length-1,(unsigned char *) comment);
312
588
            if (count != (ssize_t) (length-1))
313
45
              {
314
45
                comment=DestroyString(comment);
315
45
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
316
0
              }
317
543
            comment[length-1]='\0';
318
543
            (void) SetImageProperty(image,"comment",comment,exception);
319
543
            comment=DestroyString(comment);
320
543
            if ((length & 0x01) == 0)
321
137
              (void) ReadBlobByte(image);
322
543
          }
323
779
      }
324
4.66k
    if (EOFBlob(image) != MagickFalse)
325
4.64k
      ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
326
4.64k
    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
4.64k
    status=SetImageExtent(image,image->columns,image->rows,exception);
330
4.64k
    if (status == MagickFalse)
331
84
      {
332
84
        if (colormap != (unsigned char *) NULL)
333
27
          colormap=(unsigned char *) RelinquishMagickMemory(colormap);
334
84
        if (pixel_info != (MemoryInfo *) NULL)
335
0
          pixel_info=RelinquishVirtualMemory(pixel_info);
336
84
        return(DestroyImageList(image));
337
84
      }
338
    /*
339
      Allocate RLE pixels.
340
    */
341
4.55k
    number_planes_filled=(number_planes % 2 == 0) ? number_planes :
342
4.55k
      number_planes+1;
343
4.55k
    if (HeapOverflowSanityCheckGetSize(number_planes_filled,
344
4.55k
         (size_t) number_pixels,(size_t *) NULL) != MagickFalse)
345
4.55k
      ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed");
346
4.55k
    pixel_info=AcquireVirtualMemory(image->columns,image->rows*
347
4.55k
      MagickMax(number_planes_filled,4)*sizeof(*pixels));
348
4.55k
    if (pixel_info == (MemoryInfo *) NULL)
349
4.55k
      ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed");
350
4.55k
    pixel_info_length=image->columns*image->rows*
351
4.55k
      MagickMax(number_planes_filled,4);
352
4.55k
    pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
353
4.55k
    (void) memset(pixels,0,pixel_info_length);
354
4.55k
    if ((flags & 0x01) && !(flags & 0x02))
355
1.57k
      {
356
1.57k
        ssize_t
357
1.57k
          j;
358
359
        /*
360
          Set background color.
361
        */
362
1.57k
        p=pixels;
363
40.9M
        for (i=0; i < (ssize_t) number_pixels; i++)
364
40.9M
        {
365
40.9M
          if ((image->alpha_trait & BlendPixelTrait) == 0)
366
83.0M
            for (j=0; j < (ssize_t) number_planes; j++)
367
42.1M
              *p++=background_color[j];
368
50.1k
          else
369
50.1k
            {
370
209k
              for (j=0; j < (ssize_t) (number_planes-1); j++)
371
159k
                *p++=background_color[j];
372
50.1k
              *p++=0;  /* initialize matte channel */
373
50.1k
            }
374
40.9M
        }
375
1.57k
      }
376
    /*
377
      Read runlength-encoded image.
378
    */
379
4.55k
    plane=0;
380
4.55k
    x=0;
381
4.55k
    y=0;
382
4.55k
    opcode=ReadBlobByte(image);
383
4.55k
    if (opcode == EOF)
384
112
      {
385
112
        if (number_colormaps != 0)
386
14
          colormap=(unsigned char *) RelinquishMagickMemory(colormap);
387
112
        ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
388
0
      }
389
4.44k
    do
390
135k
    {
391
135k
      switch (opcode & 0x3f)
392
135k
      {
393
27.3k
        case SkipLinesOp:
394
27.3k
        {
395
27.3k
          operand=ReadBlobByte(image);
396
27.3k
          if (operand == EOF)
397
27.3k
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
398
27.3k
          if (opcode & 0x40)
399
22.1k
            {
400
22.1k
              operand=ReadBlobLSBSignedShort(image);
401
22.1k
              if (operand == EOF)
402
22.1k
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
403
22.1k
            }
404
27.3k
          x=0;
405
27.3k
          y+=operand;
406
27.3k
          break;
407
27.3k
        }
408
3.71k
        case SetColorOp:
409
3.71k
        {
410
3.71k
          operand=ReadBlobByte(image);
411
3.71k
          if (operand == EOF)
412
3.69k
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
413
3.69k
          plane=(unsigned char) operand;
414
3.69k
          if (plane == 255)
415
296
            plane=(unsigned char) (number_planes-1);
416
3.69k
          x=0;
417
3.69k
          break;
418
3.71k
        }
419
6.10k
        case SkipPixelsOp:
420
6.10k
        {
421
6.10k
          operand=ReadBlobByte(image);
422
6.10k
          if (operand == EOF)
423
6.08k
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
424
6.08k
          if (opcode & 0x40)
425
3.96k
            {
426
3.96k
              operand=ReadBlobLSBSignedShort(image);
427
3.96k
              if (operand == EOF)
428
3.96k
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
429
3.96k
            }
430
6.08k
          x+=operand;
431
6.08k
          break;
432
6.08k
        }
433
2.82k
        case ByteDataOp:
434
2.82k
        {
435
2.82k
          operand=ReadBlobByte(image);
436
2.82k
          if (operand == EOF)
437
2.80k
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
438
2.80k
          if (opcode & 0x40)
439
1.65k
            {
440
1.65k
              operand=ReadBlobLSBSignedShort(image);
441
1.65k
              if (operand == EOF)
442
1.64k
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
443
1.64k
            }
444
2.80k
          offset=(ssize_t) ((((ssize_t) image->rows-y-1)*(ssize_t)
445
2.80k
            image->columns*(ssize_t) number_planes)+x*(ssize_t)
446
2.80k
            number_planes+plane);
447
2.80k
          operand++;
448
2.80k
          if ((offset < 0) ||
449
2.80k
              ((size_t) (offset+operand*(ssize_t) number_planes) > pixel_info_length))
450
2.59k
            ThrowRLEException(CorruptImageError,"UnableToReadImageData");
451
2.59k
          p=pixels+offset;
452
478k
          for (i=0; i < (ssize_t) operand; i++)
453
475k
          {
454
475k
            pixel=(unsigned char) ReadBlobByte(image);
455
475k
            if ((y < (ssize_t) image->rows) &&
456
475k
                ((x+i) < (ssize_t) image->columns))
457
118k
              *p=pixel;
458
475k
            p+=(ptrdiff_t) number_planes;
459
475k
          }
460
2.59k
          if (operand & 0x01)
461
1.29k
            (void) ReadBlobByte(image);
462
2.59k
          x+=operand;
463
2.59k
          break;
464
2.80k
        }
465
3.26k
        case RunDataOp:
466
3.26k
        {
467
3.26k
          operand=ReadBlobByte(image);
468
3.26k
          if (operand == EOF)
469
3.25k
            ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
470
3.25k
          if (opcode & 0x40)
471
1.69k
            {
472
1.69k
              operand=ReadBlobLSBSignedShort(image);
473
1.69k
              if (operand == EOF)
474
1.68k
                ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
475
1.68k
            }
476
3.24k
          pixel=(unsigned char) ReadBlobByte(image);
477
3.24k
          (void) ReadBlobByte(image);
478
3.24k
          offset=(((ssize_t) image->rows-y-1)*(ssize_t) image->columns*
479
3.24k
            (ssize_t) number_planes)+x*(ssize_t) number_planes+plane;
480
3.24k
          operand++;
481
3.24k
          if ((offset < 0) ||
482
3.24k
              ((size_t) (offset+operand*(ssize_t) number_planes) > pixel_info_length))
483
3.03k
            ThrowRLEException(CorruptImageError,"UnableToReadImageData");
484
3.03k
          p=pixels+offset;
485
9.14M
          for (i=0; i < (ssize_t) operand; i++)
486
9.14M
          {
487
9.14M
            if ((y < (ssize_t) image->rows) &&
488
9.14M
                ((x+i) < (ssize_t) image->columns))
489
506k
              *p=pixel;
490
9.14M
            p+=(ptrdiff_t) number_planes;
491
9.14M
          }
492
3.03k
          x+=operand;
493
3.03k
          break;
494
3.24k
        }
495
92.3k
        default:
496
92.3k
          break;
497
135k
      }
498
135k
      opcode=ReadBlobByte(image);
499
135k
      if (opcode == EOF)
500
134k
        ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
501
134k
    } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
502
3.25k
    if (number_colormaps != 0)
503
1.66k
      {
504
1.66k
        MagickStatusType
505
1.66k
          mask;
506
507
        /*
508
          Apply colormap affineation to image.
509
        */
510
1.66k
        mask=(MagickStatusType) (map_length-1);
511
1.66k
        p=pixels;
512
1.66k
        x=(ssize_t) number_planes;
513
1.66k
        if (number_colormaps == 1)
514
32.6M
          for (i=0; i < (ssize_t) number_pixels; i++)
515
32.6M
          {
516
32.6M
            ValidateColormapValue(image,(ssize_t) (*p & mask),&index,exception);
517
32.6M
            *p=colormap[(ssize_t) index];
518
32.6M
            p++;
519
32.6M
          }
520
363
        else
521
363
          if ((number_planes >= 3) && (number_colormaps >= 3))
522
578k
            for (i=0; i < (ssize_t) number_pixels; i++)
523
2.38M
              for (x=0; x < (ssize_t) number_planes; x++)
524
1.80M
              {
525
1.80M
                ValidateColormapValue(image,x*(ssize_t) map_length+
526
1.80M
                  (*p & mask),&index,exception);
527
1.80M
                *p=colormap[(ssize_t) index];
528
1.80M
                p++;
529
1.80M
              }
530
1.66k
        if ((i < (ssize_t) number_pixels) || (x < (ssize_t) number_planes))
531
1.64k
          ThrowRLEException(CorruptImageError,"UnableToReadImageData");
532
1.64k
      }
533
    /*
534
      Initialize image structure.
535
    */
536
3.23k
    if (number_planes >= 3)
537
707
      {
538
        /*
539
          Convert raster image to DirectClass pixel packets.
540
        */
541
707
        p=pixels;
542
39.1k
        for (y=0; y < (ssize_t) image->rows; y++)
543
38.4k
        {
544
38.4k
          q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
545
38.4k
          if (q == (Quantum *) NULL)
546
0
            break;
547
2.02M
          for (x=0; x < (ssize_t) image->columns; x++)
548
1.98M
          {
549
1.98M
            SetPixelRed(image,ScaleCharToQuantum(*p++),q);
550
1.98M
            SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
551
1.98M
            SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
552
1.98M
            if (image->alpha_trait != UndefinedPixelTrait)
553
448k
              SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
554
1.98M
            q+=(ptrdiff_t) GetPixelChannels(image);
555
1.98M
          }
556
38.4k
          if (SyncAuthenticPixels(image,exception) == MagickFalse)
557
0
            break;
558
38.4k
          if (image->previous == (Image *) NULL)
559
22.1k
            {
560
22.1k
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
561
22.1k
                image->rows);
562
22.1k
              if (status == MagickFalse)
563
0
                break;
564
22.1k
            }
565
38.4k
        }
566
707
      }
567
2.53k
    else
568
2.53k
      {
569
        /*
570
          Create colormap.
571
        */
572
2.53k
        if (number_colormaps == 0)
573
1.09k
          map_length=256;
574
2.53k
        if (AcquireImageColormap(image,map_length,exception) == MagickFalse)
575
2.53k
          ThrowRLEException(ResourceLimitError,"MemoryAllocationFailed");
576
2.53k
        p=colormap;
577
2.53k
        if (number_colormaps == 1)
578
10.9k
          for (i=0; i < (ssize_t) image->colors; i++)
579
9.70k
          {
580
            /*
581
              Pseudocolor.
582
            */
583
9.70k
            image->colormap[i].red=(MagickRealType)
584
9.70k
              ScaleCharToQuantum((unsigned char) i);
585
9.70k
            image->colormap[i].green=(MagickRealType)
586
9.70k
              ScaleCharToQuantum((unsigned char) i);
587
9.70k
            image->colormap[i].blue=(MagickRealType)
588
9.70k
              ScaleCharToQuantum((unsigned char) i);
589
9.70k
          }
590
1.30k
        else
591
1.30k
          if (number_colormaps > 1)
592
1.02k
            for (i=0; i < (ssize_t) image->colors; i++)
593
810
            {
594
810
              image->colormap[i].red=(MagickRealType)
595
810
                ScaleCharToQuantum(*p);
596
810
              image->colormap[i].green=(MagickRealType)
597
810
                ScaleCharToQuantum(*(p+map_length));
598
810
              image->colormap[i].blue=(MagickRealType)
599
810
                ScaleCharToQuantum(*(p+map_length*2));
600
810
              p++;
601
810
            }
602
2.53k
        p=pixels;
603
2.53k
        if ((image->alpha_trait & BlendPixelTrait) == 0)
604
2.53k
          {
605
            /*
606
              Convert raster image to PseudoClass pixel packets.
607
            */
608
333k
            for (y=0; y < (ssize_t) image->rows; y++)
609
330k
            {
610
330k
              q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
611
330k
              if (q == (Quantum *) NULL)
612
0
                break;
613
46.5M
              for (x=0; x < (ssize_t) image->columns; x++)
614
46.2M
              {
615
46.2M
                SetPixelIndex(image,(Quantum) *p++,q);
616
46.2M
                q+=(ptrdiff_t) GetPixelChannels(image);
617
46.2M
              }
618
330k
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
619
0
                break;
620
330k
              if (image->previous == (Image *) NULL)
621
116k
                {
622
116k
                  status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
623
116k
                    y,image->rows);
624
116k
                  if (status == MagickFalse)
625
0
                    break;
626
116k
                }
627
330k
            }
628
2.53k
            (void) SyncImage(image,exception);
629
2.53k
          }
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.53k
      }
672
3.23k
    if (colormap != (unsigned char *) NULL)
673
1.64k
      colormap=(unsigned char *) RelinquishMagickMemory(colormap);
674
3.23k
    pixel_info=RelinquishVirtualMemory(pixel_info);
675
3.23k
    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
3.23k
    if (image_info->number_scenes != 0)
685
55
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
686
1
        break;
687
3.23k
    (void) ReadBlobByte(image);
688
3.23k
    count=ReadBlob(image,2,(unsigned char *) magick);
689
3.23k
    if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
690
2.60k
      {
691
        /*
692
          Allocate next image structure.
693
        */
694
2.60k
        AcquireNextImage(image_info,image,exception);
695
2.60k
        if (GetNextImageInList(image) == (Image *) NULL)
696
0
          {
697
0
            status=MagickFalse;
698
0
            break;
699
0
          }
700
2.60k
        image=SyncNextImageInList(image);
701
2.60k
        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
702
2.60k
          GetBlobSize(image));
703
2.60k
        if (status == MagickFalse)
704
0
          break;
705
2.60k
      }
706
3.23k
  } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
707
639
  if (colormap != (unsigned char *) NULL)
708
0
    colormap=(unsigned char *) RelinquishMagickMemory(colormap);
709
639
  if (CloseBlob(image) == MagickFalse)
710
0
    status=MagickFalse;
711
639
  if (status == MagickFalse)
712
0
    return(DestroyImageList(image));
713
639
  return(GetFirstImageInList(image));
714
639
}
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
}