Coverage Report

Created: 2026-07-25 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/rla.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2025 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
5
%
6
% This program is covered by multiple licenses, which are described in
7
% Copyright.txt. You should have received a copy of Copyright.txt with this
8
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9
%
10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11
%                                                                             %
12
%                                                                             %
13
%                                                                             %
14
%                            RRRR   L       AAA                               %
15
%                            R   R  L      A   A                              %
16
%                            RRRR   L      AAAAA                              %
17
%                            R R    L      A   A                              %
18
%                            R  R   LLLLL  A   A                              %
19
%                                                                             %
20
%                                                                             %
21
%                     Read Alias/Wavefront Image Format.                      %
22
%                                                                             %
23
%                                                                             %
24
%                              Software Design                                %
25
%                                John Cristy                                  %
26
%                                 July 1992                                   %
27
%                                                                             %
28
%                                                                             %
29
%                                                                             %
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31
%
32
%
33
*/
34

35
/*
36
  Include declarations.
37
*/
38
#include "magick/studio.h"
39
#include "magick/attribute.h"
40
#include "magick/blob.h"
41
#include "magick/pixel_cache.h"
42
#include "magick/log.h"
43
#include "magick/magick.h"
44
#include "magick/monitor.h"
45
#include "magick/utility.h"
46
#include "magick/static.h"
47

48
/*
49
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
50
%                                                                             %
51
%                                                                             %
52
%                                                                             %
53
%   R e a d R L A I m a g e                                                   %
54
%                                                                             %
55
%                                                                             %
56
%                                                                             %
57
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
58
%
59
%  Method ReadRLAImage reads a run-length encoded Wavefront RLA image file
60
%  and returns it.  It allocates the memory necessary for the new Image
61
%  structure and returns a pointer to the new image.
62
%
63
%  Note:  This module was contributed by Lester Vecsey (master@internexus.net).
64
%
65
%  The format of the ReadRLAImage method is:
66
%
67
%      Image *ReadRLAImage(const ImageInfo *image_info,ExceptionInfo *exception)
68
%
69
%  A description of each parameter follows:
70
%
71
%    o image:  Method ReadRLAImage returns a pointer to the image after
72
%      reading.  A null image is returned if there is a memory shortage or
73
%      if the image cannot be read.
74
%
75
%    o image_info: Specifies a pointer to a ImageInfo structure.
76
%
77
%    o exception: return any errors or warnings in this structure.
78
%
79
%
80
*/
81
11.9k
#define NULLTerminateASCIIField(field) \
82
11.9k
{ \
83
11.9k
    field[sizeof(field)-1]='\0'; \
84
11.9k
}
85
86
549
#define ThrowRLAReaderException(code_,reason_,image_) \
87
707
do { \
88
707
  MagickFreeResourceLimitedMemory(magick_uint32_t *,scanlines); \
89
707
  ThrowReaderException(code_,reason_,image_); \
90
0
} while (0);
91
static Image *ReadRLAImage(const ImageInfo *image_info,ExceptionInfo *exception)
92
786
{
93
786
  typedef struct _WindowFrame
94
786
  {
95
786
    short
96
786
      left,
97
786
      right,
98
786
      bottom,
99
786
      top;
100
786
  } WindowFrame;
101
102
786
  typedef struct _RLAInfo
103
786
  {
104
786
    WindowFrame
105
786
      window,
106
786
      active_window;
107
108
786
    magick_uint16_t
109
786
      frame,
110
786
      storage_type,
111
786
      number_channels,
112
786
      number_matte_channels,
113
786
      number_auxiliary_channels,
114
786
      revision; /* aux_mask in RLB */
115
116
786
    char
117
786
      gamma[16],
118
786
      red_primary[24],
119
786
      green_primary[24],
120
786
      blue_primary[24],
121
786
      white_point[24];
122
123
786
    magick_uint32_t
124
786
      job_number;
125
126
786
    char
127
786
      name[128],
128
786
      description[128],
129
786
      program[64],
130
786
      machine[32],
131
786
      user[32],
132
786
      date[20],
133
786
      aspect[24],
134
786
      aspect_ratio[8],
135
786
      chan[32];
136
137
786
    magick_uint16_t
138
786
      field;
139
140
    /* RLB varies after this point */
141
142
786
  } RLAInfo;
143
144
786
  typedef struct _RLA3ExtraInfo
145
786
  {
146
786
    char
147
786
      time[12],
148
786
      filter[32];
149
150
786
    magick_uint16_t
151
786
      bits_per_channel,
152
786
      matte_type,
153
786
      matte_bits,
154
786
      auxiliary_type,
155
786
      auxiliary_bits;
156
157
786
    char
158
786
      auxiliary[32],
159
786
      space[36];
160
161
786
    magick_uint32_t
162
786
      next;
163
786
  } RLA3ExtraInfo;
164
165
786
  typedef struct _RLBExtraInfo
166
786
  {
167
786
    magick_uint16_t
168
786
      filter_type;
169
170
786
    magick_uint32_t
171
786
      magic_number,
172
786
      lut_size,
173
786
      user_space_size,
174
786
      wf_space_size;
175
176
786
    magick_uint16_t
177
786
      lut_type,
178
786
      mix_type,
179
786
      encode_type,
180
786
      padding;
181
182
786
    char
183
786
      space[100];
184
786
  } RLBExtraInfo;
185
186
786
  Image
187
786
    *image;
188
189
786
  int
190
786
    channel,
191
786
    length,
192
786
    number_channels,
193
786
    runlength;
194
195
786
  unsigned long
196
786
    y;
197
198
786
  magick_uint32_t
199
786
    *scanlines=0;
200
201
786
  register unsigned long
202
786
    i,
203
786
    x;
204
205
786
  register PixelPacket
206
786
    *q;
207
208
786
  RLAInfo
209
786
    rla_info;
210
211
786
  RLA3ExtraInfo
212
786
    rla3_extra_info;
213
214
786
  RLBExtraInfo
215
786
    rlb_extra_info;
216
217
786
  MagickBool
218
786
    is_rla3;
219
220
786
  int
221
786
    byte;
222
223
786
  MagickPassFail
224
786
    status;
225
226
786
  magick_off_t
227
786
    current_offset,
228
786
    file_size;
229
230
  /*
231
    Open image file.
232
  */
233
786
  assert(image_info != (const ImageInfo *) NULL);
234
786
  assert(image_info->signature == MagickSignature);
235
786
  assert(exception != (ExceptionInfo *) NULL);
236
786
  assert(exception->signature == MagickSignature);
237
786
  image=AllocateImage(image_info);
238
786
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
239
786
  if (status == MagickFail)
240
786
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
241
786
  file_size=GetBlobSize(image);
242
786
  is_rla3=MagickFalse;
243
786
  memset(&rla_info,0,sizeof(rla_info));
244
786
  memset(&rla3_extra_info,0,sizeof(rla3_extra_info));
245
786
  memset(&rlb_extra_info,0,sizeof(rlb_extra_info));
246
786
  rla_info.window.left=ReadBlobMSBShort(image);
247
786
  rla_info.window.right=ReadBlobMSBShort(image);
248
786
  rla_info.window.bottom=ReadBlobMSBShort(image);
249
786
  rla_info.window.top=ReadBlobMSBShort(image);
250
786
  rla_info.active_window.left=ReadBlobMSBShort(image);
251
786
  rla_info.active_window.right=ReadBlobMSBShort(image);
252
786
  rla_info.active_window.bottom=ReadBlobMSBShort(image);
253
786
  rla_info.active_window.top=ReadBlobMSBShort(image);
254
786
  rla_info.frame=ReadBlobMSBShort(image);
255
786
  rla_info.storage_type=ReadBlobMSBShort(image);
256
786
  rla_info.number_channels=ReadBlobMSBShort(image);
257
786
  rla_info.number_matte_channels=ReadBlobMSBShort(image);
258
786
  if (rla_info.number_channels == 0)
259
498
    rla_info.number_channels=3;
260
786
  rla_info.number_auxiliary_channels=ReadBlobMSBShort(image);
261
786
  rla_info.revision=ReadBlobMSBShort(image);
262
786
  if (rla_info.revision == 0xFFFE)
263
52
    is_rla3=MagickTrue;
264
786
  (void) ReadBlob(image,16,(char *) rla_info.gamma);
265
786
  NULLTerminateASCIIField(rla_info.gamma);
266
786
  (void) ReadBlob(image,24,(char *) rla_info.red_primary);
267
786
  NULLTerminateASCIIField(rla_info.red_primary);
268
786
  (void) ReadBlob(image,24,(char *) rla_info.green_primary);
269
786
  NULLTerminateASCIIField(rla_info.green_primary)
270
786
  (void) ReadBlob(image,24,(char *) rla_info.blue_primary);
271
786
  NULLTerminateASCIIField(rla_info.blue_primary);
272
786
  (void) ReadBlob(image,24,(char *) rla_info.white_point);
273
786
  NULLTerminateASCIIField(rla_info.white_point);
274
786
  rla_info.job_number=(long) ReadBlobMSBLong(image);
275
786
  (void) ReadBlob(image,128,(char *) rla_info.name);
276
786
  NULLTerminateASCIIField(rla_info.name);
277
786
  (void) ReadBlob(image,128,(char *) rla_info.description);
278
786
  NULLTerminateASCIIField(rla_info.description);
279
786
  (void) ReadBlob(image,64,(char *) rla_info.program);
280
786
  NULLTerminateASCIIField(rla_info.program);
281
786
  (void) ReadBlob(image,32,(char *) rla_info.machine);
282
786
  NULLTerminateASCIIField(rla_info.machine);
283
786
  (void) ReadBlob(image,32,(char *) rla_info.user);
284
786
  NULLTerminateASCIIField(rla_info.user);
285
786
  (void) ReadBlob(image,20,(char *) rla_info.date);
286
786
  NULLTerminateASCIIField(rla_info.date);
287
786
  (void) ReadBlob(image,24,(char *) rla_info.aspect);
288
786
  NULLTerminateASCIIField(rla_info.aspect);
289
786
  (void) ReadBlob(image,8,(char *) rla_info.aspect_ratio);
290
786
  NULLTerminateASCIIField(rla_info.aspect_ratio);
291
786
  (void) ReadBlob(image,32,(char *) rla_info.chan);
292
786
  NULLTerminateASCIIField(rla_info.chan);
293
786
  rla_info.field=ReadBlobMSBShort(image);
294
786
  if (is_rla3)
295
52
    {
296
52
      (void) ReadBlob(image,12,(char *) rla3_extra_info.time);
297
52
      NULLTerminateASCIIField(rla3_extra_info.time);
298
52
      (void) ReadBlob(image,32,(char *) rla3_extra_info.filter);
299
52
      NULLTerminateASCIIField(rla3_extra_info.filter);
300
52
      rla3_extra_info.bits_per_channel=ReadBlobMSBShort(image);
301
52
      rla3_extra_info.matte_type=ReadBlobMSBShort(image);
302
52
      rla3_extra_info.matte_bits=ReadBlobMSBShort(image);
303
52
      rla3_extra_info.auxiliary_type=ReadBlobMSBShort(image);
304
52
      rla3_extra_info.auxiliary_bits=ReadBlobMSBShort(image);
305
52
      (void) ReadBlob(image,32,(char *) rla3_extra_info.auxiliary);
306
52
      NULLTerminateASCIIField(rla3_extra_info.auxiliary);
307
52
      (void) ReadBlob(image,36,(char *) rla3_extra_info.space);
308
52
      NULLTerminateASCIIField(rla3_extra_info.space);
309
52
      rla3_extra_info.next=(long) ReadBlobMSBLong(image);
310
52
    }
311
734
  else
312
734
    {
313
734
      rlb_extra_info.filter_type=ReadBlobMSBShort(image);
314
734
      rlb_extra_info.magic_number=ReadBlobMSBLong(image);
315
734
      rlb_extra_info.lut_size=ReadBlobMSBLong(image);
316
734
      rlb_extra_info.user_space_size=ReadBlobMSBLong(image);
317
734
      rlb_extra_info.wf_space_size=ReadBlobMSBLong(image);
318
734
      rlb_extra_info.lut_type=ReadBlobMSBShort(image);
319
734
      rlb_extra_info.mix_type=ReadBlobMSBShort(image);
320
734
      rlb_extra_info.encode_type=ReadBlobMSBShort(image);
321
734
      rlb_extra_info.padding=ReadBlobMSBShort(image);
322
734
      (void) ReadBlob(image,100,(char *) rlb_extra_info.space);
323
734
      NULLTerminateASCIIField(rlb_extra_info.space);
324
734
    }
325
786
  if (EOFBlob(image))
326
667
    ThrowRLAReaderException(CorruptImageError,UnexpectedEndOfFile,image);
327
328
  /*
329
    Verify revision.
330
  */
331
332
/*   if (rla3_extra_info.revision != 0xFFFE) */
333
/*     ThrowRLAReaderException(CorruptImageError,ImproperImageHeader,image); */
334
335
  /*
336
    Verify dimensions.
337
  */
338
667
  if (image->logging)
339
667
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
340
667
                          "Active Window  : Left=%d Right=%d Top=%d, Bottom=%d",
341
667
                          (int) rla_info.active_window.left,
342
667
                          (int) rla_info.active_window.right,
343
667
                          (int) rla_info.active_window.top,
344
667
                          (int) rla_info.active_window.bottom);
345
667
  if ((((long) rla_info.active_window.right - rla_info.active_window.left) < 0) ||
346
666
      (((long) rla_info.active_window.top-rla_info.active_window.bottom) < 0))
347
663
    ThrowRLAReaderException(CorruptImageError,ImproperImageHeader,image);
348
349
663
  if (image->logging)
350
663
    {
351
663
      const char
352
663
        *storage_type = "Unknown";
353
354
663
      switch (rla_info.storage_type)
355
663
        {
356
640
        case 0:
357
640
          storage_type = "INT8";
358
640
          break;
359
1
        case 1:
360
1
          storage_type = "INT16";
361
1
          break;
362
0
        case 2:
363
0
          storage_type = "INT32";
364
0
          break;
365
1
        case 3:
366
1
          storage_type = "FLOAT32";
367
1
          break;
368
663
        }
369
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
370
663
                            "Storage Type   : %s",storage_type);
371
372
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
373
663
                            "Color Channels : %u", (unsigned int) rla_info.number_channels);
374
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
375
663
                            "Matte Channels : %u", (unsigned int) rla_info.number_matte_channels);
376
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
377
663
                            "Aux Channels   : %u", (unsigned int) rla_info.number_auxiliary_channels);
378
663
      if (is_rla3)
379
46
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
380
46
                              "Format Revision: 0x%04X", rla_info.revision);
381
617
      else
382
617
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
383
617
                              "Aux Mask       : 0x%04X", rla_info.revision);
384
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
385
663
                            "Gamma          : %.16s", rla_info.gamma);
386
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
387
663
                            "Red Primary    : %.24s", rla_info.red_primary);
388
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
389
663
                            "Green Primary  : %.24s", rla_info.green_primary);
390
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
391
663
                            "Blue Primary   : %.24s", rla_info.blue_primary);
392
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
393
663
                            "White Point    : %.24s", rla_info.white_point);
394
395
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
396
663
                            "Job Number     : %u", (unsigned int) rla_info.job_number);
397
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
398
663
                            "Name           : %.128s", rla_info.name);
399
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
400
663
                            "Description    : %.128s", rla_info.description);
401
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
402
663
                            "Program        : %.64s", rla_info.program);
403
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
404
663
                            "Machine        : %.32s", rla_info.machine);
405
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
406
663
                            "User           : %.32s", rla_info.user);
407
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
408
663
                            "Date           : %.20s", rla_info.date);
409
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
410
663
                            "Aspect         : %.128s", rla_info.aspect);
411
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
412
663
                            "Aspect Ratio   : %.8s", rla_info.aspect_ratio);
413
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
414
663
                            "Colorspace     : %.32s", rla_info.chan);
415
416
663
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
417
663
                            "Field          : %u",  (unsigned int) rla_info.field);
418
419
663
      if (is_rla3)
420
46
        {
421
46
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
422
46
                                "Time           : %.12s", rla3_extra_info.time);
423
46
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
424
46
                                "Filter         : %.32s", rla3_extra_info.filter);
425
426
46
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
427
46
                                "BitsPerChannel : %u", rla3_extra_info.bits_per_channel);
428
46
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
429
46
                                "MatteType      : %u", rla3_extra_info.matte_type);
430
46
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
431
46
                                "MatteBits      : %u", rla3_extra_info.matte_bits);
432
46
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
433
46
                                "AuxType        : %u", rla3_extra_info.auxiliary_type);
434
46
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
435
46
                                "AuxBits        : %u", rla3_extra_info.auxiliary_bits);
436
46
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
437
46
                                "AuxData        : %.32s", rla3_extra_info.auxiliary);
438
46
        }
439
617
      else
440
617
        {
441
617
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
442
617
                                "FilterType     : %u", rlb_extra_info.filter_type);
443
617
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
444
617
                                "MagickNumber   : %u", rlb_extra_info.magic_number);
445
617
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
446
617
                                "LUT Size       : %u", rlb_extra_info.lut_size);
447
617
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
448
617
                                "User Space     : %u", rlb_extra_info.user_space_size);
449
617
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
450
617
                                "WF Space       : %u", rlb_extra_info.wf_space_size);
451
617
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
452
617
                                "LUT Type       : %u", rlb_extra_info.lut_type);
453
617
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
454
617
                                "MIX Type       : %u", rlb_extra_info.mix_type);
455
617
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
456
617
                                "Encode Type    : %u", rlb_extra_info.encode_type);
457
617
        }
458
663
    }
459
460
663
  if ((rla_info.storage_type != 0) || (rla_info.storage_type > 3))
461
640
    ThrowRLAReaderException(CorruptImageError,ImproperImageHeader,image);
462
463
640
  if (rla_info.storage_type != 0)
464
640
    ThrowRLAReaderException(CoderError,DataStorageTypeIsNotSupported,image);
465
466
640
  if (LocaleNCompare(rla_info.chan,"rgb",3) != 0)
467
616
    ThrowRLAReaderException(CoderError,ColorTypeNotSupported,image);
468
469
616
  if (rla_info.number_channels > 3)
470
16
    {
471
16
      if (image->logging)
472
16
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
473
16
                                  "Unsupported number of color channels: %u",
474
16
                                  rla_info.number_channels);
475
16
      ThrowRLAReaderException(CorruptImageError,UnsupportedNumberOfPlanes,image);
476
0
    }
477
600
  if (rla_info.number_matte_channels > 1)
478
14
    {
479
14
      if (image->logging)
480
14
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
481
14
                                  "Unsupported number of matte channels: %u",
482
14
                                  rla_info.number_matte_channels);
483
14
      ThrowRLAReaderException(CorruptImageError,UnsupportedNumberOfPlanes,image);
484
0
    }
485
486
  /*
487
    Initialize image structure.
488
  */
489
586
  image->matte=(rla_info.number_matte_channels != 0 ? MagickTrue: MagickFalse);
490
586
  image->columns=rla_info.active_window.right-rla_info.active_window.left+1;
491
586
  image->rows=rla_info.active_window.top-rla_info.active_window.bottom+1;
492
493
586
  if (image->logging)
494
586
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
495
586
                          "Dimensions     : %lux%lu",image->columns,image->rows);
496
497
586
  if (image_info->ping)
498
0
    {
499
0
      CloseBlob(image);
500
0
      return(image);
501
0
    }
502
503
586
  if (CheckImagePixelLimits(image, exception) != MagickPass)
504
565
    ThrowRLAReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
505
506
565
  number_channels=rla_info.number_channels+rla_info.number_matte_channels;
507
565
  scanlines=MagickAllocateResourceLimitedArray(magick_uint32_t *,image->rows,sizeof(magick_uint32_t));
508
565
  if (scanlines == (magick_uint32_t *) NULL)
509
565
    ThrowRLAReaderException(ResourceLimitError,MemoryAllocationFailed,image);
510
565
  if (*rla_info.description != '\0')
511
288
    (void) SetImageAttribute(image,"comment",rla_info.description);
512
  /*
513
    Read offsets to each scanline data.
514
  */
515
565
  current_offset=TellBlob(image);
516
63.6k
  for (i=0; i < image->rows; i++)
517
63.2k
    {
518
63.2k
      scanlines[i]=(magick_uint32_t) ReadBlobMSBLong(image);
519
#if 0
520
      if (image->logging)
521
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
522
                              "scanline[%ld] = %lu",i,(unsigned long) scanlines[i]);
523
#endif
524
63.2k
      if ((magick_off_t) scanlines[i] > file_size)
525
37
        {
526
37
          if (image->logging)
527
37
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
528
37
                                  "scanline[%ld] offset %lu is beyond end of file",
529
37
                                  i,(unsigned long) scanlines[i]);
530
37
          ThrowRLAReaderException(CorruptImageError,UnexpectedEndOfFile,image);
531
0
        }
532
63.1k
      if ((magick_off_t) scanlines[i] < current_offset)
533
91
        {
534
91
          if (image->logging)
535
91
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
536
91
                                  "scanline[%ld] offset %lu is too small!",
537
91
                                  i,(unsigned long) scanlines[i]);
538
91
          ThrowRLAReaderException(CorruptImageError,ImproperImageHeader,image);
539
0
        }
540
63.0k
      if ((i != 0) && (scanlines[i-1] == scanlines[i]))
541
19.9k
        {
542
19.9k
          if (image->logging)
543
19.9k
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
544
19.9k
                                  "scanline[%ld] offset %lu is a duplicate!",
545
19.9k
                                  i,(unsigned long) scanlines[i]);
546
19.9k
        }
547
63.0k
    }
548
437
  if (EOFBlob(image))
549
437
    ThrowRLAReaderException(CorruptImageError,UnexpectedEndOfFile,image);
550
  /*
551
    Read image data.
552
  */
553
437
  x=0;
554
44.0k
  for (y=0; y < image->rows; y++)
555
43.9k
  {
556
43.9k
    if (SeekBlob(image,scanlines[image->rows-y-1],SEEK_SET) == -1)
557
0
      {
558
0
        if (image->logging)
559
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
560
0
                                "Failed seek to %lu",
561
0
                                (unsigned long) image->rows-y-1);
562
0
        status=MagickFail;
563
0
        break;
564
0
      }
565
171k
    for (channel=0; channel < number_channels; channel++)
566
127k
    {
567
127k
      length=ReadBlobMSBShort(image);
568
24.2M
      while (length > 0)
569
24.1M
      {
570
24.1M
        if ((byte=ReadBlobByte(image)) == EOF)
571
202
          {
572
202
            status=MagickFail;
573
202
            break;
574
202
          }
575
24.1M
        runlength=byte;
576
24.1M
        if (byte > 127)
577
87.8k
          runlength=byte-256;
578
24.1M
        length--;
579
24.1M
        if (length == 0)
580
29.9k
          break;
581
24.1M
        if (runlength < 0)
582
87.7k
          {
583
2.45M
            while (runlength < 0)
584
2.36M
            {
585
2.36M
              if (x > image->rows*image->columns*number_channels)
586
2.36M
                  ThrowRLAReaderException(CorruptImageError,UnableToRunlengthDecodeImage,image);
587
2.36M
              q=GetImagePixels(image,(long) (x % image->columns),
588
2.36M
                               (long) (y % image->columns),1,1);
589
2.36M
              if (q == (PixelPacket *) NULL)
590
0
                {
591
0
                  status=MagickFail;
592
0
                  break;
593
0
                }
594
2.36M
              if ((byte=ReadBlobByte(image)) == EOF)
595
100
                {
596
100
                  status=MagickFail;
597
100
                  break;
598
100
                }
599
2.36M
              length--;
600
2.36M
              switch (channel)
601
2.36M
              {
602
217k
                case 0:
603
217k
                {
604
217k
                  q->red=ScaleCharToQuantum(byte);
605
217k
                  break;
606
0
                }
607
1.31M
                case 1:
608
1.31M
                {
609
1.31M
                  q->green=ScaleCharToQuantum(byte);
610
1.31M
                  break;
611
0
                }
612
159k
                case 2:
613
159k
                {
614
159k
                  q->blue=ScaleCharToQuantum(byte);
615
159k
                  break;
616
0
                }
617
668k
                case 3:
618
668k
                {
619
668k
                  q->opacity=(Quantum) (MaxRGB-ScaleCharToQuantum(byte));
620
668k
                  break;
621
0
                }
622
0
                default:
623
0
                {
624
                  /* Depth channel ? */
625
0
                  break;
626
0
                }
627
2.36M
              }
628
2.36M
              if (!SyncImagePixels(image))
629
0
                {
630
0
                  status=MagickFail;
631
0
                  break;
632
0
                }
633
2.36M
              x++;
634
2.36M
              runlength++;
635
2.36M
            }
636
87.7k
            continue;
637
87.7k
          }
638
24.0M
        if ((byte=ReadBlobByte(image)) == EOF)
639
59
          {
640
59
            status=MagickFail;
641
59
            break;
642
59
          }
643
24.0M
        length--;
644
24.0M
        runlength++;
645
24.0M
        do
646
79.8M
        {
647
79.8M
          if (x > image->rows*image->columns*number_channels)
648
79.8M
            ThrowRLAReaderException(CorruptImageError,UnableToRunlengthDecodeImage,image);
649
79.8M
          q=GetImagePixels(image,(long) (x % image->columns),
650
79.8M
            (long) (y % image->columns),1,1);
651
79.8M
          if (q == (PixelPacket *) NULL)
652
0
            {
653
0
              status=MagickFail;
654
0
              break;
655
0
            }
656
79.8M
          switch (channel)
657
79.8M
          {
658
2.34M
            case 0:
659
2.34M
            {
660
2.34M
              q->red=ScaleCharToQuantum(byte);
661
2.34M
              break;
662
0
            }
663
64.5M
            case 1:
664
64.5M
            {
665
64.5M
              q->green=ScaleCharToQuantum(byte);
666
64.5M
              break;
667
0
            }
668
4.90M
            case 2:
669
4.90M
            {
670
4.90M
              q->blue=ScaleCharToQuantum(byte);
671
4.90M
              break;
672
0
            }
673
8.11M
            case 3:
674
8.11M
            {
675
8.11M
              q->opacity=(Quantum) (MaxRGB-ScaleCharToQuantum(byte));
676
8.11M
              break;
677
0
            }
678
0
          default:
679
0
            {
680
              /* Depth channel ? */
681
0
              break;
682
0
            }
683
79.8M
          }
684
79.8M
          if (!SyncImagePixels(image))
685
0
            {
686
0
              status=MagickFail;
687
0
              break;
688
0
            }
689
79.8M
          x++;
690
79.8M
          runlength--;
691
79.8M
        }
692
79.8M
        while (runlength > 0);
693
694
24.0M
        if (MagickFail == status)
695
0
          break;
696
24.0M
      }
697
127k
      if (MagickFail == status)
698
284
        break;
699
127k
    }
700
43.9k
    if (QuantumTick(y,image->rows))
701
14.3k
      if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText,
702
14.3k
                                  image->filename,
703
14.3k
                                  image->columns,image->rows))
704
0
        {
705
0
          status=MagickFail;
706
0
          break;
707
0
        }
708
43.9k
    if (MagickFail == status)
709
284
      break;
710
43.9k
  }
711
418
  if (EOFBlob(image))
712
339
    ThrowRLAReaderException(CorruptImageError,UnexpectedEndOfFile,image);
713
79
  CloseBlob(image);
714
79
  MagickFreeResourceLimitedMemory(magick_uint32_t *,scanlines);
715
79
  StopTimer(&image->timer);
716
79
  return(image);
717
418
}
718

719
/*
720
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721
%                                                                             %
722
%                                                                             %
723
%                                                                             %
724
%   R e g i s t e r R L A I m a g e                                           %
725
%                                                                             %
726
%                                                                             %
727
%                                                                             %
728
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
729
%
730
%  Method RegisterRLAImage adds attributes for the RLA image format to
731
%  the list of supported formats.  The attributes include the image format
732
%  tag, a method to read and/or write the format, whether the format
733
%  supports the saving of more than one frame to the same file or blob,
734
%  whether the format supports native in-memory I/O, and a brief
735
%  description of the format.
736
%
737
%  The format of the RegisterRLAImage method is:
738
%
739
%      RegisterRLAImage(void)
740
%
741
*/
742
ModuleExport void RegisterRLAImage(void)
743
1
{
744
1
  MagickInfo
745
1
    *entry;
746
747
1
  entry=SetMagickInfo("RLA");
748
1
  entry->decoder=(DecoderHandler) ReadRLAImage;
749
1
  entry->adjoin=False;
750
1
  entry->description="Alias/Wavefront image";
751
1
  entry->seekable_stream=MagickTrue;
752
1
  entry->module="RLA";
753
1
  entry->coder_class=UnstableCoderClass;
754
1
  (void) RegisterMagickInfo(entry);
755
1
}
756

757
/*
758
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
759
%                                                                             %
760
%                                                                             %
761
%                                                                             %
762
%   U n r e g i s t e r R L A I m a g e                                       %
763
%                                                                             %
764
%                                                                             %
765
%                                                                             %
766
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
767
%
768
%  Method UnregisterRLAImage removes format registrations made by the
769
%  RLA module from the list of supported formats.
770
%
771
%  The format of the UnregisterRLAImage method is:
772
%
773
%      UnregisterRLAImage(void)
774
%
775
*/
776
ModuleExport void UnregisterRLAImage(void)
777
0
{
778
0
  (void) UnregisterMagickInfo("RLA");
779
0
}