Coverage Report

Created: 2026-03-31 06:56

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