blob: 00e653f7ade65d293d94d3f5e31650af8a170e48 [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");
dirk2ad6d332015-10-05 22:11:31 +0200317 pixel_info_length=image->columns*image->rows*number_planes_filled;
dirk7131d8f2014-12-20 13:40:15 +0000318 pixel_info=AcquireVirtualMemory(pixel_info_length,sizeof(*pixels));
cristyb64823d2013-06-30 20:58:24 +0000319 if (pixel_info == (MemoryInfo *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000320 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristyb64823d2013-06-30 20:58:24 +0000321 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
cristy3ed852e2009-09-05 21:47:34 +0000322 if ((flags & 0x01) && !(flags & 0x02))
323 {
cristybb503372010-05-27 20:51:26 +0000324 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000325 j;
326
327 /*
328 Set background color.
329 */
cristyb64823d2013-06-30 20:58:24 +0000330 p=pixels;
cristybb503372010-05-27 20:51:26 +0000331 for (i=0; i < (ssize_t) number_pixels; i++)
cristy3ed852e2009-09-05 21:47:34 +0000332 {
cristy17f11b02014-12-20 19:37:04 +0000333 if (image->alpha_trait == UndefinedPixelTrait)
cristybb503372010-05-27 20:51:26 +0000334 for (j=0; j < (ssize_t) number_planes; j++)
cristy3ed852e2009-09-05 21:47:34 +0000335 *p++=background_color[j];
336 else
337 {
cristybb503372010-05-27 20:51:26 +0000338 for (j=0; j < (ssize_t) (number_planes-1); j++)
cristy3ed852e2009-09-05 21:47:34 +0000339 *p++=background_color[j];
340 *p++=0; /* initialize matte channel */
341 }
342 }
343 }
344 /*
345 Read runlength-encoded image.
346 */
347 plane=0;
348 x=0;
349 y=0;
350 opcode=ReadBlobByte(image);
351 do
352 {
353 switch (opcode & 0x3f)
354 {
355 case SkipLinesOp:
356 {
357 operand=ReadBlobByte(image);
358 if (opcode & 0x40)
359 operand=(int) ReadBlobLSBShort(image);
360 x=0;
361 y+=operand;
362 break;
363 }
364 case SetColorOp:
365 {
366 operand=ReadBlobByte(image);
367 plane=(unsigned char) operand;
368 if (plane == 255)
369 plane=(unsigned char) (number_planes-1);
370 x=0;
371 break;
372 }
373 case SkipPixelsOp:
374 {
375 operand=ReadBlobByte(image);
376 if (opcode & 0x40)
377 operand=(int) ReadBlobLSBShort(image);
378 x+=operand;
379 break;
380 }
381 case ByteDataOp:
382 {
383 operand=ReadBlobByte(image);
384 if (opcode & 0x40)
385 operand=(int) ReadBlobLSBShort(image);
dirk7131d8f2014-12-20 13:40:15 +0000386 offset=((image->rows-y-1)*image->columns*number_planes)+x*
387 number_planes+plane;
cristy3ed852e2009-09-05 21:47:34 +0000388 operand++;
dirk7131d8f2014-12-20 13:40:15 +0000389 if (offset+((size_t) operand*number_planes) > pixel_info_length)
390 {
391 if (number_colormaps != 0)
392 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
393 pixel_info=RelinquishVirtualMemory(pixel_info);
394 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
395 }
396 p=pixels+offset;
cristybb503372010-05-27 20:51:26 +0000397 for (i=0; i < (ssize_t) operand; i++)
cristy3ed852e2009-09-05 21:47:34 +0000398 {
399 pixel=(unsigned char) ReadBlobByte(image);
cristyc6da28e2011-04-28 01:41:35 +0000400 if ((y < (ssize_t) image->rows) &&
401 ((x+i) < (ssize_t) image->columns))
cristy3ed852e2009-09-05 21:47:34 +0000402 *p=pixel;
403 p+=number_planes;
404 }
405 if (operand & 0x01)
406 (void) ReadBlobByte(image);
407 x+=operand;
408 break;
409 }
410 case RunDataOp:
411 {
412 operand=ReadBlobByte(image);
413 if (opcode & 0x40)
414 operand=(int) ReadBlobLSBShort(image);
415 pixel=(unsigned char) ReadBlobByte(image);
416 (void) ReadBlobByte(image);
dirk7131d8f2014-12-20 13:40:15 +0000417 offset=((image->rows-y-1)*image->columns*number_planes)+x*
418 number_planes+plane;
cristy3ed852e2009-09-05 21:47:34 +0000419 operand++;
dirk7131d8f2014-12-20 13:40:15 +0000420 if (offset+((size_t) operand*number_planes) > pixel_info_length)
421 {
422 if (number_colormaps != 0)
423 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
424 pixel_info=RelinquishVirtualMemory(pixel_info);
425 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
426 }
427 p=pixels+offset;
cristybb503372010-05-27 20:51:26 +0000428 for (i=0; i < (ssize_t) operand; i++)
cristy3ed852e2009-09-05 21:47:34 +0000429 {
cristyc6da28e2011-04-28 01:41:35 +0000430 if ((y < (ssize_t) image->rows) &&
431 ((x+i) < (ssize_t) image->columns))
cristy3ed852e2009-09-05 21:47:34 +0000432 *p=pixel;
433 p+=number_planes;
434 }
435 x+=operand;
436 break;
437 }
438 default:
439 break;
440 }
441 opcode=ReadBlobByte(image);
442 } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
443 if (number_colormaps != 0)
444 {
445 MagickStatusType
446 mask;
447
448 /*
449 Apply colormap affineation to image.
450 */
451 mask=(MagickStatusType) (map_length-1);
cristyb64823d2013-06-30 20:58:24 +0000452 p=pixels;
dirk25744142014-12-22 01:26:14 +0000453 x=(ssize_t) number_planes;
cristy3ed852e2009-09-05 21:47:34 +0000454 if (number_colormaps == 1)
cristybb503372010-05-27 20:51:26 +0000455 for (i=0; i < (ssize_t) number_pixels; i++)
cristy3ed852e2009-09-05 21:47:34 +0000456 {
dirk25744142014-12-22 01:26:14 +0000457 if (IsValidColormapIndex(image,*p & mask,&index,exception) ==
458 MagickFalse)
459 break;
460 *p=colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000461 p++;
462 }
463 else
464 if ((number_planes >= 3) && (number_colormaps >= 3))
cristybb503372010-05-27 20:51:26 +0000465 for (i=0; i < (ssize_t) number_pixels; i++)
466 for (x=0; x < (ssize_t) number_planes; x++)
cristy3ed852e2009-09-05 21:47:34 +0000467 {
dirk25744142014-12-22 01:26:14 +0000468 if (IsValidColormapIndex(image,(size_t) (x*map_length+
469 (*p & mask)),&index,exception) == MagickFalse)
470 break;
471 *p=colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000472 p++;
473 }
dirk25744142014-12-22 01:26:14 +0000474 if ((i < (ssize_t) number_pixels) || (x < (ssize_t) number_planes))
475 {
476 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
477 pixel_info=RelinquishVirtualMemory(pixel_info);
478 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
479 }
cristy3ed852e2009-09-05 21:47:34 +0000480 }
481 /*
482 Initialize image structure.
483 */
484 if (number_planes >= 3)
485 {
486 /*
487 Convert raster image to DirectClass pixel packets.
488 */
cristyb64823d2013-06-30 20:58:24 +0000489 p=pixels;
cristybb503372010-05-27 20:51:26 +0000490 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000491 {
492 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000493 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000494 break;
cristybb503372010-05-27 20:51:26 +0000495 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000496 {
cristy4c08aed2011-07-01 19:47:50 +0000497 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
498 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
499 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
cristy17f11b02014-12-20 19:37:04 +0000500 if (image->alpha_trait != UndefinedPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +0000501 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
cristyed231572011-07-14 02:18:59 +0000502 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000503 }
504 if (SyncAuthenticPixels(image,exception) == MagickFalse)
505 break;
506 if (image->previous == (Image *) NULL)
507 {
cristycee97112010-05-28 00:44:52 +0000508 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
509 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000510 if (status == MagickFalse)
511 break;
512 }
513 }
514 }
515 else
516 {
517 /*
518 Create colormap.
519 */
520 if (number_colormaps == 0)
521 map_length=256;
cristy018f07f2011-09-04 21:15:19 +0000522 if (AcquireImageColormap(image,map_length,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000523 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
524 p=colormap;
525 if (number_colormaps == 1)
cristybb503372010-05-27 20:51:26 +0000526 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000527 {
528 /*
529 Pseudocolor.
530 */
cristy62cc94b2014-12-19 00:30:56 +0000531 image->colormap[i].red=(MagickRealType)
532 ScaleCharToQuantum((unsigned char) i);
533 image->colormap[i].green=(MagickRealType)
534 ScaleCharToQuantum((unsigned char) i);
535 image->colormap[i].blue=(MagickRealType)
536 ScaleCharToQuantum((unsigned char) i);
cristy3ed852e2009-09-05 21:47:34 +0000537 }
538 else
539 if (number_colormaps > 1)
cristybb503372010-05-27 20:51:26 +0000540 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000541 {
cristy62cc94b2014-12-19 00:30:56 +0000542 image->colormap[i].red=(MagickRealType)
543 ScaleCharToQuantum(*p);
544 image->colormap[i].green=(MagickRealType)
545 ScaleCharToQuantum(*(p+map_length));
546 image->colormap[i].blue=(MagickRealType)
547 ScaleCharToQuantum(*(p+map_length*2));
cristy3ed852e2009-09-05 21:47:34 +0000548 p++;
549 }
cristyb64823d2013-06-30 20:58:24 +0000550 p=pixels;
cristy17f11b02014-12-20 19:37:04 +0000551 if (image->alpha_trait == UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000552 {
553 /*
554 Convert raster image to PseudoClass pixel packets.
555 */
cristybb503372010-05-27 20:51:26 +0000556 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000557 {
558 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000559 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000560 break;
cristybb503372010-05-27 20:51:26 +0000561 for (x=0; x < (ssize_t) image->columns; x++)
cristy4c08aed2011-07-01 19:47:50 +0000562 {
563 SetPixelIndex(image,*p++,q);
cristyed231572011-07-14 02:18:59 +0000564 q+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +0000565 }
cristy3ed852e2009-09-05 21:47:34 +0000566 if (SyncAuthenticPixels(image,exception) == MagickFalse)
567 break;
568 if (image->previous == (Image *) NULL)
569 {
cristyc6da28e2011-04-28 01:41:35 +0000570 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
571 y,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000572 if (status == MagickFalse)
573 break;
574 }
575 }
cristyea1a8aa2011-10-20 13:24:06 +0000576 (void) SyncImage(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000577 }
578 else
579 {
580 /*
581 Image has a matte channel-- promote to DirectClass.
582 */
cristybb503372010-05-27 20:51:26 +0000583 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000584 {
585 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000586 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000587 break;
cristybb503372010-05-27 20:51:26 +0000588 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000589 {
dirk25744142014-12-22 01:26:14 +0000590 if (IsValidColormapIndex(image,(ssize_t) *p++,&index,
591 exception) == MagickFalse)
592 break;
cristy62cc94b2014-12-19 00:30:56 +0000593 SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t)
dirk25744142014-12-22 01:26:14 +0000594 index].red),q);
595 if (IsValidColormapIndex(image,(ssize_t) *p++,&index,
596 exception) == MagickFalse)
597 break;
cristy62cc94b2014-12-19 00:30:56 +0000598 SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t)
dirk25744142014-12-22 01:26:14 +0000599 index].green),q);
600 if (IsValidColormapIndex(image,(ssize_t) *p++,&index,
601 exception) == MagickFalse)
602 break;
cristy62cc94b2014-12-19 00:30:56 +0000603 SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t)
dirk25744142014-12-22 01:26:14 +0000604 index].blue),q);
cristy4c08aed2011-07-01 19:47:50 +0000605 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
cristyed231572011-07-14 02:18:59 +0000606 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000607 }
dirk25744142014-12-22 01:26:14 +0000608 if (x < (ssize_t) image->columns)
609 break;
cristy3ed852e2009-09-05 21:47:34 +0000610 if (SyncAuthenticPixels(image,exception) == MagickFalse)
611 break;
612 if (image->previous == (Image *) NULL)
613 {
cristyc6da28e2011-04-28 01:41:35 +0000614 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
615 y,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000616 if (status == MagickFalse)
617 break;
618 }
619 }
cristy101ab702011-10-13 13:06:32 +0000620 image->colormap=(PixelInfo *) RelinquishMagickMemory(
cristy3da0b402011-05-29 21:13:36 +0000621 image->colormap);
cristy3ed852e2009-09-05 21:47:34 +0000622 image->storage_class=DirectClass;
623 image->colors=0;
624 }
625 }
626 if (number_colormaps != 0)
627 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
cristyb64823d2013-06-30 20:58:24 +0000628 pixel_info=RelinquishVirtualMemory(pixel_info);
cristy3ed852e2009-09-05 21:47:34 +0000629 if (EOFBlob(image) != MagickFalse)
630 {
631 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
632 image->filename);
633 break;
634 }
635 /*
636 Proceed to next image.
637 */
638 if (image_info->number_scenes != 0)
639 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
640 break;
641 (void) ReadBlobByte(image);
642 count=ReadBlob(image,2,(unsigned char *) magick);
643 if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
644 {
645 /*
646 Allocate next image structure.
647 */
cristy9950d572011-10-01 18:22:35 +0000648 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000649 if (GetNextImageInList(image) == (Image *) NULL)
650 {
651 image=DestroyImageList(image);
652 return((Image *) NULL);
653 }
654 image=SyncNextImageInList(image);
655 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
656 GetBlobSize(image));
657 if (status == MagickFalse)
658 break;
659 }
660 } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
661 (void) CloseBlob(image);
662 return(GetFirstImageInList(image));
663}
664
665/*
666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667% %
668% %
669% %
670% R e g i s t e r R L E I m a g e %
671% %
672% %
673% %
674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
675%
676% RegisterRLEImage() adds attributes for the RLE image format to
677% the list of supported formats. The attributes include the image format
678% tag, a method to read and/or write the format, whether the format
679% supports the saving of more than one frame to the same file or blob,
680% whether the format supports native in-memory I/O, and a brief
681% description of the format.
682%
683% The format of the RegisterRLEImage method is:
684%
cristybb503372010-05-27 20:51:26 +0000685% size_t RegisterRLEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000686%
687*/
cristybb503372010-05-27 20:51:26 +0000688ModuleExport size_t RegisterRLEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000689{
690 MagickInfo
691 *entry;
692
dirk06b627a2015-04-06 18:59:17 +0000693 entry=AcquireMagickInfo("RLE","RLE","Utah Run length encoded image");
cristy3ed852e2009-09-05 21:47:34 +0000694 entry->decoder=(DecodeImageHandler *) ReadRLEImage;
695 entry->magick=(IsImageFormatHandler *) IsRLE;
dirk08e9a112015-02-22 01:51:41 +0000696 entry->flags^=CoderAdjoinFlag;
cristy3ed852e2009-09-05 21:47:34 +0000697 (void) RegisterMagickInfo(entry);
698 return(MagickImageCoderSignature);
699}
700
701/*
702%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
703% %
704% %
705% %
706% U n r e g i s t e r R L E I m a g e %
707% %
708% %
709% %
710%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
711%
712% UnregisterRLEImage() removes format registrations made by the
713% RLE module from the list of supported formats.
714%
715% The format of the UnregisterRLEImage method is:
716%
717% UnregisterRLEImage(void)
718%
719*/
720ModuleExport void UnregisterRLEImage(void)
721{
722 (void) UnregisterMagickInfo("RLE");
723}