Coverage Report

Created: 2025-12-31 07:53

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