blob: 3d7bb9098986ffeef4fecd3da4e08287d3baf126 [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% %
cristyb56bb242014-11-25 17:12:48 +000020% Copyright 1999-2015 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,
dirk7131d8f2014-12-20 13:40:15 +0000176 one,
177 offset,
178 pixel_info_length;
cristyc6da28e2011-04-28 01:41:35 +0000179
cristy3ed852e2009-09-05 21:47:34 +0000180 ssize_t
cristyc6da28e2011-04-28 01:41:35 +0000181 count,
182 y;
cristy3ed852e2009-09-05 21:47:34 +0000183
184 unsigned char
185 background_color[256],
186 *colormap,
187 pixel,
188 plane,
cristyb64823d2013-06-30 20:58:24 +0000189 *pixels;
cristy3ed852e2009-09-05 21:47:34 +0000190
cristy3ed852e2009-09-05 21:47:34 +0000191 /*
192 Open image file.
193 */
194 assert(image_info != (const ImageInfo *) NULL);
195 assert(image_info->signature == MagickSignature);
196 if (image_info->debug != MagickFalse)
197 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
198 image_info->filename);
199 assert(exception != (ExceptionInfo *) NULL);
200 assert(exception->signature == MagickSignature);
cristy9950d572011-10-01 18:22:35 +0000201 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000202 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
203 if (status == MagickFalse)
204 {
205 image=DestroyImageList(image);
206 return((Image *) NULL);
207 }
208 /*
209 Determine if this a RLE file.
210 */
211 count=ReadBlob(image,2,(unsigned char *) magick);
cristy771c8842015-01-09 12:13:22 +0000212 if ((count != 2) || (memcmp(magick,"\122\314",2) != 0))
cristy3ed852e2009-09-05 21:47:34 +0000213 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
214 do
215 {
216 /*
217 Read image header.
218 */
219 (void) ReadBlobLSBShort(image);
220 (void) ReadBlobLSBShort(image);
221 image->columns=ReadBlobLSBShort(image);
222 image->rows=ReadBlobLSBShort(image);
223 flags=(MagickStatusType) ReadBlobByte(image);
cristyb0a657e2012-08-29 00:45:37 +0000224 image->alpha_trait=flags & 0x04 ? BlendPixelTrait : UndefinedPixelTrait;
cristy62cc94b2014-12-19 00:30:56 +0000225 number_planes=(size_t) ReadBlobByte(image);
226 bits_per_pixel=(size_t) ReadBlobByte(image);
227 number_colormaps=(size_t) ReadBlobByte(image);
cristycaf07b02014-05-24 23:26:25 +0000228 map_length=(unsigned char) ReadBlobByte(image);
229 if (map_length >= 64)
230 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
cristyeaedf062010-05-29 22:36:02 +0000231 one=1;
cristycaf07b02014-05-24 23:26:25 +0000232 map_length=one << map_length;
cristy3ed852e2009-09-05 21:47:34 +0000233 if ((number_planes == 0) || (number_planes == 2) || (bits_per_pixel != 8) ||
234 (image->columns == 0))
235 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
236 if (flags & 0x02)
237 {
238 /*
239 No background color-- initialize to black.
240 */
cristybb503372010-05-27 20:51:26 +0000241 for (i=0; i < (ssize_t) number_planes; i++)
cristy3ed852e2009-09-05 21:47:34 +0000242 background_color[i]=0;
243 (void) ReadBlobByte(image);
244 }
245 else
246 {
247 /*
248 Initialize background color.
249 */
250 p=background_color;
cristybb503372010-05-27 20:51:26 +0000251 for (i=0; i < (ssize_t) number_planes; i++)
cristy3ed852e2009-09-05 21:47:34 +0000252 *p++=(unsigned char) ReadBlobByte(image);
253 }
254 if ((number_planes & 0x01) == 0)
255 (void) ReadBlobByte(image);
256 colormap=(unsigned char *) NULL;
257 if (number_colormaps != 0)
258 {
259 /*
260 Read image colormaps.
261 */
262 colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps,
cristyddec2882014-12-21 21:04:50 +0000263 3*map_length*sizeof(*colormap));
cristy3ed852e2009-09-05 21:47:34 +0000264 if (colormap == (unsigned char *) NULL)
265 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
266 p=colormap;
cristybb503372010-05-27 20:51:26 +0000267 for (i=0; i < (ssize_t) number_colormaps; i++)
268 for (x=0; x < (ssize_t) map_length; x++)
cristy3ed852e2009-09-05 21:47:34 +0000269 *p++=(unsigned char) ScaleShortToQuantum(ReadBlobLSBShort(image));
270 }
271 if ((flags & 0x08) != 0)
272 {
273 char
274 *comment;
275
cristybb503372010-05-27 20:51:26 +0000276 size_t
cristy3ed852e2009-09-05 21:47:34 +0000277 length;
278
279 /*
280 Read image comment.
281 */
282 length=ReadBlobLSBShort(image);
283 if (length != 0)
284 {
285 comment=(char *) AcquireQuantumMemory(length,sizeof(*comment));
286 if (comment == (char *) NULL)
287 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
288 count=ReadBlob(image,length-1,(unsigned char *) comment);
289 comment[length-1]='\0';
cristyd15e6592011-10-15 00:13:06 +0000290 (void) SetImageProperty(image,"comment",comment,exception);
cristy3ed852e2009-09-05 21:47:34 +0000291 comment=DestroyString(comment);
292 if ((length & 0x01) == 0)
293 (void) ReadBlobByte(image);
294 }
295 }
296 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
297 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
298 break;
cristyacabb842014-12-14 23:36:33 +0000299 status=SetImageExtent(image,image->columns,image->rows,exception);
300 if (status == MagickFalse)
301 return(DestroyImageList(image));
cristy3ed852e2009-09-05 21:47:34 +0000302 /*
303 Allocate RLE pixels.
304 */
cristy17f11b02014-12-20 19:37:04 +0000305 if (image->alpha_trait != UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000306 number_planes++;
307 number_pixels=(MagickSizeType) image->columns*image->rows;
308 if ((number_pixels*number_planes) != (size_t) (number_pixels*number_planes))
309 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
dirk7131d8f2014-12-20 13:40:15 +0000310 pixel_info_length=image->columns*image->rows*MagickMax(number_planes,4);
311 pixel_info=AcquireVirtualMemory(pixel_info_length,sizeof(*pixels));
cristyb64823d2013-06-30 20:58:24 +0000312 if (pixel_info == (MemoryInfo *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000313 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristyb64823d2013-06-30 20:58:24 +0000314 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
cristy3ed852e2009-09-05 21:47:34 +0000315 if ((flags & 0x01) && !(flags & 0x02))
316 {
cristybb503372010-05-27 20:51:26 +0000317 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000318 j;
319
320 /*
321 Set background color.
322 */
cristyb64823d2013-06-30 20:58:24 +0000323 p=pixels;
cristybb503372010-05-27 20:51:26 +0000324 for (i=0; i < (ssize_t) number_pixels; i++)
cristy3ed852e2009-09-05 21:47:34 +0000325 {
cristy17f11b02014-12-20 19:37:04 +0000326 if (image->alpha_trait == UndefinedPixelTrait)
cristybb503372010-05-27 20:51:26 +0000327 for (j=0; j < (ssize_t) number_planes; j++)
cristy3ed852e2009-09-05 21:47:34 +0000328 *p++=background_color[j];
329 else
330 {
cristybb503372010-05-27 20:51:26 +0000331 for (j=0; j < (ssize_t) (number_planes-1); j++)
cristy3ed852e2009-09-05 21:47:34 +0000332 *p++=background_color[j];
333 *p++=0; /* initialize matte channel */
334 }
335 }
336 }
337 /*
338 Read runlength-encoded image.
339 */
340 plane=0;
341 x=0;
342 y=0;
343 opcode=ReadBlobByte(image);
344 do
345 {
346 switch (opcode & 0x3f)
347 {
348 case SkipLinesOp:
349 {
350 operand=ReadBlobByte(image);
351 if (opcode & 0x40)
352 operand=(int) ReadBlobLSBShort(image);
353 x=0;
354 y+=operand;
355 break;
356 }
357 case SetColorOp:
358 {
359 operand=ReadBlobByte(image);
360 plane=(unsigned char) operand;
361 if (plane == 255)
362 plane=(unsigned char) (number_planes-1);
363 x=0;
364 break;
365 }
366 case SkipPixelsOp:
367 {
368 operand=ReadBlobByte(image);
369 if (opcode & 0x40)
370 operand=(int) ReadBlobLSBShort(image);
371 x+=operand;
372 break;
373 }
374 case ByteDataOp:
375 {
376 operand=ReadBlobByte(image);
377 if (opcode & 0x40)
378 operand=(int) ReadBlobLSBShort(image);
dirk7131d8f2014-12-20 13:40:15 +0000379 offset=((image->rows-y-1)*image->columns*number_planes)+x*
380 number_planes+plane;
cristy3ed852e2009-09-05 21:47:34 +0000381 operand++;
dirk7131d8f2014-12-20 13:40:15 +0000382 if (offset+((size_t) operand*number_planes) > pixel_info_length)
383 {
384 if (number_colormaps != 0)
385 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
386 pixel_info=RelinquishVirtualMemory(pixel_info);
387 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
388 }
389 p=pixels+offset;
cristybb503372010-05-27 20:51:26 +0000390 for (i=0; i < (ssize_t) operand; i++)
cristy3ed852e2009-09-05 21:47:34 +0000391 {
392 pixel=(unsigned char) ReadBlobByte(image);
cristyc6da28e2011-04-28 01:41:35 +0000393 if ((y < (ssize_t) image->rows) &&
394 ((x+i) < (ssize_t) image->columns))
cristy3ed852e2009-09-05 21:47:34 +0000395 *p=pixel;
396 p+=number_planes;
397 }
398 if (operand & 0x01)
399 (void) ReadBlobByte(image);
400 x+=operand;
401 break;
402 }
403 case RunDataOp:
404 {
405 operand=ReadBlobByte(image);
406 if (opcode & 0x40)
407 operand=(int) ReadBlobLSBShort(image);
408 pixel=(unsigned char) ReadBlobByte(image);
409 (void) ReadBlobByte(image);
dirk7131d8f2014-12-20 13:40:15 +0000410 offset=((image->rows-y-1)*image->columns*number_planes)+x*
411 number_planes+plane;
cristy3ed852e2009-09-05 21:47:34 +0000412 operand++;
dirk7131d8f2014-12-20 13:40:15 +0000413 if (offset+((size_t) operand*number_planes) > pixel_info_length)
414 {
415 if (number_colormaps != 0)
416 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
417 pixel_info=RelinquishVirtualMemory(pixel_info);
418 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
419 }
420 p=pixels+offset;
cristybb503372010-05-27 20:51:26 +0000421 for (i=0; i < (ssize_t) operand; i++)
cristy3ed852e2009-09-05 21:47:34 +0000422 {
cristyc6da28e2011-04-28 01:41:35 +0000423 if ((y < (ssize_t) image->rows) &&
424 ((x+i) < (ssize_t) image->columns))
cristy3ed852e2009-09-05 21:47:34 +0000425 *p=pixel;
426 p+=number_planes;
427 }
428 x+=operand;
429 break;
430 }
431 default:
432 break;
433 }
434 opcode=ReadBlobByte(image);
435 } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
436 if (number_colormaps != 0)
437 {
438 MagickStatusType
439 mask;
440
441 /*
442 Apply colormap affineation to image.
443 */
444 mask=(MagickStatusType) (map_length-1);
cristyb64823d2013-06-30 20:58:24 +0000445 p=pixels;
dirk25744142014-12-22 01:26:14 +0000446 x=(ssize_t) number_planes;
cristy3ed852e2009-09-05 21:47:34 +0000447 if (number_colormaps == 1)
cristybb503372010-05-27 20:51:26 +0000448 for (i=0; i < (ssize_t) number_pixels; i++)
cristy3ed852e2009-09-05 21:47:34 +0000449 {
dirk25744142014-12-22 01:26:14 +0000450 if (IsValidColormapIndex(image,*p & mask,&index,exception) ==
451 MagickFalse)
452 break;
453 *p=colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000454 p++;
455 }
456 else
457 if ((number_planes >= 3) && (number_colormaps >= 3))
cristybb503372010-05-27 20:51:26 +0000458 for (i=0; i < (ssize_t) number_pixels; i++)
459 for (x=0; x < (ssize_t) number_planes; x++)
cristy3ed852e2009-09-05 21:47:34 +0000460 {
dirk25744142014-12-22 01:26:14 +0000461 if (IsValidColormapIndex(image,(size_t) (x*map_length+
462 (*p & mask)),&index,exception) == MagickFalse)
463 break;
464 *p=colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000465 p++;
466 }
dirk25744142014-12-22 01:26:14 +0000467 if ((i < (ssize_t) number_pixels) || (x < (ssize_t) number_planes))
468 {
469 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
470 pixel_info=RelinquishVirtualMemory(pixel_info);
471 ThrowReaderException(CorruptImageError,"UnableToReadImageData");
472 }
cristy3ed852e2009-09-05 21:47:34 +0000473 }
474 /*
475 Initialize image structure.
476 */
477 if (number_planes >= 3)
478 {
479 /*
480 Convert raster image to DirectClass pixel packets.
481 */
cristyb64823d2013-06-30 20:58:24 +0000482 p=pixels;
cristybb503372010-05-27 20:51:26 +0000483 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000484 {
485 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000486 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000487 break;
cristybb503372010-05-27 20:51:26 +0000488 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000489 {
cristy4c08aed2011-07-01 19:47:50 +0000490 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
491 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
492 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
cristy17f11b02014-12-20 19:37:04 +0000493 if (image->alpha_trait != UndefinedPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +0000494 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
cristyed231572011-07-14 02:18:59 +0000495 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000496 }
497 if (SyncAuthenticPixels(image,exception) == MagickFalse)
498 break;
499 if (image->previous == (Image *) NULL)
500 {
cristycee97112010-05-28 00:44:52 +0000501 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
502 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000503 if (status == MagickFalse)
504 break;
505 }
506 }
507 }
508 else
509 {
510 /*
511 Create colormap.
512 */
513 if (number_colormaps == 0)
514 map_length=256;
cristy018f07f2011-09-04 21:15:19 +0000515 if (AcquireImageColormap(image,map_length,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000516 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
517 p=colormap;
518 if (number_colormaps == 1)
cristybb503372010-05-27 20:51:26 +0000519 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000520 {
521 /*
522 Pseudocolor.
523 */
cristy62cc94b2014-12-19 00:30:56 +0000524 image->colormap[i].red=(MagickRealType)
525 ScaleCharToQuantum((unsigned char) i);
526 image->colormap[i].green=(MagickRealType)
527 ScaleCharToQuantum((unsigned char) i);
528 image->colormap[i].blue=(MagickRealType)
529 ScaleCharToQuantum((unsigned char) i);
cristy3ed852e2009-09-05 21:47:34 +0000530 }
531 else
532 if (number_colormaps > 1)
cristybb503372010-05-27 20:51:26 +0000533 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000534 {
cristy62cc94b2014-12-19 00:30:56 +0000535 image->colormap[i].red=(MagickRealType)
536 ScaleCharToQuantum(*p);
537 image->colormap[i].green=(MagickRealType)
538 ScaleCharToQuantum(*(p+map_length));
539 image->colormap[i].blue=(MagickRealType)
540 ScaleCharToQuantum(*(p+map_length*2));
cristy3ed852e2009-09-05 21:47:34 +0000541 p++;
542 }
cristyb64823d2013-06-30 20:58:24 +0000543 p=pixels;
cristy17f11b02014-12-20 19:37:04 +0000544 if (image->alpha_trait == UndefinedPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000545 {
546 /*
547 Convert raster image to PseudoClass pixel packets.
548 */
cristybb503372010-05-27 20:51:26 +0000549 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000550 {
551 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000552 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000553 break;
cristybb503372010-05-27 20:51:26 +0000554 for (x=0; x < (ssize_t) image->columns; x++)
cristy4c08aed2011-07-01 19:47:50 +0000555 {
556 SetPixelIndex(image,*p++,q);
cristyed231572011-07-14 02:18:59 +0000557 q+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +0000558 }
cristy3ed852e2009-09-05 21:47:34 +0000559 if (SyncAuthenticPixels(image,exception) == MagickFalse)
560 break;
561 if (image->previous == (Image *) NULL)
562 {
cristyc6da28e2011-04-28 01:41:35 +0000563 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
564 y,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000565 if (status == MagickFalse)
566 break;
567 }
568 }
cristyea1a8aa2011-10-20 13:24:06 +0000569 (void) SyncImage(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000570 }
571 else
572 {
573 /*
574 Image has a matte channel-- promote to DirectClass.
575 */
cristybb503372010-05-27 20:51:26 +0000576 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000577 {
578 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000579 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000580 break;
cristybb503372010-05-27 20:51:26 +0000581 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000582 {
dirk25744142014-12-22 01:26:14 +0000583 if (IsValidColormapIndex(image,(ssize_t) *p++,&index,
584 exception) == MagickFalse)
585 break;
cristy62cc94b2014-12-19 00:30:56 +0000586 SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t)
dirk25744142014-12-22 01:26:14 +0000587 index].red),q);
588 if (IsValidColormapIndex(image,(ssize_t) *p++,&index,
589 exception) == MagickFalse)
590 break;
cristy62cc94b2014-12-19 00:30:56 +0000591 SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t)
dirk25744142014-12-22 01:26:14 +0000592 index].green),q);
593 if (IsValidColormapIndex(image,(ssize_t) *p++,&index,
594 exception) == MagickFalse)
595 break;
cristy62cc94b2014-12-19 00:30:56 +0000596 SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t)
dirk25744142014-12-22 01:26:14 +0000597 index].blue),q);
cristy4c08aed2011-07-01 19:47:50 +0000598 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
cristyed231572011-07-14 02:18:59 +0000599 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000600 }
dirk25744142014-12-22 01:26:14 +0000601 if (x < (ssize_t) image->columns)
602 break;
cristy3ed852e2009-09-05 21:47:34 +0000603 if (SyncAuthenticPixels(image,exception) == MagickFalse)
604 break;
605 if (image->previous == (Image *) NULL)
606 {
cristyc6da28e2011-04-28 01:41:35 +0000607 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
608 y,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000609 if (status == MagickFalse)
610 break;
611 }
612 }
cristy101ab702011-10-13 13:06:32 +0000613 image->colormap=(PixelInfo *) RelinquishMagickMemory(
cristy3da0b402011-05-29 21:13:36 +0000614 image->colormap);
cristy3ed852e2009-09-05 21:47:34 +0000615 image->storage_class=DirectClass;
616 image->colors=0;
617 }
618 }
619 if (number_colormaps != 0)
620 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
cristyb64823d2013-06-30 20:58:24 +0000621 pixel_info=RelinquishVirtualMemory(pixel_info);
cristy3ed852e2009-09-05 21:47:34 +0000622 if (EOFBlob(image) != MagickFalse)
623 {
624 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
625 image->filename);
626 break;
627 }
628 /*
629 Proceed to next image.
630 */
631 if (image_info->number_scenes != 0)
632 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
633 break;
634 (void) ReadBlobByte(image);
635 count=ReadBlob(image,2,(unsigned char *) magick);
636 if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
637 {
638 /*
639 Allocate next image structure.
640 */
cristy9950d572011-10-01 18:22:35 +0000641 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000642 if (GetNextImageInList(image) == (Image *) NULL)
643 {
644 image=DestroyImageList(image);
645 return((Image *) NULL);
646 }
647 image=SyncNextImageInList(image);
648 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
649 GetBlobSize(image));
650 if (status == MagickFalse)
651 break;
652 }
653 } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
654 (void) CloseBlob(image);
655 return(GetFirstImageInList(image));
656}
657
658/*
659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
660% %
661% %
662% %
663% R e g i s t e r R L E I m a g e %
664% %
665% %
666% %
667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
668%
669% RegisterRLEImage() adds attributes for the RLE image format to
670% the list of supported formats. The attributes include the image format
671% tag, a method to read and/or write the format, whether the format
672% supports the saving of more than one frame to the same file or blob,
673% whether the format supports native in-memory I/O, and a brief
674% description of the format.
675%
676% The format of the RegisterRLEImage method is:
677%
cristybb503372010-05-27 20:51:26 +0000678% size_t RegisterRLEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000679%
680*/
cristybb503372010-05-27 20:51:26 +0000681ModuleExport size_t RegisterRLEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000682{
683 MagickInfo
684 *entry;
685
dirk06b627a2015-04-06 18:59:17 +0000686 entry=AcquireMagickInfo("RLE","RLE","Utah Run length encoded image");
cristy3ed852e2009-09-05 21:47:34 +0000687 entry->decoder=(DecodeImageHandler *) ReadRLEImage;
688 entry->magick=(IsImageFormatHandler *) IsRLE;
dirk08e9a112015-02-22 01:51:41 +0000689 entry->flags^=CoderAdjoinFlag;
cristy3ed852e2009-09-05 21:47:34 +0000690 (void) RegisterMagickInfo(entry);
691 return(MagickImageCoderSignature);
692}
693
694/*
695%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
696% %
697% %
698% %
699% U n r e g i s t e r R L E I m a g e %
700% %
701% %
702% %
703%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
704%
705% UnregisterRLEImage() removes format registrations made by the
706% RLE module from the list of supported formats.
707%
708% The format of the UnregisterRLEImage method is:
709%
710% UnregisterRLEImage(void)
711%
712*/
713ModuleExport void UnregisterRLEImage(void)
714{
715 (void) UnregisterMagickInfo("RLE");
716}