2
% Copyright (C) 2003 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
6
% This program is covered by multiple licenses, which are described in
7
% Copyright.txt. You should have received a copy of Copyright.txt with this
8
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
21
% Read URT RLE Image Format. %
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38
#include "magick/studio.h"
39
#include "magick/attribute.h"
40
#include "magick/blob.h"
41
#include "magick/cache.h"
42
#include "magick/magick.h"
43
#include "magick/monitor.h"
44
#include "magick/utility.h"
47
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57
% Method IsRLE returns True if the image format type, identified by the
58
% magick string, is RLE.
60
% The format of the ReadRLEImage method is:
62
% unsigned int IsRLE(const unsigned char *magick,const size_t length)
64
% A description of each parameter follows:
66
% o status: Method IsRLE returns True if the image format type is RLE.
68
% o magick: This string is generally the first few bytes of an image file
71
% o length: Specifies the length of the magick string.
75
static unsigned int IsRLE(const unsigned char *magick,const size_t length)
79
if (memcmp(magick,"\122\314",2) == 0)
85
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89
% R e a d R L E I m a g e %
93
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95
% Method ReadRLEImage reads a run-length encoded Utah Raster Toolkit
96
% image file and returns it. It allocates the memory necessary for the new
97
% Image structure and returns a pointer to the new image.
99
% The format of the ReadRLEImage method is:
101
% Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
103
% A description of each parameter follows:
105
% o image: Method ReadRLEImage returns a pointer to the image after
106
% reading. A null image is returned if there is a memory shortage or
107
% if the image cannot be read.
109
% o image_info: Specifies a pointer to a ImageInfo structure.
111
% o exception: return any errors or warnings in this structure.
115
static Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
117
#define SkipLinesOp 0x01
118
#define SetColorOp 0x02
119
#define SkipPixelsOp 0x03
120
#define ByteDataOp 0x05
121
#define RunDataOp 0x06
150
register unsigned char
157
background_color[256],
176
assert(image_info != (const ImageInfo *) NULL);
177
assert(image_info->signature == MagickSignature);
178
assert(exception != (ExceptionInfo *) NULL);
179
assert(exception->signature == MagickSignature);
180
image=AllocateImage(image_info);
181
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
183
ThrowReaderException(FileOpenError,UnableToOpenFile,image);
185
Determine if this is a RLE file.
187
count=ReadBlob(image,2,(char *) magick);
188
if ((count == 0) || (memcmp(magick,"\122\314",2) != 0))
189
ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
195
(void) ReadBlobLSBShort(image);
196
(void) ReadBlobLSBShort(image);
197
image->columns=ReadBlobLSBShort(image);
198
image->rows=ReadBlobLSBShort(image);
199
flags=ReadBlobByte(image);
200
image->matte=flags & 0x04;
201
number_planes=ReadBlobByte(image);
202
bits_per_pixel=ReadBlobByte(image);
203
number_colormaps=ReadBlobByte(image);
204
map_length=1 << ReadBlobByte(image);
205
if ((number_planes == 0) || (number_planes == 2) || (bits_per_pixel != 8) ||
206
(image->columns == 0))
207
ThrowReaderException(CoderError,DataEncodingSchemeIsNotSupported,image);
211
No background color-- initialize to black.
213
for (i=0; i < (long) number_planes; i++)
214
background_color[i]=0;
215
(void) ReadBlobByte(image);
220
Initialize background color.
223
for (i=0; i < (long) number_planes; i++)
224
*p++=ReadBlobByte(image);
226
if ((number_planes & 0x01) == 0)
227
(void) ReadBlobByte(image);
228
colormap=(unsigned char *) NULL;
229
if (number_colormaps != 0)
232
Read image colormaps.
234
colormap=MagickAllocateMemory(unsigned char *,number_colormaps*map_length);
235
if (colormap == (unsigned char *) NULL)
236
ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
239
for (i=0; i < (long) number_colormaps; i++)
240
for (x=0; x < (long) map_length; x++)
241
*p++=ScaleShortToQuantum(ReadBlobLSBShort(image));
254
length=ReadBlobLSBShort(image);
255
comment=MagickAllocateMemory(char *,length);
256
if (comment == (char *) NULL)
257
ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
259
(void) ReadBlob(image,length-1,comment);
260
comment[length-1]='\0';
261
(void) SetImageAttribute(image,"comment",comment);
262
MagickFreeMemory(comment);
263
if ((length & 0x01) == 0)
264
(void) ReadBlobByte(image);
266
if (image_info->ping && (image_info->subrange != 0))
267
if (image->scene >= (image_info->subimage+image_info->subrange-1))
274
number_pixels=image->columns*image->rows;
275
rle_pixels=MagickAllocateMemory(unsigned char *,number_pixels*number_planes);
276
if (rle_pixels == (unsigned char *) NULL)
277
ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
278
if ((flags & 0x01) && !(flags & 0x02))
284
Set background color.
287
for (i=0; i < (long) number_pixels; i++)
290
for (j=0; j < (long) number_planes; j++)
291
*p++=background_color[j];
294
for (j=0; j < (long) (number_planes-1); j++)
295
*p++=background_color[j];
296
*p++=0; /* initialize matte channel */
301
Read runlength-encoded image.
306
opcode=ReadBlobByte(image);
309
switch (opcode & 0x3f)
313
operand=ReadBlobByte(image);
315
operand=ReadBlobLSBShort(image);
322
operand=ReadBlobByte(image);
323
plane=(unsigned char) operand;
325
plane=(unsigned char) (number_planes-1);
331
operand=ReadBlobByte(image);
333
operand=ReadBlobLSBShort(image);
339
operand=ReadBlobByte(image);
341
operand=ReadBlobLSBShort(image);
342
p=rle_pixels+((image->rows-y-1)*image->columns*number_planes)+
343
x*number_planes+plane;
345
for (i=0; i < (long) operand; i++)
347
pixel=ReadBlobByte(image);
348
if ((y < (long) image->rows) && ((x+i) < (long) image->columns))
353
(void) ReadBlobByte(image);
359
operand=ReadBlobByte(image);
361
operand=ReadBlobLSBShort(image);
362
pixel=ReadBlobByte(image);
363
(void) ReadBlobByte(image);
365
p=rle_pixels+((image->rows-y-1)*image->columns*number_planes)+
366
x*number_planes+plane;
367
for (i=0; i < (long) operand; i++)
369
if ((y < (long) image->rows) && ((x+i) < (long) image->columns))
379
opcode=ReadBlobByte(image);
380
} while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
381
if (number_colormaps != 0)
387
Apply colormap affineation to image.
391
if (number_colormaps == 1)
392
for (i=0; i < (long) number_pixels; i++)
394
*p=colormap[*p & mask];
398
if ((number_planes >= 3) && (number_colormaps >= 3))
399
for (i=0; i < (long) number_pixels; i++)
400
for (x=0; x < (long) number_planes; x++)
402
*p=colormap[x*map_length+(*p & mask)];
407
Initialize image structure.
409
if (number_planes >= 3)
412
Convert raster image to DirectClass pixel packets.
415
for (y=0; y < (long) image->rows; y++)
417
q=SetImagePixels(image,0,y,image->columns,1);
418
if (q == (PixelPacket *) NULL)
420
for (x=0; x < (long) image->columns; x++)
422
q->red=ScaleCharToQuantum(*p++);
423
q->green=ScaleCharToQuantum(*p++);
424
q->blue=ScaleCharToQuantum(*p++);
426
q->opacity=(Quantum) (MaxRGB-ScaleCharToQuantum(*p++));
429
if (!SyncImagePixels(image))
431
if (image->previous == (Image *) NULL)
432
if (QuantumTick(y,image->rows))
433
if (!MagickMonitor(LoadImageText,y,image->rows,exception))
442
if (number_colormaps == 0)
444
if (!AllocateImageColormap(image,map_length))
445
ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,
448
if (number_colormaps == 1)
449
for (i=0; i < (long) image->colors; i++)
454
image->colormap[i].red=ScaleCharToQuantum(i);
455
image->colormap[i].green=ScaleCharToQuantum(i);
456
image->colormap[i].blue=ScaleCharToQuantum(i);
459
if (number_colormaps > 1)
460
for (i=0; i < (long) image->colors; i++)
462
image->colormap[i].red=ScaleCharToQuantum(*p);
463
image->colormap[i].green=ScaleCharToQuantum(*(p+map_length));
464
image->colormap[i].blue=ScaleCharToQuantum(*(p+map_length*2));
471
Convert raster image to PseudoClass pixel packets.
473
for (y=0; y < (long) image->rows; y++)
475
q=SetImagePixels(image,0,y,image->columns,1);
476
if (q == (PixelPacket *) NULL)
478
indexes=GetIndexes(image);
479
for (x=0; x < (long) image->columns; x++)
481
if (!SyncImagePixels(image))
483
if (image->previous == (Image *) NULL)
484
if (QuantumTick(y,image->rows))
485
if (!MagickMonitor(LoadImageText,y,image->rows,exception))
493
Image has a matte channel-- promote to DirectClass.
495
for (y=0; y < (long) image->rows; y++)
497
q=SetImagePixels(image,0,y,image->columns,1);
498
if (q == (PixelPacket *) NULL)
500
for (x=0; x < (long) image->columns; x++)
502
q->red=image->colormap[*p++].red;
503
q->green=image->colormap[*p++].green;
504
q->blue=image->colormap[*p++].blue;
505
q->opacity=(Quantum) (MaxRGB-ScaleCharToQuantum(*p++));
508
if (!SyncImagePixels(image))
510
if (image->previous == (Image *) NULL)
511
if (QuantumTick(y,image->rows))
512
if (!MagickMonitor(LoadImageText,y,image->rows,exception))
515
MagickFreeMemory(image->colormap);
516
image->colormap=(PixelPacket *) NULL;
517
image->storage_class=DirectClass;
521
if (number_colormaps != 0)
522
MagickFreeMemory(colormap);
523
MagickFreeMemory(rle_pixels);
526
ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
531
Proceed to next image.
533
if (image_info->subrange != 0)
534
if (image->scene >= (image_info->subimage+image_info->subrange-1))
536
(void) ReadBlobByte(image);
537
count=ReadBlob(image,2,(char *) magick);
538
if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
541
Allocate next image structure.
543
AllocateNextImage(image_info,image);
544
if (image->next == (Image *) NULL)
546
DestroyImageList(image);
547
return((Image *) NULL);
549
image=SyncNextImageInList(image);
550
if (!MagickMonitor(LoadImagesText,TellBlob(image),GetBlobSize(image),exception))
553
} while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
554
while (image->previous != (Image *) NULL)
555
image=image->previous;
561
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
565
% R e g i s t e r R L E I m a g e %
569
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
571
% Method RegisterRLEImage adds attributes for the RLE image format to
572
% the list of supported formats. The attributes include the image format
573
% tag, a method to read and/or write the format, whether the format
574
% supports the saving of more than one frame to the same file or blob,
575
% whether the format supports native in-memory I/O, and a brief
576
% description of the format.
578
% The format of the RegisterRLEImage method is:
580
% RegisterRLEImage(void)
583
ModuleExport void RegisterRLEImage(void)
588
entry=SetMagickInfo("RLE");
589
entry->decoder=(DecoderHandler) ReadRLEImage;
590
entry->magick=(MagickHandler) IsRLE;
592
entry->description=AcquireString("Utah Run length encoded image");
593
entry->module=AcquireString("RLE");
594
(void) RegisterMagickInfo(entry);
598
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602
% U n r e g i s t e r R L E I m a g e %
606
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
608
% Method UnregisterRLEImage removes format registrations made by the
609
% RLE module from the list of supported formats.
611
% The format of the UnregisterRLEImage method is:
613
% UnregisterRLEImage(void)
616
ModuleExport void UnregisterRLEImage(void)
618
(void) UnregisterMagickInfo("RLE");