blob: fc326088cecb2a54aed12363460d80d47c714a19 [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 %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristyfe676ee2013-11-18 13:03:38 +000020% Copyright 1999-2014 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"
43#include "MagickCore/property.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
46#include "MagickCore/cache.h"
47#include "MagickCore/colormap.h"
48#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"
58#include "MagickCore/quantum-private.h"
59#include "MagickCore/pixel.h"
60#include "MagickCore/static.h"
61#include "MagickCore/string_.h"
62#include "MagickCore/module.h"
cristy3ed852e2009-09-05 21:47:34 +000063
64/*
65%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
66% %
67% %
68% %
69% I s R L E %
70% %
71% %
72% %
73%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74%
75% IsRLE() returns MagickTrue if the image format type, identified by the
76% magick string, is RLE.
77%
78% The format of the ReadRLEImage method is:
79%
80% MagickBooleanType IsRLE(const unsigned char *magick,const size_t length)
81%
82% A description of each parameter follows:
83%
84% o magick: compare image format pattern against these bytes.
85%
86% o length: Specifies the length of the magick string.
87%
88%
89*/
90static MagickBooleanType IsRLE(const unsigned char *magick,const size_t length)
91{
92 if (length < 2)
93 return(MagickFalse);
94 if (memcmp(magick,"\122\314",2) == 0)
95 return(MagickTrue);
96 return(MagickFalse);
97}
98
99/*
100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101% %
102% %
103% %
104% R e a d R L E I m a g e %
105% %
106% %
107% %
108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109%
110% ReadRLEImage() reads a run-length encoded Utah Raster Toolkit
111% image file and returns it. It allocates the memory necessary for the new
112% Image structure and returns a pointer to the new image.
113%
114% The format of the ReadRLEImage method is:
115%
116% Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
117%
118% A description of each parameter follows:
119%
120% o image_info: the image info.
121%
122% o exception: return any errors or warnings in this structure.
123%
124%
125*/
126static Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
127{
128#define SkipLinesOp 0x01
129#define SetColorOp 0x02
130#define SkipPixelsOp 0x03
131#define ByteDataOp 0x05
132#define RunDataOp 0x06
133#define EOFOp 0x07
134
135 char
136 magick[12];
137
138 Image
139 *image;
140
141 int
142 opcode,
143 operand,
144 status;
145
cristy3ed852e2009-09-05 21:47:34 +0000146 MagickStatusType
147 flags;
148
149 MagickSizeType
150 number_pixels;
151
cristyb64823d2013-06-30 20:58:24 +0000152 MemoryInfo
153 *pixel_info;
154
cristybb503372010-05-27 20:51:26 +0000155 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000156 x;
157
cristy4c08aed2011-07-01 19:47:50 +0000158 register Quantum
cristy3ed852e2009-09-05 21:47:34 +0000159 *q;
160
cristybb503372010-05-27 20:51:26 +0000161 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000162 i;
163
164 register unsigned char
165 *p;
166
cristyc6da28e2011-04-28 01:41:35 +0000167 size_t
168 bits_per_pixel,
169 map_length,
170 number_colormaps,
171 number_planes,
172 one;
173
cristy3ed852e2009-09-05 21:47:34 +0000174 ssize_t
cristyc6da28e2011-04-28 01:41:35 +0000175 count,
176 y;
cristy3ed852e2009-09-05 21:47:34 +0000177
178 unsigned char
179 background_color[256],
180 *colormap,
181 pixel,
182 plane,
cristyb64823d2013-06-30 20:58:24 +0000183 *pixels;
cristy3ed852e2009-09-05 21:47:34 +0000184
cristy3ed852e2009-09-05 21:47:34 +0000185 /*
186 Open image file.
187 */
188 assert(image_info != (const ImageInfo *) NULL);
189 assert(image_info->signature == MagickSignature);
190 if (image_info->debug != MagickFalse)
191 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
192 image_info->filename);
193 assert(exception != (ExceptionInfo *) NULL);
194 assert(exception->signature == MagickSignature);
cristy9950d572011-10-01 18:22:35 +0000195 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000196 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
197 if (status == MagickFalse)
198 {
199 image=DestroyImageList(image);
200 return((Image *) NULL);
201 }
202 /*
203 Determine if this a RLE file.
204 */
205 count=ReadBlob(image,2,(unsigned char *) magick);
206 if ((count == 0) || (memcmp(magick,"\122\314",2) != 0))
207 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
208 do
209 {
210 /*
211 Read image header.
212 */
213 (void) ReadBlobLSBShort(image);
214 (void) ReadBlobLSBShort(image);
215 image->columns=ReadBlobLSBShort(image);
216 image->rows=ReadBlobLSBShort(image);
217 flags=(MagickStatusType) ReadBlobByte(image);
cristyb0a657e2012-08-29 00:45:37 +0000218 image->alpha_trait=flags & 0x04 ? BlendPixelTrait : UndefinedPixelTrait;
cristy3ed852e2009-09-05 21:47:34 +0000219 number_planes=1UL*ReadBlobByte(image);
220 bits_per_pixel=1UL*ReadBlobByte(image);
221 number_colormaps=1UL*ReadBlobByte(image);
cristyeaedf062010-05-29 22:36:02 +0000222 one=1;
223 map_length=one << ReadBlobByte(image);
cristy3ed852e2009-09-05 21:47:34 +0000224 if ((number_planes == 0) || (number_planes == 2) || (bits_per_pixel != 8) ||
225 (image->columns == 0))
226 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
227 if (flags & 0x02)
228 {
229 /*
230 No background color-- initialize to black.
231 */
cristybb503372010-05-27 20:51:26 +0000232 for (i=0; i < (ssize_t) number_planes; i++)
cristy3ed852e2009-09-05 21:47:34 +0000233 background_color[i]=0;
234 (void) ReadBlobByte(image);
235 }
236 else
237 {
238 /*
239 Initialize background color.
240 */
241 p=background_color;
cristybb503372010-05-27 20:51:26 +0000242 for (i=0; i < (ssize_t) number_planes; i++)
cristy3ed852e2009-09-05 21:47:34 +0000243 *p++=(unsigned char) ReadBlobByte(image);
244 }
245 if ((number_planes & 0x01) == 0)
246 (void) ReadBlobByte(image);
247 colormap=(unsigned char *) NULL;
248 if (number_colormaps != 0)
249 {
250 /*
251 Read image colormaps.
252 */
253 colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps,
254 map_length*sizeof(*colormap));
255 if (colormap == (unsigned char *) NULL)
256 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
257 p=colormap;
cristybb503372010-05-27 20:51:26 +0000258 for (i=0; i < (ssize_t) number_colormaps; i++)
259 for (x=0; x < (ssize_t) map_length; x++)
cristy3ed852e2009-09-05 21:47:34 +0000260 *p++=(unsigned char) ScaleShortToQuantum(ReadBlobLSBShort(image));
261 }
262 if ((flags & 0x08) != 0)
263 {
264 char
265 *comment;
266
cristybb503372010-05-27 20:51:26 +0000267 size_t
cristy3ed852e2009-09-05 21:47:34 +0000268 length;
269
270 /*
271 Read image comment.
272 */
273 length=ReadBlobLSBShort(image);
274 if (length != 0)
275 {
276 comment=(char *) AcquireQuantumMemory(length,sizeof(*comment));
277 if (comment == (char *) NULL)
278 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
279 count=ReadBlob(image,length-1,(unsigned char *) comment);
280 comment[length-1]='\0';
cristyd15e6592011-10-15 00:13:06 +0000281 (void) SetImageProperty(image,"comment",comment,exception);
cristy3ed852e2009-09-05 21:47:34 +0000282 comment=DestroyString(comment);
283 if ((length & 0x01) == 0)
284 (void) ReadBlobByte(image);
285 }
286 }
287 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
288 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
289 break;
290 /*
291 Allocate RLE pixels.
292 */
cristy8a46d822012-08-28 23:32:39 +0000293 if (image->alpha_trait == BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000294 number_planes++;
295 number_pixels=(MagickSizeType) image->columns*image->rows;
296 if ((number_pixels*number_planes) != (size_t) (number_pixels*number_planes))
297 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristyb64823d2013-06-30 20:58:24 +0000298 pixel_info=AcquireVirtualMemory(image->columns,image->rows*number_planes*
299 sizeof(*pixels));
300 if (pixel_info == (MemoryInfo *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000301 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristyb64823d2013-06-30 20:58:24 +0000302 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
cristy3ed852e2009-09-05 21:47:34 +0000303 if ((flags & 0x01) && !(flags & 0x02))
304 {
cristybb503372010-05-27 20:51:26 +0000305 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000306 j;
307
308 /*
309 Set background color.
310 */
cristyb64823d2013-06-30 20:58:24 +0000311 p=pixels;
cristybb503372010-05-27 20:51:26 +0000312 for (i=0; i < (ssize_t) number_pixels; i++)
cristy3ed852e2009-09-05 21:47:34 +0000313 {
cristy8a46d822012-08-28 23:32:39 +0000314 if (image->alpha_trait != BlendPixelTrait)
cristybb503372010-05-27 20:51:26 +0000315 for (j=0; j < (ssize_t) number_planes; j++)
cristy3ed852e2009-09-05 21:47:34 +0000316 *p++=background_color[j];
317 else
318 {
cristybb503372010-05-27 20:51:26 +0000319 for (j=0; j < (ssize_t) (number_planes-1); j++)
cristy3ed852e2009-09-05 21:47:34 +0000320 *p++=background_color[j];
321 *p++=0; /* initialize matte channel */
322 }
323 }
324 }
325 /*
326 Read runlength-encoded image.
327 */
328 plane=0;
329 x=0;
330 y=0;
331 opcode=ReadBlobByte(image);
332 do
333 {
334 switch (opcode & 0x3f)
335 {
336 case SkipLinesOp:
337 {
338 operand=ReadBlobByte(image);
339 if (opcode & 0x40)
340 operand=(int) ReadBlobLSBShort(image);
341 x=0;
342 y+=operand;
343 break;
344 }
345 case SetColorOp:
346 {
347 operand=ReadBlobByte(image);
348 plane=(unsigned char) operand;
349 if (plane == 255)
350 plane=(unsigned char) (number_planes-1);
351 x=0;
352 break;
353 }
354 case SkipPixelsOp:
355 {
356 operand=ReadBlobByte(image);
357 if (opcode & 0x40)
358 operand=(int) ReadBlobLSBShort(image);
359 x+=operand;
360 break;
361 }
362 case ByteDataOp:
363 {
364 operand=ReadBlobByte(image);
365 if (opcode & 0x40)
366 operand=(int) ReadBlobLSBShort(image);
cristyb64823d2013-06-30 20:58:24 +0000367 p=pixels+((image->rows-y-1)*image->columns*number_planes)+
cristy3ed852e2009-09-05 21:47:34 +0000368 x*number_planes+plane;
369 operand++;
cristybb503372010-05-27 20:51:26 +0000370 for (i=0; i < (ssize_t) operand; i++)
cristy3ed852e2009-09-05 21:47:34 +0000371 {
372 pixel=(unsigned char) ReadBlobByte(image);
cristyc6da28e2011-04-28 01:41:35 +0000373 if ((y < (ssize_t) image->rows) &&
374 ((x+i) < (ssize_t) image->columns))
cristy3ed852e2009-09-05 21:47:34 +0000375 *p=pixel;
376 p+=number_planes;
377 }
378 if (operand & 0x01)
379 (void) ReadBlobByte(image);
380 x+=operand;
381 break;
382 }
383 case RunDataOp:
384 {
385 operand=ReadBlobByte(image);
386 if (opcode & 0x40)
387 operand=(int) ReadBlobLSBShort(image);
388 pixel=(unsigned char) ReadBlobByte(image);
389 (void) ReadBlobByte(image);
390 operand++;
cristyb64823d2013-06-30 20:58:24 +0000391 p=pixels+((image->rows-y-1)*image->columns*number_planes)+
cristy3ed852e2009-09-05 21:47:34 +0000392 x*number_planes+plane;
cristybb503372010-05-27 20:51:26 +0000393 for (i=0; i < (ssize_t) operand; i++)
cristy3ed852e2009-09-05 21:47:34 +0000394 {
cristyc6da28e2011-04-28 01:41:35 +0000395 if ((y < (ssize_t) image->rows) &&
396 ((x+i) < (ssize_t) image->columns))
cristy3ed852e2009-09-05 21:47:34 +0000397 *p=pixel;
398 p+=number_planes;
399 }
400 x+=operand;
401 break;
402 }
403 default:
404 break;
405 }
406 opcode=ReadBlobByte(image);
407 } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
408 if (number_colormaps != 0)
409 {
410 MagickStatusType
411 mask;
412
413 /*
414 Apply colormap affineation to image.
415 */
416 mask=(MagickStatusType) (map_length-1);
cristyb64823d2013-06-30 20:58:24 +0000417 p=pixels;
cristy3ed852e2009-09-05 21:47:34 +0000418 if (number_colormaps == 1)
cristybb503372010-05-27 20:51:26 +0000419 for (i=0; i < (ssize_t) number_pixels; i++)
cristy3ed852e2009-09-05 21:47:34 +0000420 {
421 *p=colormap[*p & mask];
422 p++;
423 }
424 else
425 if ((number_planes >= 3) && (number_colormaps >= 3))
cristybb503372010-05-27 20:51:26 +0000426 for (i=0; i < (ssize_t) number_pixels; i++)
427 for (x=0; x < (ssize_t) number_planes; x++)
cristy3ed852e2009-09-05 21:47:34 +0000428 {
429 *p=colormap[x*map_length+(*p & mask)];
430 p++;
431 }
432 }
433 /*
434 Initialize image structure.
435 */
436 if (number_planes >= 3)
437 {
438 /*
439 Convert raster image to DirectClass pixel packets.
440 */
cristyb64823d2013-06-30 20:58:24 +0000441 p=pixels;
cristybb503372010-05-27 20:51:26 +0000442 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000443 {
444 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000445 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000446 break;
cristybb503372010-05-27 20:51:26 +0000447 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000448 {
cristy4c08aed2011-07-01 19:47:50 +0000449 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
450 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
451 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
cristy8a46d822012-08-28 23:32:39 +0000452 if (image->alpha_trait == BlendPixelTrait)
cristy4c08aed2011-07-01 19:47:50 +0000453 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
cristyed231572011-07-14 02:18:59 +0000454 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000455 }
456 if (SyncAuthenticPixels(image,exception) == MagickFalse)
457 break;
458 if (image->previous == (Image *) NULL)
459 {
cristycee97112010-05-28 00:44:52 +0000460 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
461 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000462 if (status == MagickFalse)
463 break;
464 }
465 }
466 }
467 else
468 {
469 /*
470 Create colormap.
471 */
472 if (number_colormaps == 0)
473 map_length=256;
cristy018f07f2011-09-04 21:15:19 +0000474 if (AcquireImageColormap(image,map_length,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000475 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
476 p=colormap;
477 if (number_colormaps == 1)
cristybb503372010-05-27 20:51:26 +0000478 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000479 {
480 /*
481 Pseudocolor.
482 */
483 image->colormap[i].red=ScaleCharToQuantum((unsigned char) i);
484 image->colormap[i].green=ScaleCharToQuantum((unsigned char) i);
485 image->colormap[i].blue=ScaleCharToQuantum((unsigned char) i);
486 }
487 else
488 if (number_colormaps > 1)
cristybb503372010-05-27 20:51:26 +0000489 for (i=0; i < (ssize_t) image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000490 {
491 image->colormap[i].red=ScaleCharToQuantum(*p);
492 image->colormap[i].green=ScaleCharToQuantum(*(p+map_length));
493 image->colormap[i].blue=ScaleCharToQuantum(*(p+map_length*2));
494 p++;
495 }
cristyb64823d2013-06-30 20:58:24 +0000496 p=pixels;
cristy8a46d822012-08-28 23:32:39 +0000497 if (image->alpha_trait != BlendPixelTrait)
cristy3ed852e2009-09-05 21:47:34 +0000498 {
499 /*
500 Convert raster image to PseudoClass pixel packets.
501 */
cristybb503372010-05-27 20:51:26 +0000502 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000503 {
504 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000505 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000506 break;
cristybb503372010-05-27 20:51:26 +0000507 for (x=0; x < (ssize_t) image->columns; x++)
cristy4c08aed2011-07-01 19:47:50 +0000508 {
509 SetPixelIndex(image,*p++,q);
cristyed231572011-07-14 02:18:59 +0000510 q+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +0000511 }
cristy3ed852e2009-09-05 21:47:34 +0000512 if (SyncAuthenticPixels(image,exception) == MagickFalse)
513 break;
514 if (image->previous == (Image *) NULL)
515 {
cristyc6da28e2011-04-28 01:41:35 +0000516 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
517 y,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000518 if (status == MagickFalse)
519 break;
520 }
521 }
cristyea1a8aa2011-10-20 13:24:06 +0000522 (void) SyncImage(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000523 }
524 else
525 {
526 /*
527 Image has a matte channel-- promote to DirectClass.
528 */
cristybb503372010-05-27 20:51:26 +0000529 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000530 {
531 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000532 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000533 break;
cristybb503372010-05-27 20:51:26 +0000534 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000535 {
cristy4c08aed2011-07-01 19:47:50 +0000536 SetPixelRed(image,image->colormap[*p++].red,q);
537 SetPixelGreen(image,image->colormap[*p++].green,q);
538 SetPixelBlue(image,image->colormap[*p++].blue,q);
539 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
cristyed231572011-07-14 02:18:59 +0000540 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000541 }
542 if (SyncAuthenticPixels(image,exception) == MagickFalse)
543 break;
544 if (image->previous == (Image *) NULL)
545 {
cristyc6da28e2011-04-28 01:41:35 +0000546 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
547 y,image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000548 if (status == MagickFalse)
549 break;
550 }
551 }
cristy101ab702011-10-13 13:06:32 +0000552 image->colormap=(PixelInfo *) RelinquishMagickMemory(
cristy3da0b402011-05-29 21:13:36 +0000553 image->colormap);
cristy3ed852e2009-09-05 21:47:34 +0000554 image->storage_class=DirectClass;
555 image->colors=0;
556 }
557 }
558 if (number_colormaps != 0)
559 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
cristyb64823d2013-06-30 20:58:24 +0000560 pixel_info=RelinquishVirtualMemory(pixel_info);
cristy3ed852e2009-09-05 21:47:34 +0000561 if (EOFBlob(image) != MagickFalse)
562 {
563 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
564 image->filename);
565 break;
566 }
567 /*
568 Proceed to next image.
569 */
570 if (image_info->number_scenes != 0)
571 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
572 break;
573 (void) ReadBlobByte(image);
574 count=ReadBlob(image,2,(unsigned char *) magick);
575 if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
576 {
577 /*
578 Allocate next image structure.
579 */
cristy9950d572011-10-01 18:22:35 +0000580 AcquireNextImage(image_info,image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000581 if (GetNextImageInList(image) == (Image *) NULL)
582 {
583 image=DestroyImageList(image);
584 return((Image *) NULL);
585 }
586 image=SyncNextImageInList(image);
587 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
588 GetBlobSize(image));
589 if (status == MagickFalse)
590 break;
591 }
592 } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
593 (void) CloseBlob(image);
594 return(GetFirstImageInList(image));
595}
596
597/*
598%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
599% %
600% %
601% %
602% R e g i s t e r R L E I m a g e %
603% %
604% %
605% %
606%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
607%
608% RegisterRLEImage() adds attributes for the RLE image format to
609% the list of supported formats. The attributes include the image format
610% tag, a method to read and/or write the format, whether the format
611% supports the saving of more than one frame to the same file or blob,
612% whether the format supports native in-memory I/O, and a brief
613% description of the format.
614%
615% The format of the RegisterRLEImage method is:
616%
cristybb503372010-05-27 20:51:26 +0000617% size_t RegisterRLEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000618%
619*/
cristybb503372010-05-27 20:51:26 +0000620ModuleExport size_t RegisterRLEImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000621{
622 MagickInfo
623 *entry;
624
625 entry=SetMagickInfo("RLE");
626 entry->decoder=(DecodeImageHandler *) ReadRLEImage;
627 entry->magick=(IsImageFormatHandler *) IsRLE;
628 entry->adjoin=MagickFalse;
629 entry->description=ConstantString("Utah Run length encoded image");
630 entry->module=ConstantString("RLE");
631 (void) RegisterMagickInfo(entry);
632 return(MagickImageCoderSignature);
633}
634
635/*
636%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
637% %
638% %
639% %
640% U n r e g i s t e r R L E I m a g e %
641% %
642% %
643% %
644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
645%
646% UnregisterRLEImage() removes format registrations made by the
647% RLE module from the list of supported formats.
648%
649% The format of the UnregisterRLEImage method is:
650%
651% UnregisterRLEImage(void)
652%
653*/
654ModuleExport void UnregisterRLEImage(void)
655{
656 (void) UnregisterMagickInfo("RLE");
657}