Coverage Report

Created: 2026-01-20 07:37

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.3k
#define NULLTerminateASCIIField(field) \
82
11.3k
{ \
83
11.3k
    field[sizeof(field)-1]='\0'; \
84
11.3k
}
85
86
521
#define ThrowRLAReaderException(code_,reason_,image_) \
87
675
do { \
88
675
  MagickFreeResourceLimitedMemory(magick_uint32_t *,scanlines); \
89
675
  ThrowReaderException(code_,reason_,image_); \
90
0
} while (0);
91
static Image *ReadRLAImage(const ImageInfo *image_info,ExceptionInfo *exception)
92
749
{
93
749
  typedef struct _WindowFrame
94
749
  {
95
749
    short
96
749
      left,
97
749
      right,
98
749
      bottom,
99
749
      top;
100
749
  } WindowFrame;
101
102
749
  typedef struct _RLAInfo
103
749
  {
104
749
    WindowFrame
105
749
      window,
106
749
      active_window;
107
108
749
    magick_uint16_t
109
749
      frame,
110
749
      storage_type,
111
749
      number_channels,
112
749
      number_matte_channels,
113
749
      number_auxiliary_channels,
114
749
      revision; /* aux_mask in RLB */
115
116
749
    char
117
749
      gamma[16],
118
749
      red_primary[24],
119
749
      green_primary[24],
120
749
      blue_primary[24],
121
749
      white_point[24];
122
123
749
    magick_uint32_t
124
749
      job_number;
125
126
749
    char
127
749
      name[128],
128
749
      description[128],
129
749
      program[64],
130
749
      machine[32],
131
749
      user[32],
132
749
      date[20],
133
749
      aspect[24],
134
749
      aspect_ratio[8],
135
749
      chan[32];
136
137
749
    magick_uint16_t
138
749
      field;
139
140
    /* RLB varies after this point */
141
142
749
  } RLAInfo;
143
144
749
  typedef struct _RLA3ExtraInfo
145
749
  {
146
749
    char
147
749
      time[12],
148
749
      filter[32];
149
150
749
    magick_uint16_t
151
749
      bits_per_channel,
152
749
      matte_type,
153
749
      matte_bits,
154
749
      auxiliary_type,
155
749
      auxiliary_bits;
156
157
749
    char
158
749
      auxiliary[32],
159
749
      space[36];
160
161
749
    magick_uint32_t
162
749
      next;
163
749
  } RLA3ExtraInfo;
164
165
749
  typedef struct _RLBExtraInfo
166
749
  {
167
749
    magick_uint16_t
168
749
      filter_type;
169
170
749
    magick_uint32_t
171
749
      magic_number,
172
749
      lut_size,
173
749
      user_space_size,
174
749
      wf_space_size;
175
176
749
    magick_uint16_t
177
749
      lut_type,
178
749
      mix_type,
179
749
      encode_type,
180
749
      padding;
181
182
749
    char
183
749
      space[100];
184
749
  } RLBExtraInfo;
185
186
749
  Image
187
749
    *image;
188
189
749
  int
190
749
    channel,
191
749
    length,
192
749
    number_channels,
193
749
    runlength;
194
195
749
  unsigned long
196
749
    y;
197
198
749
  magick_uint32_t
199
749
    *scanlines=0;
200
201
749
  register unsigned long
202
749
    i,
203
749
    x;
204
205
749
  register PixelPacket
206
749
    *q;
207
208
749
  RLAInfo
209
749
    rla_info;
210
211
749
  RLA3ExtraInfo
212
749
    rla3_extra_info;
213
214
749
  RLBExtraInfo
215
749
    rlb_extra_info;
216
217
749
  MagickBool
218
749
    is_rla3;
219
220
749
  int
221
749
    byte;
222
223
749
  MagickPassFail
224
749
    status;
225
226
749
  magick_off_t
227
749
    current_offset,
228
749
    file_size;
229
230
  /*
231
    Open image file.
232
  */
233
749
  assert(image_info != (const ImageInfo *) NULL);
234
749
  assert(image_info->signature == MagickSignature);
235
749
  assert(exception != (ExceptionInfo *) NULL);
236
749
  assert(exception->signature == MagickSignature);
237
749
  image=AllocateImage(image_info);
238
749
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
239
749
  if (status == MagickFail)
240
749
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
241
749
  file_size=GetBlobSize(image);
242
749
  is_rla3=MagickFalse;
243
749
  memset(&rla_info,0,sizeof(rla_info));
244
749
  memset(&rla3_extra_info,0,sizeof(rla3_extra_info));
245
749
  memset(&rlb_extra_info,0,sizeof(rlb_extra_info));
246
749
  rla_info.window.left=ReadBlobMSBShort(image);
247
749
  rla_info.window.right=ReadBlobMSBShort(image);
248
749
  rla_info.window.bottom=ReadBlobMSBShort(image);
249
749
  rla_info.window.top=ReadBlobMSBShort(image);
250
749
  rla_info.active_window.left=ReadBlobMSBShort(image);
251
749
  rla_info.active_window.right=ReadBlobMSBShort(image);
252
749
  rla_info.active_window.bottom=ReadBlobMSBShort(image);
253
749
  rla_info.active_window.top=ReadBlobMSBShort(image);
254
749
  rla_info.frame=ReadBlobMSBShort(image);
255
749
  rla_info.storage_type=ReadBlobMSBShort(image);
256
749
  rla_info.number_channels=ReadBlobMSBShort(image);
257
749
  rla_info.number_matte_channels=ReadBlobMSBShort(image);
258
749
  if (rla_info.number_channels == 0)
259
476
    rla_info.number_channels=3;
260
749
  rla_info.number_auxiliary_channels=ReadBlobMSBShort(image);
261
749
  rla_info.revision=ReadBlobMSBShort(image);
262
749
  if (rla_info.revision == 0xFFFE)
263
41
    is_rla3=MagickTrue;
264
749
  (void) ReadBlob(image,16,(char *) rla_info.gamma);
265
749
  NULLTerminateASCIIField(rla_info.gamma);
266
749
  (void) ReadBlob(image,24,(char *) rla_info.red_primary);
267
749
  NULLTerminateASCIIField(rla_info.red_primary);
268
749
  (void) ReadBlob(image,24,(char *) rla_info.green_primary);
269
749
  NULLTerminateASCIIField(rla_info.green_primary)
270
749
  (void) ReadBlob(image,24,(char *) rla_info.blue_primary);
271
749
  NULLTerminateASCIIField(rla_info.blue_primary);
272
749
  (void) ReadBlob(image,24,(char *) rla_info.white_point);
273
749
  NULLTerminateASCIIField(rla_info.white_point);
274
749
  rla_info.job_number=(long) ReadBlobMSBLong(image);
275
749
  (void) ReadBlob(image,128,(char *) rla_info.name);
276
749
  NULLTerminateASCIIField(rla_info.name);
277
749
  (void) ReadBlob(image,128,(char *) rla_info.description);
278
749
  NULLTerminateASCIIField(rla_info.description);
279
749
  (void) ReadBlob(image,64,(char *) rla_info.program);
280
749
  NULLTerminateASCIIField(rla_info.program);
281
749
  (void) ReadBlob(image,32,(char *) rla_info.machine);
282
749
  NULLTerminateASCIIField(rla_info.machine);
283
749
  (void) ReadBlob(image,32,(char *) rla_info.user);
284
749
  NULLTerminateASCIIField(rla_info.user);
285
749
  (void) ReadBlob(image,20,(char *) rla_info.date);
286
749
  NULLTerminateASCIIField(rla_info.date);
287
749
  (void) ReadBlob(image,24,(char *) rla_info.aspect);
288
749
  NULLTerminateASCIIField(rla_info.aspect);
289
749
  (void) ReadBlob(image,8,(char *) rla_info.aspect_ratio);
290
749
  NULLTerminateASCIIField(rla_info.aspect_ratio);
291
749
  (void) ReadBlob(image,32,(char *) rla_info.chan);
292
749
  NULLTerminateASCIIField(rla_info.chan);
293
749
  rla_info.field=ReadBlobMSBShort(image);
294
749
  if (is_rla3)
295
41
    {
296
41
      (void) ReadBlob(image,12,(char *) rla3_extra_info.time);
297
41
      NULLTerminateASCIIField(rla3_extra_info.time);
298
41
      (void) ReadBlob(image,32,(char *) rla3_extra_info.filter);
299
41
      NULLTerminateASCIIField(rla3_extra_info.filter);
300
41
      rla3_extra_info.bits_per_channel=ReadBlobMSBShort(image);
301
41
      rla3_extra_info.matte_type=ReadBlobMSBShort(image);
302
41
      rla3_extra_info.matte_bits=ReadBlobMSBShort(image);
303
41
      rla3_extra_info.auxiliary_type=ReadBlobMSBShort(image);
304
41
      rla3_extra_info.auxiliary_bits=ReadBlobMSBShort(image);
305
41
      (void) ReadBlob(image,32,(char *) rla3_extra_info.auxiliary);
306
41
      NULLTerminateASCIIField(rla3_extra_info.auxiliary);
307
41
      (void) ReadBlob(image,36,(char *) rla3_extra_info.space);
308
41
      NULLTerminateASCIIField(rla3_extra_info.space);
309
41
      rla3_extra_info.next=(long) ReadBlobMSBLong(image);
310
41
    }
311
708
  else
312
708
    {
313
708
      rlb_extra_info.filter_type=ReadBlobMSBShort(image);
314
708
      rlb_extra_info.magic_number=ReadBlobMSBLong(image);
315
708
      rlb_extra_info.lut_size=ReadBlobMSBLong(image);
316
708
      rlb_extra_info.user_space_size=ReadBlobMSBLong(image);
317
708
      rlb_extra_info.wf_space_size=ReadBlobMSBLong(image);
318
708
      rlb_extra_info.lut_type=ReadBlobMSBShort(image);
319
708
      rlb_extra_info.mix_type=ReadBlobMSBShort(image);
320
708
      rlb_extra_info.encode_type=ReadBlobMSBShort(image);
321
708
      rlb_extra_info.padding=ReadBlobMSBShort(image);
322
708
      (void) ReadBlob(image,100,(char *) rlb_extra_info.space);
323
708
      NULLTerminateASCIIField(rlb_extra_info.space);
324
708
    }
325
749
  if (EOFBlob(image))
326
629
    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
629
  if (image->logging)
339
629
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
340
629
                          "Active Window  : Left=%d Right=%d Top=%d, Bottom=%d",
341
629
                          (int) rla_info.active_window.left,
342
629
                          (int) rla_info.active_window.right,
343
629
                          (int) rla_info.active_window.top,
344
629
                          (int) rla_info.active_window.bottom);
345
629
  if ((((long) rla_info.active_window.right - rla_info.active_window.left) < 0) ||
346
628
      (((long) rla_info.active_window.top-rla_info.active_window.bottom) < 0))
347
625
    ThrowRLAReaderException(CorruptImageError,ImproperImageHeader,image);
348
349
625
  if (image->logging)
350
625
    {
351
625
      const char
352
625
        *storage_type = "Unknown";
353
354
625
      switch (rla_info.storage_type)
355
625
        {
356
605
        case 0:
357
605
          storage_type = "INT8";
358
605
          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
625
        }
369
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
370
625
                            "Storage Type   : %s",storage_type);
371
372
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
373
625
                            "Color Channels : %u", (unsigned int) rla_info.number_channels);
374
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
375
625
                            "Matte Channels : %u", (unsigned int) rla_info.number_matte_channels);
376
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
377
625
                            "Aux Channels   : %u", (unsigned int) rla_info.number_auxiliary_channels);
378
625
      if (is_rla3)
379
35
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
380
35
                              "Format Revision: 0x%04X", rla_info.revision);
381
590
      else
382
590
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
383
590
                              "Aux Mask       : 0x%04X", rla_info.revision);
384
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
385
625
                            "Gamma          : %.16s", rla_info.gamma);
386
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
387
625
                            "Red Primary    : %.24s", rla_info.red_primary);
388
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
389
625
                            "Green Primary  : %.24s", rla_info.green_primary);
390
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
391
625
                            "Blue Primary   : %.24s", rla_info.blue_primary);
392
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
393
625
                            "White Point    : %.24s", rla_info.white_point);
394
395
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
396
625
                            "Job Number     : %u", (unsigned int) rla_info.job_number);
397
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
398
625
                            "Name           : %.128s", rla_info.name);
399
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
400
625
                            "Description    : %.128s", rla_info.description);
401
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
402
625
                            "Program        : %.64s", rla_info.program);
403
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
404
625
                            "Machine        : %.32s", rla_info.machine);
405
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
406
625
                            "User           : %.32s", rla_info.user);
407
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
408
625
                            "Date           : %.20s", rla_info.date);
409
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
410
625
                            "Aspect         : %.128s", rla_info.aspect);
411
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
412
625
                            "Aspect Ratio   : %.8s", rla_info.aspect_ratio);
413
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
414
625
                            "Colorspace     : %.32s", rla_info.chan);
415
416
625
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
417
625
                            "Field          : %u",  (unsigned int) rla_info.field);
418
419
625
      if (is_rla3)
420
35
        {
421
35
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
422
35
                                "Time           : %.12s", rla3_extra_info.time);
423
35
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
424
35
                                "Filter         : %.32s", rla3_extra_info.filter);
425
426
35
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
427
35
                                "BitsPerChannel : %u", rla3_extra_info.bits_per_channel);
428
35
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
429
35
                                "MatteType      : %u", rla3_extra_info.matte_type);
430
35
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
431
35
                                "MatteBits      : %u", rla3_extra_info.matte_bits);
432
35
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
433
35
                                "AuxType        : %u", rla3_extra_info.auxiliary_type);
434
35
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
435
35
                                "AuxBits        : %u", rla3_extra_info.auxiliary_bits);
436
35
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
437
35
                                "AuxData        : %.32s", rla3_extra_info.auxiliary);
438
35
        }
439
590
      else
440
590
        {
441
590
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
442
590
                                "FilterType     : %u", rlb_extra_info.filter_type);
443
590
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
444
590
                                "MagickNumber   : %u", rlb_extra_info.magic_number);
445
590
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
446
590
                                "LUT Size       : %u", rlb_extra_info.lut_size);
447
590
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
448
590
                                "User Space     : %u", rlb_extra_info.user_space_size);
449
590
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
450
590
                                "WF Space       : %u", rlb_extra_info.wf_space_size);
451
590
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
452
590
                                "LUT Type       : %u", rlb_extra_info.lut_type);
453
590
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
454
590
                                "MIX Type       : %u", rlb_extra_info.mix_type);
455
590
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
456
590
                                "Encode Type    : %u", rlb_extra_info.encode_type);
457
590
        }
458
625
    }
459
460
625
  if ((rla_info.storage_type != 0) || (rla_info.storage_type > 3))
461
605
    ThrowRLAReaderException(CorruptImageError,ImproperImageHeader,image);
462
463
605
  if (rla_info.storage_type != 0)
464
605
    ThrowRLAReaderException(CoderError,DataStorageTypeIsNotSupported,image);
465
466
605
  if (LocaleNCompare(rla_info.chan,"rgb",3) != 0)
467
586
    ThrowRLAReaderException(CoderError,ColorTypeNotSupported,image);
468
469
586
  if (rla_info.number_channels > 3)
470
15
    {
471
15
      if (image->logging)
472
15
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
473
15
                                  "Unsupported number of color channels: %u",
474
15
                                  rla_info.number_channels);
475
15
      ThrowRLAReaderException(CorruptImageError,UnsupportedNumberOfPlanes,image);
476
0
    }
477
571
  if (rla_info.number_matte_channels > 1)
478
15
    {
479
15
      if (image->logging)
480
15
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
481
15
                                  "Unsupported number of matte channels: %u",
482
15
                                  rla_info.number_matte_channels);
483
15
      ThrowRLAReaderException(CorruptImageError,UnsupportedNumberOfPlanes,image);
484
0
    }
485
486
  /*
487
    Initialize image structure.
488
  */
489
556
  image->matte=(rla_info.number_matte_channels != 0 ? MagickTrue: MagickFalse);
490
556
  image->columns=rla_info.active_window.right-rla_info.active_window.left+1;
491
556
  image->rows=rla_info.active_window.top-rla_info.active_window.bottom+1;
492
493
556
  if (image->logging)
494
556
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
495
556
                          "Dimensions     : %lux%lu",image->columns,image->rows);
496
497
556
  if (image_info->ping)
498
0
    {
499
0
      CloseBlob(image);
500
0
      return(image);
501
0
    }
502
503
556
  if (CheckImagePixelLimits(image, exception) != MagickPass)
504
535
    ThrowRLAReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
505
506
535
  number_channels=rla_info.number_channels+rla_info.number_matte_channels;
507
535
  scanlines=MagickAllocateResourceLimitedArray(magick_uint32_t *,image->rows,sizeof(magick_uint32_t));
508
535
  if (scanlines == (magick_uint32_t *) NULL)
509
535
    ThrowRLAReaderException(ResourceLimitError,MemoryAllocationFailed,image);
510
535
  if (*rla_info.description != '\0')
511
275
    (void) SetImageAttribute(image,"comment",rla_info.description);
512
  /*
513
    Read offsets to each scanline data.
514
  */
515
535
  current_offset=TellBlob(image);
516
64.2k
  for (i=0; i < image->rows; i++)
517
63.8k
    {
518
63.8k
      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.8k
      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.7k
      if ((magick_off_t) scanlines[i] < current_offset)
533
87
        {
534
87
          if (image->logging)
535
87
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
536
87
                                  "scanline[%ld] offset %lu is too small!",
537
87
                                  i,(unsigned long) scanlines[i]);
538
87
          ThrowRLAReaderException(CorruptImageError,ImproperImageHeader,image);
539
0
        }
540
63.6k
      if ((i != 0) && (scanlines[i-1] == scanlines[i]))
541
18.8k
        {
542
18.8k
          if (image->logging)
543
18.8k
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
544
18.8k
                                  "scanline[%ld] offset %lu is a duplicate!",
545
18.8k
                                  i,(unsigned long) scanlines[i]);
546
18.8k
        }
547
63.6k
    }
548
411
  if (EOFBlob(image))
549
411
    ThrowRLAReaderException(CorruptImageError,UnexpectedEndOfFile,image);
550
  /*
551
    Read image data.
552
  */
553
411
  x=0;
554
43.5k
  for (y=0; y < image->rows; y++)
555
43.4k
  {
556
43.4k
    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
170k
    for (channel=0; channel < number_channels; channel++)
566
127k
    {
567
127k
      length=ReadBlobMSBShort(image);
568
24.4M
      while (length > 0)
569
24.3M
      {
570
24.3M
        if ((byte=ReadBlobByte(image)) == EOF)
571
179
          {
572
179
            status=MagickFail;
573
179
            break;
574
179
          }
575
24.3M
        runlength=byte;
576
24.3M
        if (byte > 127)
577
163k
          runlength=byte-256;
578
24.3M
        length--;
579
24.3M
        if (length == 0)
580
32.3k
          break;
581
24.3M
        if (runlength < 0)
582
163k
          {
583
3.20M
            while (runlength < 0)
584
3.03M
            {
585
3.03M
              if (x > image->rows*image->columns*number_channels)
586
3.03M
                  ThrowRLAReaderException(CorruptImageError,UnableToRunlengthDecodeImage,image);
587
3.03M
              q=GetImagePixels(image,(long) (x % image->columns),
588
3.03M
                               (long) (y % image->columns),1,1);
589
3.03M
              if (q == (PixelPacket *) NULL)
590
0
                {
591
0
                  status=MagickFail;
592
0
                  break;
593
0
                }
594
3.03M
              if ((byte=ReadBlobByte(image)) == EOF)
595
86
                {
596
86
                  status=MagickFail;
597
86
                  break;
598
86
                }
599
3.03M
              length--;
600
3.03M
              switch (channel)
601
3.03M
              {
602
192k
                case 0:
603
192k
                {
604
192k
                  q->red=ScaleCharToQuantum(byte);
605
192k
                  break;
606
0
                }
607
1.67M
                case 1:
608
1.67M
                {
609
1.67M
                  q->green=ScaleCharToQuantum(byte);
610
1.67M
                  break;
611
0
                }
612
392k
                case 2:
613
392k
                {
614
392k
                  q->blue=ScaleCharToQuantum(byte);
615
392k
                  break;
616
0
                }
617
779k
                case 3:
618
779k
                {
619
779k
                  q->opacity=(Quantum) (MaxRGB-ScaleCharToQuantum(byte));
620
779k
                  break;
621
0
                }
622
0
                default:
623
0
                {
624
                  /* Depth channel ? */
625
0
                  break;
626
0
                }
627
3.03M
              }
628
3.03M
              if (!SyncImagePixels(image))
629
0
                {
630
0
                  status=MagickFail;
631
0
                  break;
632
0
                }
633
3.03M
              x++;
634
3.03M
              runlength++;
635
3.03M
            }
636
163k
            continue;
637
163k
          }
638
24.1M
        if ((byte=ReadBlobByte(image)) == EOF)
639
67
          {
640
67
            status=MagickFail;
641
67
            break;
642
67
          }
643
24.1M
        length--;
644
24.1M
        runlength++;
645
24.1M
        do
646
84.9M
        {
647
84.9M
          if (x > image->rows*image->columns*number_channels)
648
84.9M
            ThrowRLAReaderException(CorruptImageError,UnableToRunlengthDecodeImage,image);
649
84.9M
          q=GetImagePixels(image,(long) (x % image->columns),
650
84.9M
            (long) (y % image->columns),1,1);
651
84.9M
          if (q == (PixelPacket *) NULL)
652
0
            {
653
0
              status=MagickFail;
654
0
              break;
655
0
            }
656
84.9M
          switch (channel)
657
84.9M
          {
658
2.12M
            case 0:
659
2.12M
            {
660
2.12M
              q->red=ScaleCharToQuantum(byte);
661
2.12M
              break;
662
0
            }
663
63.2M
            case 1:
664
63.2M
            {
665
63.2M
              q->green=ScaleCharToQuantum(byte);
666
63.2M
              break;
667
0
            }
668
9.99M
            case 2:
669
9.99M
            {
670
9.99M
              q->blue=ScaleCharToQuantum(byte);
671
9.99M
              break;
672
0
            }
673
9.53M
            case 3:
674
9.53M
            {
675
9.53M
              q->opacity=(Quantum) (MaxRGB-ScaleCharToQuantum(byte));
676
9.53M
              break;
677
0
            }
678
0
          default:
679
0
            {
680
              /* Depth channel ? */
681
0
              break;
682
0
            }
683
84.9M
          }
684
84.9M
          if (!SyncImagePixels(image))
685
0
            {
686
0
              status=MagickFail;
687
0
              break;
688
0
            }
689
84.9M
          x++;
690
84.9M
          runlength--;
691
84.9M
        }
692
84.9M
        while (runlength > 0);
693
694
24.1M
        if (MagickFail == status)
695
0
          break;
696
24.1M
      }
697
127k
      if (MagickFail == status)
698
266
        break;
699
127k
    }
700
43.4k
    if (QuantumTick(y,image->rows))
701
13.8k
      if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText,
702
13.8k
                                  image->filename,
703
13.8k
                                  image->columns,image->rows))
704
0
        {
705
0
          status=MagickFail;
706
0
          break;
707
0
        }
708
43.4k
    if (MagickFail == status)
709
266
      break;
710
43.4k
  }
711
395
  if (EOFBlob(image))
712
321
    ThrowRLAReaderException(CorruptImageError,UnexpectedEndOfFile,image);
713
74
  CloseBlob(image);
714
74
  MagickFreeResourceLimitedMemory(magick_uint32_t *,scanlines);
715
74
  StopTimer(&image->timer);
716
74
  return(image);
717
395
}
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
}