blob: cf184f1daab59d93fb66f280a58543e21534f5b9 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% CCC U U TTTTT %
6% C U U T %
7% C U U T %
8% C U U T %
9% CCC UUU T %
10% %
11% %
12% Read DR Halo Image Format %
13% %
14% Software Design %
15% Jaroslav Fojtik %
16% June 2000 %
17% %
18% %
19% Permission is hereby granted, free of charge, to any person obtaining a %
20% copy of this software and associated documentation files ("ImageMagick"), %
21% to deal in ImageMagick without restriction, including without limitation %
22% the rights to use, copy, modify, merge, publish, distribute, sublicense, %
23% and/or sell copies of ImageMagick, and to permit persons to whom the %
24% ImageMagick is furnished to do so, subject to the following conditions: %
25% %
26% The above copyright notice and this permission notice shall be included in %
27% all copies or substantial portions of ImageMagick. %
28% %
29% The software is provided "as is", without warranty of any kind, express or %
30% implied, including but not limited to the warranties of merchantability, %
31% fitness for a particular purpose and noninfringement. In no event shall %
32% ImageMagick Studio be liable for any claim, damages or other liability, %
33% whether in an action of contract, tort or otherwise, arising from, out of %
34% or in connection with ImageMagick or the use or other dealings in %
35% ImageMagick. %
36% %
37% Except as contained in this notice, the name of the ImageMagick Studio %
38% shall not be used in advertising or otherwise to promote the sale, use or %
39% other dealings in ImageMagick without prior written authorization from the %
40% ImageMagick Studio. %
41% %
42%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
43%
44%
45*/
46
47/*
48 Include declarations.
49*/
cristy4c08aed2011-07-01 19:47:50 +000050#include "MagickCore/studio.h"
51#include "MagickCore/attribute.h"
52#include "MagickCore/blob.h"
53#include "MagickCore/blob-private.h"
54#include "MagickCore/cache.h"
55#include "MagickCore/color.h"
56#include "MagickCore/color-private.h"
57#include "MagickCore/colormap.h"
58#include "MagickCore/colormap-private.h"
59#include "MagickCore/exception.h"
60#include "MagickCore/exception-private.h"
61#include "MagickCore/image.h"
62#include "MagickCore/image-private.h"
63#include "MagickCore/list.h"
64#include "MagickCore/magick.h"
65#include "MagickCore/memory_.h"
66#include "MagickCore/pixel-accessor.h"
67#include "MagickCore/quantum-private.h"
68#include "MagickCore/static.h"
69#include "MagickCore/string_.h"
70#include "MagickCore/module.h"
71#include "MagickCore/utility.h"
cristy18c6c272011-09-23 14:40:37 +000072#include "MagickCore/utility-private.h"
cristy3ed852e2009-09-05 21:47:34 +000073
74typedef struct
75{
76 unsigned Width;
77 unsigned Height;
78 unsigned Reserved;
79} CUTHeader;
80
81typedef struct
82{
83 char FileId[2];
84 unsigned Version;
85 unsigned Size;
86 char FileType;
87 char SubType;
88 unsigned BoardID;
89 unsigned GraphicsMode;
90 unsigned MaxIndex;
91 unsigned MaxRed;
92 unsigned MaxGreen;
93 unsigned MaxBlue;
94 char PaletteId[20];
95} CUTPalHeader;
96
97
cristyc82a27b2011-10-21 01:07:16 +000098static void InsertRow(Image *image,ssize_t depth,unsigned char *p,ssize_t y,
99 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000100{
cristybb503372010-05-27 20:51:26 +0000101 size_t bit; ssize_t x;
cristy4c08aed2011-07-01 19:47:50 +0000102 register Quantum *q;
103 Quantum index;
cristy3ed852e2009-09-05 21:47:34 +0000104
cristy4c08aed2011-07-01 19:47:50 +0000105 index=0;
cristy3ed852e2009-09-05 21:47:34 +0000106 switch (depth)
cristy4e82e512011-04-24 01:33:42 +0000107 {
cristy3ed852e2009-09-05 21:47:34 +0000108 case 1: /* Convert bitmap scanline. */
109 {
110 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000111 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000112 break;
cristybb503372010-05-27 20:51:26 +0000113 for (x=0; x < ((ssize_t) image->columns-7); x+=8)
cristy4e82e512011-04-24 01:33:42 +0000114 {
115 for (bit=0; bit < 8; bit++)
cristy3ed852e2009-09-05 21:47:34 +0000116 {
cristy4c08aed2011-07-01 19:47:50 +0000117 index=(Quantum) ((((*p) & (0x80 >> bit)) != 0) ? 0x01 : 0x00);
118 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000119 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000120 }
cristy4e82e512011-04-24 01:33:42 +0000121 p++;
122 }
cristy3ed852e2009-09-05 21:47:34 +0000123 if ((image->columns % 8) != 0)
124 {
125 for (bit=0; bit < (image->columns % 8); bit++)
126 {
cristy4c08aed2011-07-01 19:47:50 +0000127 index=(Quantum) ((((*p) & (0x80 >> bit)) != 0) ? 0x01 : 0x00);
128 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000129 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000130 }
131 p++;
132 }
133 if (SyncAuthenticPixels(image,exception) == MagickFalse)
134 break;
cristy3ed852e2009-09-05 21:47:34 +0000135 break;
136 }
137 case 2: /* Convert PseudoColor scanline. */
138 {
139 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000140 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000141 break;
cristybb503372010-05-27 20:51:26 +0000142 for (x=0; x < ((ssize_t) image->columns-1); x+=2)
cristy4c08aed2011-07-01 19:47:50 +0000143 {
cristyc82a27b2011-10-21 01:07:16 +0000144 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
cristy4c08aed2011-07-01 19:47:50 +0000145 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000146 q+=GetPixelChannels(image);
cristyc82a27b2011-10-21 01:07:16 +0000147 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
cristy4c08aed2011-07-01 19:47:50 +0000148 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000149 q+=GetPixelChannels(image);
cristyc82a27b2011-10-21 01:07:16 +0000150 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,exception);
cristy4c08aed2011-07-01 19:47:50 +0000151 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000152 q+=GetPixelChannels(image);
cristyc82a27b2011-10-21 01:07:16 +0000153 index=ConstrainColormapIndex(image,(*p) & 0x3,exception);
cristy4c08aed2011-07-01 19:47:50 +0000154 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000155 q+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +0000156 p++;
157 }
cristy3ed852e2009-09-05 21:47:34 +0000158 if ((image->columns % 4) != 0)
159 {
cristyc82a27b2011-10-21 01:07:16 +0000160 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
cristy4c08aed2011-07-01 19:47:50 +0000161 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000162 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000163 if ((image->columns % 4) >= 1)
164
165 {
cristyc82a27b2011-10-21 01:07:16 +0000166 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
cristy4c08aed2011-07-01 19:47:50 +0000167 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000168 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000169 if ((image->columns % 4) >= 2)
170
171 {
cristyc82a27b2011-10-21 01:07:16 +0000172 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,
173 exception);
cristy4c08aed2011-07-01 19:47:50 +0000174 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000175 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000176 }
177 }
178 p++;
179 }
180 if (SyncAuthenticPixels(image,exception) == MagickFalse)
181 break;
cristy3ed852e2009-09-05 21:47:34 +0000182 break;
183 }
184
185 case 4: /* Convert PseudoColor scanline. */
186 {
187 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000188 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000189 break;
cristybb503372010-05-27 20:51:26 +0000190 for (x=0; x < ((ssize_t) image->columns-1); x+=2)
cristy4c08aed2011-07-01 19:47:50 +0000191 {
cristyc82a27b2011-10-21 01:07:16 +0000192 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf,exception);
cristy4c08aed2011-07-01 19:47:50 +0000193 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000194 q+=GetPixelChannels(image);
cristyc82a27b2011-10-21 01:07:16 +0000195 index=ConstrainColormapIndex(image,(*p) & 0xf,exception);
cristy4c08aed2011-07-01 19:47:50 +0000196 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000197 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000198 p++;
199 }
200 if ((image->columns % 2) != 0)
201 {
cristyc82a27b2011-10-21 01:07:16 +0000202 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf,exception);
cristy4c08aed2011-07-01 19:47:50 +0000203 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000204 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000205 p++;
206 }
207 if (SyncAuthenticPixels(image,exception) == MagickFalse)
208 break;
cristy3ed852e2009-09-05 21:47:34 +0000209 break;
210 }
211 case 8: /* Convert PseudoColor scanline. */
212 {
213 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000214 if (q == (Quantum *) NULL) break;
cristybb503372010-05-27 20:51:26 +0000215 for (x=0; x < (ssize_t) image->columns; x++)
cristy4e82e512011-04-24 01:33:42 +0000216 {
cristyc82a27b2011-10-21 01:07:16 +0000217 index=ConstrainColormapIndex(image,*p,exception);
cristy4c08aed2011-07-01 19:47:50 +0000218 SetPixelIndex(image,index,q);
cristy4e82e512011-04-24 01:33:42 +0000219 p++;
cristyed231572011-07-14 02:18:59 +0000220 q+=GetPixelChannels(image);
cristy4e82e512011-04-24 01:33:42 +0000221 }
cristy3ed852e2009-09-05 21:47:34 +0000222 if (SyncAuthenticPixels(image,exception) == MagickFalse)
223 break;
cristy3ed852e2009-09-05 21:47:34 +0000224 }
225 break;
226
227 }
228}
229
230/*
231 Compute the number of colors in Grayed R[i]=G[i]=B[i] image
232*/
cristyc82a27b2011-10-21 01:07:16 +0000233static int GetCutColors(Image *image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000234{
cristy3ed852e2009-09-05 21:47:34 +0000235 Quantum
236 intensity,
237 scale_intensity;
238
cristy4c08aed2011-07-01 19:47:50 +0000239 register Quantum
cristy4e82e512011-04-24 01:33:42 +0000240 *q;
241
242 ssize_t
243 x,
244 y;
245
cristy3ed852e2009-09-05 21:47:34 +0000246 intensity=0;
247 scale_intensity=ScaleCharToQuantum(16);
cristybb503372010-05-27 20:51:26 +0000248 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000249 {
250 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
cristybb503372010-05-27 20:51:26 +0000251 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000252 {
cristy4c08aed2011-07-01 19:47:50 +0000253 if (intensity < GetPixelRed(image,q))
254 intensity=GetPixelRed(image,q);
cristy3ed852e2009-09-05 21:47:34 +0000255 if (intensity >= scale_intensity)
256 return(255);
cristyed231572011-07-14 02:18:59 +0000257 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000258 }
259 }
260 if (intensity < ScaleCharToQuantum(2))
261 return(2);
262 if (intensity < ScaleCharToQuantum(16))
263 return(16);
264 return((int) intensity);
265}
266
267/*
268%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269% %
270% %
271% %
272% R e a d C U T I m a g e %
273% %
274% %
275% %
276%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
277%
278% ReadCUTImage() reads an CUT X image file and returns it. It
279% allocates the memory necessary for the new Image structure and returns a
280% pointer to the new image.
281%
282% The format of the ReadCUTImage method is:
283%
284% Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
285%
286% A description of each parameter follows:
287%
288% o image_info: the image info.
289%
290% o exception: return any errors or warnings in this structure.
291%
292*/
293static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
294{
295 Image *image,*palette;
296 ImageInfo *clone_info;
297 MagickBooleanType status;
298
299 MagickOffsetType
300 offset;
301
cristybb503372010-05-27 20:51:26 +0000302 size_t EncodedByte;
cristy3ed852e2009-09-05 21:47:34 +0000303 unsigned char RunCount,RunValue,RunCountMasked;
304 CUTHeader Header;
305 CUTPalHeader PalHeader;
cristybb503372010-05-27 20:51:26 +0000306 ssize_t depth;
307 ssize_t i,j;
308 ssize_t ldblk;
cristy3ed852e2009-09-05 21:47:34 +0000309 unsigned char *BImgBuff=NULL,*ptrB;
cristy4c08aed2011-07-01 19:47:50 +0000310 register Quantum *q;
cristy3ed852e2009-09-05 21:47:34 +0000311
cristy3ed852e2009-09-05 21:47:34 +0000312 /*
313 Open image file.
314 */
315 assert(image_info != (const ImageInfo *) NULL);
316 assert(image_info->signature == MagickSignature);
317 if (image_info->debug != MagickFalse)
318 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
319 image_info->filename);
320 assert(exception != (ExceptionInfo *) NULL);
321 assert(exception->signature == MagickSignature);
cristy9950d572011-10-01 18:22:35 +0000322 image=AcquireImage(image_info,exception);
cristy3ed852e2009-09-05 21:47:34 +0000323 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
324 if (status == MagickFalse)
325 {
326 image=DestroyImageList(image);
327 return((Image *) NULL);
328 }
329 /*
330 Read CUT image.
331 */
332 palette=NULL;
333 clone_info=NULL;
334 Header.Width=ReadBlobLSBShort(image);
335 Header.Height=ReadBlobLSBShort(image);
336 Header.Reserved=ReadBlobLSBShort(image);
337
338 if (Header.Width==0 || Header.Height==0 || Header.Reserved!=0)
339 CUT_KO: ThrowReaderException(CorruptImageError,"ImproperImageHeader");
340
341 /*---This code checks first line of image---*/
342 EncodedByte=ReadBlobLSBShort(image);
343 RunCount=(unsigned char) ReadBlobByte(image);
344 RunCountMasked=RunCount & 0x7F;
345 ldblk=0;
346 while((int) RunCountMasked!=0) /*end of line?*/
347 {
348 i=1;
cristybb503372010-05-27 20:51:26 +0000349 if((int) RunCount<0x80) i=(ssize_t) RunCountMasked;
cristy3ed852e2009-09-05 21:47:34 +0000350 offset=SeekBlob(image,TellBlob(image)+i,SEEK_SET);
351 if (offset < 0)
352 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
353 if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data*/
354 EncodedByte-=i+1;
cristybb503372010-05-27 20:51:26 +0000355 ldblk+=(ssize_t) RunCountMasked;
cristy3ed852e2009-09-05 21:47:34 +0000356
357 RunCount=(unsigned char) ReadBlobByte(image);
358 if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data: unexpected eof in line*/
359 RunCountMasked=RunCount & 0x7F;
360 }
361 if(EncodedByte!=1) goto CUT_KO; /*wrong data: size incorrect*/
362 i=0; /*guess a number of bit planes*/
363 if(ldblk==(int) Header.Width) i=8;
364 if(2*ldblk==(int) Header.Width) i=4;
365 if(8*ldblk==(int) Header.Width) i=1;
366 if(i==0) goto CUT_KO; /*wrong data: incorrect bit planes*/
367 depth=i;
368
369 image->columns=Header.Width;
370 image->rows=Header.Height;
371 image->depth=8;
cristybb503372010-05-27 20:51:26 +0000372 image->colors=(size_t) (GetQuantumRange(1UL*i)+1);
cristy3ed852e2009-09-05 21:47:34 +0000373
374 if (image_info->ping) goto Finish;
375
376 /* ----- Do something with palette ----- */
377 if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette;
378
379
cristybb503372010-05-27 20:51:26 +0000380 i=(ssize_t) strlen(clone_info->filename);
cristy3ed852e2009-09-05 21:47:34 +0000381 j=i;
382 while(--i>0)
383 {
384 if(clone_info->filename[i]=='.')
385 {
386 break;
387 }
388 if(clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' ||
389 clone_info->filename[i]==':' )
390 {
391 i=j;
392 break;
393 }
394 }
395
396 (void) CopyMagickString(clone_info->filename+i,".PAL",(size_t)
397 (MaxTextExtent-i));
cristy18c6c272011-09-23 14:40:37 +0000398 if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL)
cristy3ed852e2009-09-05 21:47:34 +0000399 {
400 (void) CopyMagickString(clone_info->filename+i,".pal",(size_t)
401 (MaxTextExtent-i));
cristy18c6c272011-09-23 14:40:37 +0000402 if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL)
cristy3ed852e2009-09-05 21:47:34 +0000403 {
404 clone_info->filename[i]='\0';
cristy18c6c272011-09-23 14:40:37 +0000405 if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL)
cristy3ed852e2009-09-05 21:47:34 +0000406 {
407 clone_info=DestroyImageInfo(clone_info);
408 clone_info=NULL;
409 goto NoPalette;
410 }
411 }
412 }
413
cristy9950d572011-10-01 18:22:35 +0000414 if( (palette=AcquireImage(clone_info,exception))==NULL ) goto NoPalette;
cristy3ed852e2009-09-05 21:47:34 +0000415 status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception);
416 if (status == MagickFalse)
417 {
418 ErasePalette:
419 palette=DestroyImage(palette);
420 palette=NULL;
421 goto NoPalette;
422 }
423
424
425 if(palette!=NULL)
426 {
cristyda16f162011-02-19 23:52:17 +0000427 (void) ReadBlob(palette,2,(unsigned char *) PalHeader.FileId);
cristy3ed852e2009-09-05 21:47:34 +0000428 if(strncmp(PalHeader.FileId,"AH",2) != 0) goto ErasePalette;
429 PalHeader.Version=ReadBlobLSBShort(palette);
430 PalHeader.Size=ReadBlobLSBShort(palette);
431 PalHeader.FileType=(char) ReadBlobByte(palette);
432 PalHeader.SubType=(char) ReadBlobByte(palette);
433 PalHeader.BoardID=ReadBlobLSBShort(palette);
434 PalHeader.GraphicsMode=ReadBlobLSBShort(palette);
435 PalHeader.MaxIndex=ReadBlobLSBShort(palette);
436 PalHeader.MaxRed=ReadBlobLSBShort(palette);
437 PalHeader.MaxGreen=ReadBlobLSBShort(palette);
438 PalHeader.MaxBlue=ReadBlobLSBShort(palette);
cristyda16f162011-02-19 23:52:17 +0000439 (void) ReadBlob(palette,20,(unsigned char *) PalHeader.PaletteId);
cristy3ed852e2009-09-05 21:47:34 +0000440
441 if(PalHeader.MaxIndex<1) goto ErasePalette;
442 image->colors=PalHeader.MaxIndex+1;
cristy018f07f2011-09-04 21:15:19 +0000443 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) goto NoMemory;
cristy3ed852e2009-09-05 21:47:34 +0000444
445 if(PalHeader.MaxRed==0) PalHeader.MaxRed=(unsigned int) QuantumRange; /*avoid division by 0*/
446 if(PalHeader.MaxGreen==0) PalHeader.MaxGreen=(unsigned int) QuantumRange;
447 if(PalHeader.MaxBlue==0) PalHeader.MaxBlue=(unsigned int) QuantumRange;
448
449 for(i=0;i<=(int) PalHeader.MaxIndex;i++)
450 { /*this may be wrong- I don't know why is palette such strange*/
cristybb503372010-05-27 20:51:26 +0000451 j=(ssize_t) TellBlob(palette);
cristy3ed852e2009-09-05 21:47:34 +0000452 if((j % 512)>512-6)
453 {
454 j=((j / 512)+1)*512;
455 offset=SeekBlob(palette,j,SEEK_SET);
456 if (offset < 0)
457 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
458 }
459 image->colormap[i].red=(Quantum) ReadBlobLSBShort(palette);
cristy4f3c0be2009-09-12 16:04:05 +0000460 if (QuantumRange != (Quantum) PalHeader.MaxRed)
cristy3ed852e2009-09-05 21:47:34 +0000461 {
cristyce70c172010-01-07 17:15:30 +0000462 image->colormap[i].red=ClampToQuantum(((double)
cristy3ed852e2009-09-05 21:47:34 +0000463 image->colormap[i].red*QuantumRange+(PalHeader.MaxRed>>1))/
464 PalHeader.MaxRed);
465 }
466 image->colormap[i].green=(Quantum) ReadBlobLSBShort(palette);
cristy4f3c0be2009-09-12 16:04:05 +0000467 if (QuantumRange != (Quantum) PalHeader.MaxGreen)
cristy3ed852e2009-09-05 21:47:34 +0000468 {
cristyce70c172010-01-07 17:15:30 +0000469 image->colormap[i].green=ClampToQuantum
cristy3ed852e2009-09-05 21:47:34 +0000470 (((double) image->colormap[i].green*QuantumRange+(PalHeader.MaxGreen>>1))/PalHeader.MaxGreen);
471 }
472 image->colormap[i].blue=(Quantum) ReadBlobLSBShort(palette);
cristy4f3c0be2009-09-12 16:04:05 +0000473 if (QuantumRange != (Quantum) PalHeader.MaxBlue)
cristy3ed852e2009-09-05 21:47:34 +0000474 {
cristyce70c172010-01-07 17:15:30 +0000475 image->colormap[i].blue=ClampToQuantum
cristy3ed852e2009-09-05 21:47:34 +0000476 (((double)image->colormap[i].blue*QuantumRange+(PalHeader.MaxBlue>>1))/PalHeader.MaxBlue);
477 }
478
479 }
480 }
481
482
483
484 NoPalette:
485 if(palette==NULL)
486 {
487
488 image->colors=256;
cristy018f07f2011-09-04 21:15:19 +0000489 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000490 {
491 NoMemory:
492 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
493 }
494
cristybb503372010-05-27 20:51:26 +0000495 for (i=0; i < (ssize_t)image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000496 {
497 image->colormap[i].red=ScaleCharToQuantum((unsigned char) i);
498 image->colormap[i].green=ScaleCharToQuantum((unsigned char) i);
499 image->colormap[i].blue=ScaleCharToQuantum((unsigned char) i);
500 }
501 }
502
503
504 /* ----- Load RLE compressed raster ----- */
505 BImgBuff=(unsigned char *) AcquireQuantumMemory((size_t) ldblk,
506 sizeof(*BImgBuff)); /*Ldblk was set in the check phase*/
507 if(BImgBuff==NULL) goto NoMemory;
508
509 offset=SeekBlob(image,6 /*sizeof(Header)*/,SEEK_SET);
510 if (offset < 0)
511 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
512 for (i=0; i < (int) Header.Height; i++)
513 {
514 EncodedByte=ReadBlobLSBShort(image);
515
516 ptrB=BImgBuff;
517 j=ldblk;
518
519 RunCount=(unsigned char) ReadBlobByte(image);
520 RunCountMasked=RunCount & 0x7F;
521
cristy4e82e512011-04-24 01:33:42 +0000522 while ((int) RunCountMasked != 0)
523 {
cristybb503372010-05-27 20:51:26 +0000524 if((ssize_t) RunCountMasked>j)
cristy3ed852e2009-09-05 21:47:34 +0000525 { /*Wrong Data*/
526 RunCountMasked=(unsigned char) j;
527 if(j==0)
528 {
529 break;
530 }
531 }
532
533 if((int) RunCount>0x80)
534 {
535 RunValue=(unsigned char) ReadBlobByte(image);
536 (void) ResetMagickMemory(ptrB,(int) RunValue,(size_t) RunCountMasked);
537 }
538 else {
cristyda16f162011-02-19 23:52:17 +0000539 (void) ReadBlob(image,(size_t) RunCountMasked,ptrB);
cristy3ed852e2009-09-05 21:47:34 +0000540 }
541
542 ptrB+=(int) RunCountMasked;
543 j-=(int) RunCountMasked;
544
545 if (EOFBlob(image) != MagickFalse) goto Finish; /* wrong data: unexpected eof in line */
546 RunCount=(unsigned char) ReadBlobByte(image);
547 RunCountMasked=RunCount & 0x7F;
548 }
549
cristyc82a27b2011-10-21 01:07:16 +0000550 InsertRow(image,depth,BImgBuff,i,exception);
cristy3ed852e2009-09-05 21:47:34 +0000551 }
cristyea1a8aa2011-10-20 13:24:06 +0000552 (void) SyncImage(image,exception);
cristy3ed852e2009-09-05 21:47:34 +0000553
554
555 /*detect monochrome image*/
556
557 if(palette==NULL)
558 { /*attempt to detect binary (black&white) images*/
559 if ((image->storage_class == PseudoClass) &&
cristyc82a27b2011-10-21 01:07:16 +0000560 (IsImageGray(image,exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +0000561 {
cristyc82a27b2011-10-21 01:07:16 +0000562 if(GetCutColors(image,exception)==2)
cristy3ed852e2009-09-05 21:47:34 +0000563 {
cristybb503372010-05-27 20:51:26 +0000564 for (i=0; i < (ssize_t)image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000565 {
566 register Quantum
567 sample;
568 sample=ScaleCharToQuantum((unsigned char) i);
569 if(image->colormap[i].red!=sample) goto Finish;
570 if(image->colormap[i].green!=sample) goto Finish;
571 if(image->colormap[i].blue!=sample) goto Finish;
572 }
573
cristy9fff7b42011-04-29 01:09:31 +0000574 image->colormap[1].red=image->colormap[1].green=
575 image->colormap[1].blue=(Quantum) QuantumRange;
cristybb503372010-05-27 20:51:26 +0000576 for (i=0; i < (ssize_t)image->rows; i++)
cristy3ed852e2009-09-05 21:47:34 +0000577 {
578 q=QueueAuthenticPixels(image,0,i,image->columns,1,exception);
cristybb503372010-05-27 20:51:26 +0000579 for (j=0; j < (ssize_t)image->columns; j++)
cristy3ed852e2009-09-05 21:47:34 +0000580 {
cristy4c08aed2011-07-01 19:47:50 +0000581 if (GetPixelRed(image,q) == ScaleCharToQuantum(1))
cristy3ed852e2009-09-05 21:47:34 +0000582 {
cristy4c08aed2011-07-01 19:47:50 +0000583 SetPixelRed(image,QuantumRange,q);
584 SetPixelGreen(image,QuantumRange,q);
585 SetPixelBlue(image,QuantumRange,q);
cristy3ed852e2009-09-05 21:47:34 +0000586 }
cristyed231572011-07-14 02:18:59 +0000587 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000588 }
589 if (SyncAuthenticPixels(image,exception) == MagickFalse) goto Finish;
590 }
591 }
592 }
593 }
594
595 Finish:
596 if (BImgBuff != NULL)
597 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
598 if (palette != NULL)
599 palette=DestroyImage(palette);
600 if (clone_info != NULL)
601 clone_info=DestroyImageInfo(clone_info);
602 if (EOFBlob(image) != MagickFalse)
603 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
604 image->filename);
605 (void) CloseBlob(image);
606 return(GetFirstImageInList(image));
607}
608
609/*
610%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611% %
612% %
613% %
614% R e g i s t e r C U T I m a g e %
615% %
616% %
617% %
618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619%
620% RegisterCUTImage() adds attributes for the CUT image format to
621% the list of supported formats. The attributes include the image format
622% tag, a method to read and/or write the format, whether the format
623% supports the saving of more than one frame to the same file or blob,
624% whether the format supports native in-memory I/O, and a brief
625% description of the format.
626%
627% The format of the RegisterCUTImage method is:
628%
cristybb503372010-05-27 20:51:26 +0000629% size_t RegisterCUTImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000630%
631*/
cristybb503372010-05-27 20:51:26 +0000632ModuleExport size_t RegisterCUTImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000633{
634 MagickInfo
635 *entry;
636
637 entry=SetMagickInfo("CUT");
638 entry->decoder=(DecodeImageHandler *) ReadCUTImage;
639 entry->seekable_stream=MagickTrue;
640 entry->description=ConstantString("DR Halo");
641 entry->module=ConstantString("CUT");
642 (void) RegisterMagickInfo(entry);
643 return(MagickImageCoderSignature);
644}
645
646/*
647%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
648% %
649% %
650% %
651% U n r e g i s t e r C U T I m a g e %
652% %
653% %
654% %
655%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
656%
657% UnregisterCUTImage() removes format registrations made by the
658% CUT module from the list of supported formats.
659%
660% The format of the UnregisterCUTImage method is:
661%
662% UnregisterCUTImage(void)
663%
664*/
665ModuleExport void UnregisterCUTImage(void)
666{
667 (void) UnregisterMagickInfo("CUT");
668}