blob: cc1ce594ee9e16340cf0a278596833c2d554b747 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% RRRR L EEEEE %
7% R R L E %
8% RRRR L EEE %
9% R R L E %
10% R R LLLLL EEEEE %
11% %
12% %
13% Read URT RLE Image Format %
14% %
15% Software Design %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 1992 %
18% %
19% %
Cristy7ce65e72015-12-12 18:03:16 -050020% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
cristy4c08aed2011-07-01 19:47:50 +000043#include "MagickCore/blob.h"
44#include "MagickCore/blob-private.h"
45#include "MagickCore/cache.h"
46#include "MagickCore/colormap.h"
cristye5f00422014-12-15 11:29:56 +000047#include "MagickCore/colormap-private.h"
cristy4c08aed2011-07-01 19:47:50 +000048#include "MagickCore/exception.h"
49#include "MagickCore/exception-private.h"
50#include "MagickCore/image.h"
51#include "MagickCore/image-private.h"
52#include "MagickCore/list.h"
53#include "MagickCore/magick.h"
54#include "MagickCore/memory_.h"
55#include "MagickCore/monitor.h"
56#include "MagickCore/monitor-private.h"
57#include "MagickCore/pixel-accessor.h"
cristy4c08aed2011-07-01 19:47:50 +000058#include "MagickCore/pixel.h"
cristye5f00422014-12-15 11:29:56 +000059#include "MagickCore/property.h"
60#include "MagickCore/quantum-private.h"
cristy4c08aed2011-07-01 19:47:50 +000061#include "MagickCore/static.h"
62#include "MagickCore/string_.h"
63#include "MagickCore/module.h"
cristy3ed852e2009-09-05 21:47:34 +000064
65/*
66%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67% %
68% %
69% %
70% I s R L E %
71% %
72% %
73% %
74%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75%
76% IsRLE() returns MagickTrue if the image format type, identified by the
77% magick string, is RLE.
78%
79% The format of the ReadRLEImage method is:
80%
81% MagickBooleanType IsRLE(const unsigned char *magick,const size_t length)
82%
83% A description of each parameter follows:
84%
85% o magick: compare image format pattern against these bytes.
86%
87% o length: Specifies the length of the magick string.
88%
89%
90*/
91static MagickBooleanType IsRLE(const unsigned char *magick,const size_t length)
92{
93 if (length < 2)
94 return(MagickFalse);
95 if (memcmp(magick,"\122\314",2) == 0)
96 return(MagickTrue);
97 return(MagickFalse);
98}
99
100/*
101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102% %
103% %
104% %
105% R e a d R L E I m a g e %
106% %
107% %
108% %
109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110%
111% ReadRLEImage() reads a run-length encoded Utah Raster Toolkit
112% image file and returns it. It allocates the memory necessary for the new
113% Image structure and returns a pointer to the new image.
114%
115% The format of the ReadRLEImage method is:
116%
117% Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
118%
119% A description of each parameter follows:
120%
121% o image_info: the image info.
122%
123% o exception: return any errors or warnings in this structure.
124%
125%
126*/
127static Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
128{
129#define SkipLinesOp 0x01
130#define SetColorOp 0x02
131#define SkipPixelsOp 0x03
132#define ByteDataOp 0x05
133#define RunDataOp 0x06
134#define EOFOp 0x07
135
136 char
137 magick[12];
138
139 Image
140 *image;
141
142 int
143 opcode,
144 operand,
145 status;
146
cristy3ed852e2009-09-05 21:47:34 +0000147 MagickStatusType
148 flags;
149
150 MagickSizeType
151 number_pixels;
152
cristyb64823d2013-06-30 20:58:24 +0000153 MemoryInfo
154 *pixel_info;
155
dirk25744142014-12-22 01:26:14 +0000156 Quantum
157 index;
158
cristybb503372010-05-27 20:51:26 +0000159 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000160 x;
161
cristy4c08aed2011-07-01 19:47:50 +0000162 register Quantum
cristy3ed852e2009-09-05 21:47:34 +0000163 *q;
164
cristybb503372010-05-27 20:51:26 +0000165 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000166 i;
167
168 register unsigned char
169 *p;
170
cristyc6da28e2011-04-28 01:41:35 +0000171 size_t
172 bits_per_pixel,
173 map_length,
174 number_colormaps,
175 number_planes,
dirk2ad6d332015-10-05 22:11:31 +0200176 number_planes_filled,
dirk7131d8f2014-12-20 13:40:15 +0000177 one,
178 offset,
179 pixel_info_length;
cristyc6da28e2011-04-28 01:41:35 +0000180
cristy3ed852e2009-09-05 21:47:34 +0000181 ssize_t
cristyc6da28e2011-04-28 01:41:35 +0000182 count,
183 y;
cristy3ed852e2009-09-05 21:47:34 +0000184
185 unsigned char
186 background_color[256],
187 *colormap,
188 pixel,
189 plane,
cristyb64823d2013-06-30 20:58:24 +0000190 *pixels;
cristy3ed852e2009-09-05 21:47:34 +0000191
cristy3ed852e2009-09-05 21:47:34 +0000192 /*
193 Open image file.
194 */
195 assert(image_info != (const ImageInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000196 assert(image_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000197 if (image_info->debug != MagickFalse)
198 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
199 image_info->filename);
200 assert(exception != (ExceptionInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000201 assert(exception->signature == MagickCoreSignature);
cristy9950d572011-10-01 18:22:35 +0000202 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000203 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
204 if (status == MagickFalse)
dirk613a1412015-09-17 22:35:27 +0200205 return(DestroyImageList(image));
cristy3ed852e2009-09-05 21:47:34 +0000206 /*
207 Determine if this a RLE file.
208 */
209 count=ReadBlob(image,2,(unsigned char *) magick);
cristy771c8842015-01-09 12:13:22 +0000210 if ((count != 2) || (memcmp(magick,"\122\314",2) != 0))
cristy3ed852e2009-09-05 21:47:34 +0000211 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
212 do
213 {
214 /*
215 Read image header.
216 */
cristy450bee72015-06-18 23:36:31 +0000217 image->page.x=ReadBlobLSBShort(image);
218 image->page.y=ReadBlobLSBShort(image);
cristy3ed852e2009-09-05 21:47:34 +0000219 image->columns=ReadBlobLSBShort(image);
220 image->rows=ReadBlobLSBShort(image);
221 flags=(MagickStatusType) ReadBlobByte(image);
cristyb0a657e2012-08-29 00:45:37 +0000222 image->alpha_trait=flags & 0x04 ? BlendPixelTrait : UndefinedPixelTrait;
cristy62cc94b2014-12-19 00:30:56 +0000223 number_planes=(size_t) ReadBlobByte(image);
224 bits_per_pixel=(size_t) ReadBlobByte(image);
225 number_colormaps=(size_t) ReadBlobByte(image);
cristycaf07b02014-05-24 23:26:25 +0000226 map_length=(unsigned char) ReadBlobByte(image);
227 if (map_length >= 64)
228 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
cristyeaedf062010-05-29 22:36:02 +0000229 one=1;
cristycaf07b02014-05-24 23:26:25 +0000230 map_length=one << map_length;
cristy3ed852e2009-09-05 21:47:34 +0000231 if ((number_planes == 0) || (number_planes == 2) || (bits_per_pixel != 8) ||
232 (image->columns == 0))
233 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
234 if (flags & 0x02)
235 {
236 /*
237 No background color-- initialize to black.
238 */
cristybb503372010-05-27 20:51:26 +0000239 for (i=0; i < (ssize_t) number_planes; i++)
cristy3ed852e2009-09-05 21:47:34 +0000240 background_color[i]=0;
241 (void) ReadBlobByte(image);
242 }
243 else
244 {
245 /*
246 Initialize background color.
247 */
248 p=background_color;
cristybb503372010-05-27 20:51:26 +0000249 for (i=0; i < (ssize_t) number_planes; i++)
cristy3ed852e2009-09-05 21:47:34 +0000250 *p++=(unsigned char) ReadBlobByte(image);
251 }
252 if ((number_planes & 0x01) == 0)
253 (void) ReadBlobByte(image);
cristy450bee72015-06-18 23:36:31 +0000254 if (EOFBlob(image) != MagickFalse)
255 {
256 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
257 image->filename);
258 break;
259 }
cristy3ed852e2009-09-05 21:47:34 +0000260 colormap=(unsigned char *) NULL;
261 if (number_colormaps != 0)
262 {
263 /*
264 Read image colormaps.
265 */
266 colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps,
cristyddec2882014-12-21 21:04:50 +0000267 3*map_length*sizeof(*colormap));
cristy3ed852e2009-09-05 21:47:34 +0000268 if (colormap == (unsigned char *) NULL)
269 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
270 p=colormap;
cristybb503372010-05-27 20:51:26 +0000271 for (i=0; i < (ssize_t) number_colormaps; i++)
272 for (x=0; x < (ssize_t) map_length; x++)
cristy3ed852e2009-09-05 21:47:34 +0000273 *p++=(unsigned char) ScaleShortToQuantum(ReadBlobLSBShort(image));
274 }
275 if ((flags & 0x08) != 0)
276 {
277 char
278 *comment;
279
cristybb503372010-05-27 20:51:26 +0000280 size_t
cristy3ed852e2009-09-05 21:47:34 +0000281 length;
282
283 /*
284 Read image comment.
285 */
286 length=ReadBlobLSBShort(image);
287 if (length != 0)
288 {
289 comment=(char *) AcquireQuantumMemory(length,sizeof(*comment));
290 if (comment == (char *) NULL)
291 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
292 count=ReadBlob(image,length-1,(unsigned char *) comment);
293 comment[length-1]='\0';
cristyd15e6592011-10-15 00:13:06 +0000294 (void) SetImageProperty(image,"comment",comment,exception);
cristy3ed852e2009-09-05 21:47:34 +0000295 comment=DestroyString(comment);
296 if ((length & 0x01) == 0)
297 (void) ReadBlobByte(image);
298 }
299 }
300 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
301 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
302 break;
cristyacabb842014-12-14 23:36:33 +0000303 status=SetImageExtent(image,image->columns,image->rows,exception);
304 if (status == MagickFalse)
305 return(DestroyImageList(image));
cristy3ed852e2009-09-05 21:47:34 +0000306 /*
307 Allocate RLE pixels.
308 */
cristy17f11b02014-12-20 19:37:04 +0000309 if (image->alpha_trait != UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000310 number_planes++;
311 number_pixels=(MagickSizeType) image->columns*image->rows;
dirk2ad6d332015-10-05 22:11:31 +0200312 number_planes_filled=(number_planes % 2 == 0) ? number_planes :
313 number_planes+1;
314 if ((number_pixels*number_planes_filled) != (size_t) (number_pixels*
315 number_planes_filled))
cristy3ed852e2009-09-05 21:47:34 +0000316 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
Cristy21744842016-01-13 18:31:21 -0500317 if (image->rows < (image->rows*number_planes_filled*sizeof(*pixels)))
318 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
319 pixel_info=AcquireVirtualMemory(image->columns,image->rows*
320 number_planes_filled*sizeof(*pixels));
cristyb64823d2013-06-30 20:58:24 +0000321 if (pixel_info == (MemoryInfo *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000322 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
Cristy21744842016-01-13 18:31:21 -0500323 pixel_info_length=image->columns*image->rows*number_planes_filled;
cristyb64823d2013-06-30 20:58:24 +0000324 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
cristy3ed852e2009-09-05 21:47:34 +0000325 if ((flags & 0x01) && !(flags & 0x02))
326 {
cristybb503372010-05-27 20:51:26 +0000327 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000328 j;
329
330 /*
331 Set background color.
332 */
cristyb64823d2013-06-30 20:58:24 +0000333 p=pixels;
cristybb503372010-05-27 20:51:26 +0000334 for (i=0; i < (ssize_t) number_pixels; i++)
cristy3ed852e2009-09-05 21:47:34 +0000335 {
cristy17f11b02014-12-20 19:37:04 +0000336 if (image->alpha_trait == UndefinedPixelTrait)
cristybb503372010-05-27 20:51:26 +0000337 for (j=0; j < (ssize_t) number_planes; j++)
cristy3ed852e2009-09-05 21:47:34 +0000338 *p++=background_color[j];
339 else
340 {
cristybb503372010-05-27 20:51:26 +0000341 for (j=0; j < (ssize_t) (number_planes-1); j++)
cristy3ed852e2009-09-05 21:47:34 +0000342 *p++=background_color[j];
343 *p++=0; /* initialize matte channel */
344 }
345 }
346 }
347 /*
348 Read runlength-encoded image.
349 */
350 plane=0;
351 x=0;
352 y=0;
353 opcode=ReadBlobByte(image);
354 do
355 {
356 switch (opcode & 0x3f)
357 {
358 case SkipLinesOp:
359 {
360 operand=ReadBlobByte(image);
361 if (opcode & 0x40)
362 operand=(int) ReadBlobLSBShort(image);
363 x=0;
364 y+=operand;
365 break;
366 }
367 case SetColorOp:
368 {
369 operand=ReadBlobByte(image);
370 plane=(unsigned char) operand;
371 if (plane == 255)
372 plane=(unsigned char) (number_planes-1);
373 x=0;
374 break;
375 }
376 case SkipPixelsOp:
377 {
378 operand=ReadBlobByte(image);
379 if (opcode & 0x40)
380 operand=(int) ReadBlobLSBShort(image);
381 x+=operand;
382 break;
383 }
384 case ByteDataOp:
385 {
386 operand=ReadBlobByte(image);
387 if (opcode & 0x40)
388 operand=(int) ReadBlobLSBShort(image);
dirk7131d8f2014-12-20 13:40:15 +0000389 offset=((image->rows-y-1)*image->columns*number_planes)+x*
390 number_planes+plane;
cristy3ed852e2009-09-05 21:47:34 +0000391 operand++;
dirk7131d8f2014-12-20 13:40:15 +0000392 if (offset+((size_t) operand*number_planes) > pixel_info_length)
393 {
394 if (number_colormaps != 0)
395 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
396 pixel_info=RelinquishVirtualMemory(pixel_info);
397 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
398 }
399 p=pixels+offset;
cristybb503372010-05-27 20:51:26 +0000400 for (i=0; i < (ssize_t) operand; i++)
cristy3ed852e2009-09-05 21:47:34 +0000401 {
402 pixel=(unsigned char) ReadBlobByte(image);
cristyc6da28e2011-04-28 01:41:35 +0000403 if ((y < (ssize_t) image->rows) &&
404 ((x+i) < (ssize_t) image->columns))
cristy3ed852e2009-09-05 21:47:34 +0000405 *p=pixel;
406 p+=number_planes;
407 }
408 if (operand & 0x01)
409 (void) ReadBlobByte(image);
410 x+=operand;
411 break;
412 }
413 case RunDataOp:
414 {
415 operand=ReadBlobByte(image);
416 if (opcode & 0x40)
417 operand=(int) ReadBlobLSBShort(image);
418 pixel=(unsigned char) ReadBlobByte(image);
419 (void) ReadBlobByte(image);
dirk7131d8f2014-12-20 13:40:15 +0000420 offset=((image->rows-y-1)*image->columns*number_planes)+x*
421 number_planes+plane;
cristy3ed852e2009-09-05 21:47:34 +0000422 operand++;
dirk7131d8f2014-12-20 13:40:15 +0000423 if (offset+((size_t) operand*number_planes) > pixel_info_length)
424 {
425 if (number_colormaps != 0)
426 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
427 pixel_info=RelinquishVirtualMemory(pixel_info);
428 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
429 }
430 p=pixels+offset;
cristybb503372010-05-27 20:51:26 +0000431 for (i=0; i < (ssize_t) operand; i++)
cristy3ed852e2009-09-05 21:47:34 +0000432 {
cristyc6da28e2011-04-28 01:41:35 +0000433 if ((y < (ssize_t) image->rows) &&
434 ((x+i) < (ssize_t) image->columns))
cristy3ed852e2009-09-05 21:47:34 +0000435 *p=pixel;
436 p+=number_planes;
437 }
438 x+=operand;
439 break;
440 }
441 default:
442 break;
443 }
444 opcode=ReadBlobByte(image);
445 } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
446 if (number_colormaps != 0)
447 {
448 MagickStatusType
449 mask;
450
451 /*
452 Apply colormap affineation to image.
453 */
454 mask=(MagickStatusType) (map_length-1);
cristyb64823d2013-06-30 20:58:24 +0000455 p=pixels;
dirk25744142014-12-22 01:26:14 +0000456 x=(ssize_t) number_planes;
cristy3ed852e2009-09-05 21:47:34 +0000457 if (number_colormaps == 1)
cristybb503372010-05-27 20:51:26 +0000458 for (i=0; i < (ssize_t) number_pixels; i++)
cristy3ed852e2009-09-05 21:47:34 +0000459 {
dirk25744142014-12-22 01:26:14 +0000460 if (IsValidColormapIndex(image,*p & mask,&index,exception) ==
461 MagickFalse)
462 break;
463 *p=colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000464 p++;
465 }
466 else
467 if ((number_planes >= 3) && (number_colormaps >= 3))
cristybb503372010-05-27 20:51:26 +0000468 for (i=0; i < (ssize_t) number_pixels; i++)
469 for (x=0; x < (ssize_t) number_planes; x++)
cristy3ed852e2009-09-05 21:47:34 +0000470 {
dirk25744142014-12-22 01:26:14 +0000471 if (IsValidColormapIndex(image,(size_t) (x*map_length+
472 (*p & mask)),&index,exception) == MagickFalse)
473 break;
474 *p=colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000475 p++;
476 }
dirk25744142014-12-22 01:26:14 +0000477 if ((i < (ssize_t) number_pixels) || (x < (ssize_t) number_planes))
478 {
479 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
480 pixel_info=RelinquishVirtualMemory(pixel_info);
481 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
482 }
cristy3ed852e2009-09-05 21:47:34 +0000483 }
484 /*
485 Initialize image structure.
486 */
487 if (number_planes >= 3)
488 {
489 /*
490 Convert raster image to DirectClass pixel packets.
491 */
cristyb64823d2013-06-30 20:58:24 +0000492 p=pixels;
cristybb503372010-05-27 20:51:26 +0000493 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000494 {
495 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000496 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000497 break;
cristybb503372010-05-27 20:51:26 +0000498 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000499 {
cristy4c08aed2011-07-01 19:47:50 +0000500 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
501 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
502 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
cristy17f11b02014-12-20 19:37:04 +0000503 if (image->alpha_trait != UndefinedPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +0000504 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
cristyed231572011-07-14 02:18:59 +0000505 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000506 }
507 if (SyncAuthenticPixels(image,exception) == MagickFalse)
508 break;
509 if (image->previous == (Image *) NULL)
510 {
cristycee97112010-05-28 00:44:52 +0000511 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
512 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000513 if (status == MagickFalse)
514 break;
515 }
516 }
517 }
518 else
519 {
520 /*
521 Create colormap.
522 */
523 if (number_colormaps == 0)
524 map_length=256;
cristy018f07f2011-09-04 21:15:19 +0000525 if (AcquireImageColormap(image,map_length,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000526 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
527 p=colormap;
528 if (number_colormaps == 1)
cristybb503372010-05-27 20:51:26 +0000529 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000530 {
531 /*
532 Pseudocolor.
533 */
cristy62cc94b2014-12-19 00:30:56 +0000534 image->colormap[i].red=(MagickRealType)
535 ScaleCharToQuantum((unsigned char) i);
536 image->colormap[i].green=(MagickRealType)
537 ScaleCharToQuantum((unsigned char) i);
538 image->colormap[i].blue=(MagickRealType)
539 ScaleCharToQuantum((unsigned char) i);
cristy3ed852e2009-09-05 21:47:34 +0000540 }
541 else
542 if (number_colormaps > 1)
cristybb503372010-05-27 20:51:26 +0000543 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000544 {
cristy62cc94b2014-12-19 00:30:56 +0000545 image->colormap[i].red=(MagickRealType)
546 ScaleCharToQuantum(*p);
547 image->colormap[i].green=(MagickRealType)
548 ScaleCharToQuantum(*(p+map_length));
549 image->colormap[i].blue=(MagickRealType)
550 ScaleCharToQuantum(*(p+map_length*2));
cristy3ed852e2009-09-05 21:47:34 +0000551 p++;
552 }
cristyb64823d2013-06-30 20:58:24 +0000553 p=pixels;
cristy17f11b02014-12-20 19:37:04 +0000554 if (image->alpha_trait == UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000555 {
556 /*
557 Convert raster image to PseudoClass pixel packets.
558 */
cristybb503372010-05-27 20:51:26 +0000559 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000560 {
561 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000562 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000563 break;
cristybb503372010-05-27 20:51:26 +0000564 for (x=0; x < (ssize_t) image->columns; x++)
cristy4c08aed2011-07-01 19:47:50 +0000565 {
566 SetPixelIndex(image,*p++,q);
cristyed231572011-07-14 02:18:59 +0000567 q+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +0000568 }
cristy3ed852e2009-09-05 21:47:34 +0000569 if (SyncAuthenticPixels(image,exception) == MagickFalse)
570 break;
571 if (image->previous == (Image *) NULL)
572 {
cristyc6da28e2011-04-28 01:41:35 +0000573 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
574 y,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000575 if (status == MagickFalse)
576 break;
577 }
578 }
cristyea1a8aa2011-10-20 13:24:06 +0000579 (void) SyncImage(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000580 }
581 else
582 {
583 /*
584 Image has a matte channel-- promote to DirectClass.
585 */
cristybb503372010-05-27 20:51:26 +0000586 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000587 {
588 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000589 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000590 break;
cristybb503372010-05-27 20:51:26 +0000591 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000592 {
dirk25744142014-12-22 01:26:14 +0000593 if (IsValidColormapIndex(image,(ssize_t) *p++,&index,
594 exception) == MagickFalse)
595 break;
cristy62cc94b2014-12-19 00:30:56 +0000596 SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t)
dirk25744142014-12-22 01:26:14 +0000597 index].red),q);
598 if (IsValidColormapIndex(image,(ssize_t) *p++,&index,
599 exception) == MagickFalse)
600 break;
cristy62cc94b2014-12-19 00:30:56 +0000601 SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t)
dirk25744142014-12-22 01:26:14 +0000602 index].green),q);
603 if (IsValidColormapIndex(image,(ssize_t) *p++,&index,
604 exception) == MagickFalse)
605 break;
cristy62cc94b2014-12-19 00:30:56 +0000606 SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t)
dirk25744142014-12-22 01:26:14 +0000607 index].blue),q);
cristy4c08aed2011-07-01 19:47:50 +0000608 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
cristyed231572011-07-14 02:18:59 +0000609 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000610 }
dirk25744142014-12-22 01:26:14 +0000611 if (x < (ssize_t) image->columns)
612 break;
cristy3ed852e2009-09-05 21:47:34 +0000613 if (SyncAuthenticPixels(image,exception) == MagickFalse)
614 break;
615 if (image->previous == (Image *) NULL)
616 {
cristyc6da28e2011-04-28 01:41:35 +0000617 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
618 y,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000619 if (status == MagickFalse)
620 break;
621 }
622 }
cristy101ab702011-10-13 13:06:32 +0000623 image->colormap=(PixelInfo *) RelinquishMagickMemory(
cristy3da0b402011-05-29 21:13:36 +0000624 image->colormap);
cristy3ed852e2009-09-05 21:47:34 +0000625 image->storage_class=DirectClass;
626 image->colors=0;
627 }
628 }
629 if (number_colormaps != 0)
630 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
cristyb64823d2013-06-30 20:58:24 +0000631 pixel_info=RelinquishVirtualMemory(pixel_info);
cristy3ed852e2009-09-05 21:47:34 +0000632 if (EOFBlob(image) != MagickFalse)
633 {
634 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
635 image->filename);
636 break;
637 }
638 /*
639 Proceed to next image.
640 */
641 if (image_info->number_scenes != 0)
642 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
643 break;
644 (void) ReadBlobByte(image);
645 count=ReadBlob(image,2,(unsigned char *) magick);
646 if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
647 {
648 /*
649 Allocate next image structure.
650 */
cristy9950d572011-10-01 18:22:35 +0000651 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000652 if (GetNextImageInList(image) == (Image *) NULL)
653 {
654 image=DestroyImageList(image);
655 return((Image *) NULL);
656 }
657 image=SyncNextImageInList(image);
658 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
659 GetBlobSize(image));
660 if (status == MagickFalse)
661 break;
662 }
663 } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
664 (void) CloseBlob(image);
665 return(GetFirstImageInList(image));
666}
667
668/*
669%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670% %
671% %
672% %
673% R e g i s t e r R L E I m a g e %
674% %
675% %
676% %
677%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678%
679% RegisterRLEImage() adds attributes for the RLE image format to
680% the list of supported formats. The attributes include the image format
681% tag, a method to read and/or write the format, whether the format
682% supports the saving of more than one frame to the same file or blob,
683% whether the format supports native in-memory I/O, and a brief
684% description of the format.
685%
686% The format of the RegisterRLEImage method is:
687%
cristybb503372010-05-27 20:51:26 +0000688% size_t RegisterRLEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000689%
690*/
cristybb503372010-05-27 20:51:26 +0000691ModuleExport size_t RegisterRLEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000692{
693 MagickInfo
694 *entry;
695
dirk06b627a2015-04-06 18:59:17 +0000696 entry=AcquireMagickInfo("RLE","RLE","Utah Run length encoded image");
cristy3ed852e2009-09-05 21:47:34 +0000697 entry->decoder=(DecodeImageHandler *) ReadRLEImage;
698 entry->magick=(IsImageFormatHandler *) IsRLE;
dirk08e9a112015-02-22 01:51:41 +0000699 entry->flags^=CoderAdjoinFlag;
cristy3ed852e2009-09-05 21:47:34 +0000700 (void) RegisterMagickInfo(entry);
701 return(MagickImageCoderSignature);
702}
703
704/*
705%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
706% %
707% %
708% %
709% U n r e g i s t e r R L E I m a g e %
710% %
711% %
712% %
713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714%
715% UnregisterRLEImage() removes format registrations made by the
716% RLE module from the list of supported formats.
717%
718% The format of the UnregisterRLEImage method is:
719%
720% UnregisterRLEImage(void)
721%
722*/
723ModuleExport void UnregisterRLEImage(void)
724{
725 (void) UnregisterMagickInfo("RLE");
726}