blob: 091d49999cb02b5c0661f2b4544b4b23c42b03e6 [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"
cristy3ed852e2009-09-05 21:47:34 +000072
73typedef struct
74{
75 unsigned Width;
76 unsigned Height;
77 unsigned Reserved;
78} CUTHeader;
79
80typedef struct
81{
82 char FileId[2];
83 unsigned Version;
84 unsigned Size;
85 char FileType;
86 char SubType;
87 unsigned BoardID;
88 unsigned GraphicsMode;
89 unsigned MaxIndex;
90 unsigned MaxRed;
91 unsigned MaxGreen;
92 unsigned MaxBlue;
93 char PaletteId[20];
94} CUTPalHeader;
95
96
cristybb503372010-05-27 20:51:26 +000097static void InsertRow(ssize_t depth,unsigned char *p,ssize_t y,Image *image)
cristy3ed852e2009-09-05 21:47:34 +000098{
99 ExceptionInfo
100 *exception;
101
cristybb503372010-05-27 20:51:26 +0000102 size_t bit; ssize_t x;
cristy4c08aed2011-07-01 19:47:50 +0000103 register Quantum *q;
104 Quantum index;
cristy3ed852e2009-09-05 21:47:34 +0000105
cristy4c08aed2011-07-01 19:47:50 +0000106 index=0;
cristy3ed852e2009-09-05 21:47:34 +0000107 exception=(&image->exception);
108 switch (depth)
cristy4e82e512011-04-24 01:33:42 +0000109 {
cristy3ed852e2009-09-05 21:47:34 +0000110 case 1: /* Convert bitmap scanline. */
111 {
112 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000113 if (q == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000114 break;
cristybb503372010-05-27 20:51:26 +0000115 for (x=0; x < ((ssize_t) image->columns-7); x+=8)
cristy4e82e512011-04-24 01:33:42 +0000116 {
117 for (bit=0; bit < 8; bit++)
cristy3ed852e2009-09-05 21:47:34 +0000118 {
cristy4c08aed2011-07-01 19:47:50 +0000119 index=(Quantum) ((((*p) & (0x80 >> bit)) != 0) ? 0x01 : 0x00);
120 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000121 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000122 }
cristy4e82e512011-04-24 01:33:42 +0000123 p++;
124 }
cristy3ed852e2009-09-05 21:47:34 +0000125 if ((image->columns % 8) != 0)
126 {
127 for (bit=0; bit < (image->columns % 8); bit++)
128 {
cristy4c08aed2011-07-01 19:47:50 +0000129 index=(Quantum) ((((*p) & (0x80 >> bit)) != 0) ? 0x01 : 0x00);
130 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000131 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000132 }
133 p++;
134 }
135 if (SyncAuthenticPixels(image,exception) == MagickFalse)
136 break;
cristy3ed852e2009-09-05 21:47:34 +0000137 break;
138 }
139 case 2: /* Convert PseudoColor scanline. */
140 {
141 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000142 if (q == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000143 break;
cristybb503372010-05-27 20:51:26 +0000144 for (x=0; x < ((ssize_t) image->columns-1); x+=2)
cristy4c08aed2011-07-01 19:47:50 +0000145 {
146 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3);
147 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000148 q+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +0000149 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3);
150 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000151 q+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +0000152 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3);
153 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000154 q+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +0000155 index=ConstrainColormapIndex(image,(*p) & 0x3);
156 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000157 q+=GetPixelChannels(image);
cristy4c08aed2011-07-01 19:47:50 +0000158 p++;
159 }
cristy3ed852e2009-09-05 21:47:34 +0000160 if ((image->columns % 4) != 0)
161 {
162 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3);
cristy4c08aed2011-07-01 19:47:50 +0000163 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000164 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000165 if ((image->columns % 4) >= 1)
166
167 {
168 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3);
cristy4c08aed2011-07-01 19:47:50 +0000169 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000170 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000171 if ((image->columns % 4) >= 2)
172
173 {
174 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3);
cristy4c08aed2011-07-01 19:47:50 +0000175 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000176 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000177 }
178 }
179 p++;
180 }
181 if (SyncAuthenticPixels(image,exception) == MagickFalse)
182 break;
cristy3ed852e2009-09-05 21:47:34 +0000183 break;
184 }
185
186 case 4: /* Convert PseudoColor scanline. */
187 {
188 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000189 if (q == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000190 break;
cristybb503372010-05-27 20:51:26 +0000191 for (x=0; x < ((ssize_t) image->columns-1); x+=2)
cristy4c08aed2011-07-01 19:47:50 +0000192 {
cristy3ed852e2009-09-05 21:47:34 +0000193 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf);
cristy4c08aed2011-07-01 19:47:50 +0000194 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000195 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000196 index=ConstrainColormapIndex(image,(*p) & 0xf);
cristy4c08aed2011-07-01 19:47:50 +0000197 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000198 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000199 p++;
200 }
201 if ((image->columns % 2) != 0)
202 {
203 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf);
cristy4c08aed2011-07-01 19:47:50 +0000204 SetPixelIndex(image,index,q);
cristyed231572011-07-14 02:18:59 +0000205 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000206 p++;
207 }
208 if (SyncAuthenticPixels(image,exception) == MagickFalse)
209 break;
cristy3ed852e2009-09-05 21:47:34 +0000210 break;
211 }
212 case 8: /* Convert PseudoColor scanline. */
213 {
214 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000215 if (q == (const Quantum *) NULL) break;
cristybb503372010-05-27 20:51:26 +0000216 for (x=0; x < (ssize_t) image->columns; x++)
cristy4e82e512011-04-24 01:33:42 +0000217 {
218 index=ConstrainColormapIndex(image,*p);
cristy4c08aed2011-07-01 19:47:50 +0000219 SetPixelIndex(image,index,q);
cristy4e82e512011-04-24 01:33:42 +0000220 p++;
cristyed231572011-07-14 02:18:59 +0000221 q+=GetPixelChannels(image);
cristy4e82e512011-04-24 01:33:42 +0000222 }
cristy3ed852e2009-09-05 21:47:34 +0000223 if (SyncAuthenticPixels(image,exception) == MagickFalse)
224 break;
cristy3ed852e2009-09-05 21:47:34 +0000225 }
226 break;
227
228 }
229}
230
231/*
232 Compute the number of colors in Grayed R[i]=G[i]=B[i] image
233*/
234static int GetCutColors(Image *image)
235{
236 ExceptionInfo
237 *exception;
238
cristy3ed852e2009-09-05 21:47:34 +0000239 Quantum
240 intensity,
241 scale_intensity;
242
cristy4c08aed2011-07-01 19:47:50 +0000243 register Quantum
cristy4e82e512011-04-24 01:33:42 +0000244 *q;
245
246 ssize_t
247 x,
248 y;
249
cristy3ed852e2009-09-05 21:47:34 +0000250 exception=(&image->exception);
251 intensity=0;
252 scale_intensity=ScaleCharToQuantum(16);
cristybb503372010-05-27 20:51:26 +0000253 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000254 {
255 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
cristybb503372010-05-27 20:51:26 +0000256 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000257 {
cristy4c08aed2011-07-01 19:47:50 +0000258 if (intensity < GetPixelRed(image,q))
259 intensity=GetPixelRed(image,q);
cristy3ed852e2009-09-05 21:47:34 +0000260 if (intensity >= scale_intensity)
261 return(255);
cristyed231572011-07-14 02:18:59 +0000262 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000263 }
264 }
265 if (intensity < ScaleCharToQuantum(2))
266 return(2);
267 if (intensity < ScaleCharToQuantum(16))
268 return(16);
269 return((int) intensity);
270}
271
272/*
273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274% %
275% %
276% %
277% R e a d C U T I m a g e %
278% %
279% %
280% %
281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282%
283% ReadCUTImage() reads an CUT X image file and returns it. It
284% allocates the memory necessary for the new Image structure and returns a
285% pointer to the new image.
286%
287% The format of the ReadCUTImage method is:
288%
289% Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
290%
291% A description of each parameter follows:
292%
293% o image_info: the image info.
294%
295% o exception: return any errors or warnings in this structure.
296%
297*/
298static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
299{
300 Image *image,*palette;
301 ImageInfo *clone_info;
302 MagickBooleanType status;
303
304 MagickOffsetType
305 offset;
306
cristybb503372010-05-27 20:51:26 +0000307 size_t EncodedByte;
cristy3ed852e2009-09-05 21:47:34 +0000308 unsigned char RunCount,RunValue,RunCountMasked;
309 CUTHeader Header;
310 CUTPalHeader PalHeader;
cristybb503372010-05-27 20:51:26 +0000311 ssize_t depth;
312 ssize_t i,j;
313 ssize_t ldblk;
cristy3ed852e2009-09-05 21:47:34 +0000314 unsigned char *BImgBuff=NULL,*ptrB;
cristy4c08aed2011-07-01 19:47:50 +0000315 register Quantum *q;
cristy3ed852e2009-09-05 21:47:34 +0000316
cristy3ed852e2009-09-05 21:47:34 +0000317 /*
318 Open image file.
319 */
320 assert(image_info != (const ImageInfo *) NULL);
321 assert(image_info->signature == MagickSignature);
322 if (image_info->debug != MagickFalse)
323 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
324 image_info->filename);
325 assert(exception != (ExceptionInfo *) NULL);
326 assert(exception->signature == MagickSignature);
327 image=AcquireImage(image_info);
328 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
329 if (status == MagickFalse)
330 {
331 image=DestroyImageList(image);
332 return((Image *) NULL);
333 }
334 /*
335 Read CUT image.
336 */
337 palette=NULL;
338 clone_info=NULL;
339 Header.Width=ReadBlobLSBShort(image);
340 Header.Height=ReadBlobLSBShort(image);
341 Header.Reserved=ReadBlobLSBShort(image);
342
343 if (Header.Width==0 || Header.Height==0 || Header.Reserved!=0)
344 CUT_KO: ThrowReaderException(CorruptImageError,"ImproperImageHeader");
345
346 /*---This code checks first line of image---*/
347 EncodedByte=ReadBlobLSBShort(image);
348 RunCount=(unsigned char) ReadBlobByte(image);
349 RunCountMasked=RunCount & 0x7F;
350 ldblk=0;
351 while((int) RunCountMasked!=0) /*end of line?*/
352 {
353 i=1;
cristybb503372010-05-27 20:51:26 +0000354 if((int) RunCount<0x80) i=(ssize_t) RunCountMasked;
cristy3ed852e2009-09-05 21:47:34 +0000355 offset=SeekBlob(image,TellBlob(image)+i,SEEK_SET);
356 if (offset < 0)
357 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
358 if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data*/
359 EncodedByte-=i+1;
cristybb503372010-05-27 20:51:26 +0000360 ldblk+=(ssize_t) RunCountMasked;
cristy3ed852e2009-09-05 21:47:34 +0000361
362 RunCount=(unsigned char) ReadBlobByte(image);
363 if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data: unexpected eof in line*/
364 RunCountMasked=RunCount & 0x7F;
365 }
366 if(EncodedByte!=1) goto CUT_KO; /*wrong data: size incorrect*/
367 i=0; /*guess a number of bit planes*/
368 if(ldblk==(int) Header.Width) i=8;
369 if(2*ldblk==(int) Header.Width) i=4;
370 if(8*ldblk==(int) Header.Width) i=1;
371 if(i==0) goto CUT_KO; /*wrong data: incorrect bit planes*/
372 depth=i;
373
374 image->columns=Header.Width;
375 image->rows=Header.Height;
376 image->depth=8;
cristybb503372010-05-27 20:51:26 +0000377 image->colors=(size_t) (GetQuantumRange(1UL*i)+1);
cristy3ed852e2009-09-05 21:47:34 +0000378
379 if (image_info->ping) goto Finish;
380
381 /* ----- Do something with palette ----- */
382 if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette;
383
384
cristybb503372010-05-27 20:51:26 +0000385 i=(ssize_t) strlen(clone_info->filename);
cristy3ed852e2009-09-05 21:47:34 +0000386 j=i;
387 while(--i>0)
388 {
389 if(clone_info->filename[i]=='.')
390 {
391 break;
392 }
393 if(clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' ||
394 clone_info->filename[i]==':' )
395 {
396 i=j;
397 break;
398 }
399 }
400
401 (void) CopyMagickString(clone_info->filename+i,".PAL",(size_t)
402 (MaxTextExtent-i));
403 if((clone_info->file=OpenMagickStream(clone_info->filename,"rb"))==NULL)
404 {
405 (void) CopyMagickString(clone_info->filename+i,".pal",(size_t)
406 (MaxTextExtent-i));
407 if((clone_info->file=OpenMagickStream(clone_info->filename,"rb"))==NULL)
408 {
409 clone_info->filename[i]='\0';
410 if((clone_info->file=OpenMagickStream(clone_info->filename,"rb"))==NULL)
411 {
412 clone_info=DestroyImageInfo(clone_info);
413 clone_info=NULL;
414 goto NoPalette;
415 }
416 }
417 }
418
419 if( (palette=AcquireImage(clone_info))==NULL ) goto NoPalette;
420 status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception);
421 if (status == MagickFalse)
422 {
423 ErasePalette:
424 palette=DestroyImage(palette);
425 palette=NULL;
426 goto NoPalette;
427 }
428
429
430 if(palette!=NULL)
431 {
cristyda16f162011-02-19 23:52:17 +0000432 (void) ReadBlob(palette,2,(unsigned char *) PalHeader.FileId);
cristy3ed852e2009-09-05 21:47:34 +0000433 if(strncmp(PalHeader.FileId,"AH",2) != 0) goto ErasePalette;
434 PalHeader.Version=ReadBlobLSBShort(palette);
435 PalHeader.Size=ReadBlobLSBShort(palette);
436 PalHeader.FileType=(char) ReadBlobByte(palette);
437 PalHeader.SubType=(char) ReadBlobByte(palette);
438 PalHeader.BoardID=ReadBlobLSBShort(palette);
439 PalHeader.GraphicsMode=ReadBlobLSBShort(palette);
440 PalHeader.MaxIndex=ReadBlobLSBShort(palette);
441 PalHeader.MaxRed=ReadBlobLSBShort(palette);
442 PalHeader.MaxGreen=ReadBlobLSBShort(palette);
443 PalHeader.MaxBlue=ReadBlobLSBShort(palette);
cristyda16f162011-02-19 23:52:17 +0000444 (void) ReadBlob(palette,20,(unsigned char *) PalHeader.PaletteId);
cristy3ed852e2009-09-05 21:47:34 +0000445
446 if(PalHeader.MaxIndex<1) goto ErasePalette;
447 image->colors=PalHeader.MaxIndex+1;
448 if (AcquireImageColormap(image,image->colors) == MagickFalse) goto NoMemory;
449
450 if(PalHeader.MaxRed==0) PalHeader.MaxRed=(unsigned int) QuantumRange; /*avoid division by 0*/
451 if(PalHeader.MaxGreen==0) PalHeader.MaxGreen=(unsigned int) QuantumRange;
452 if(PalHeader.MaxBlue==0) PalHeader.MaxBlue=(unsigned int) QuantumRange;
453
454 for(i=0;i<=(int) PalHeader.MaxIndex;i++)
455 { /*this may be wrong- I don't know why is palette such strange*/
cristybb503372010-05-27 20:51:26 +0000456 j=(ssize_t) TellBlob(palette);
cristy3ed852e2009-09-05 21:47:34 +0000457 if((j % 512)>512-6)
458 {
459 j=((j / 512)+1)*512;
460 offset=SeekBlob(palette,j,SEEK_SET);
461 if (offset < 0)
462 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
463 }
464 image->colormap[i].red=(Quantum) ReadBlobLSBShort(palette);
cristy4f3c0be2009-09-12 16:04:05 +0000465 if (QuantumRange != (Quantum) PalHeader.MaxRed)
cristy3ed852e2009-09-05 21:47:34 +0000466 {
cristyce70c172010-01-07 17:15:30 +0000467 image->colormap[i].red=ClampToQuantum(((double)
cristy3ed852e2009-09-05 21:47:34 +0000468 image->colormap[i].red*QuantumRange+(PalHeader.MaxRed>>1))/
469 PalHeader.MaxRed);
470 }
471 image->colormap[i].green=(Quantum) ReadBlobLSBShort(palette);
cristy4f3c0be2009-09-12 16:04:05 +0000472 if (QuantumRange != (Quantum) PalHeader.MaxGreen)
cristy3ed852e2009-09-05 21:47:34 +0000473 {
cristyce70c172010-01-07 17:15:30 +0000474 image->colormap[i].green=ClampToQuantum
cristy3ed852e2009-09-05 21:47:34 +0000475 (((double) image->colormap[i].green*QuantumRange+(PalHeader.MaxGreen>>1))/PalHeader.MaxGreen);
476 }
477 image->colormap[i].blue=(Quantum) ReadBlobLSBShort(palette);
cristy4f3c0be2009-09-12 16:04:05 +0000478 if (QuantumRange != (Quantum) PalHeader.MaxBlue)
cristy3ed852e2009-09-05 21:47:34 +0000479 {
cristyce70c172010-01-07 17:15:30 +0000480 image->colormap[i].blue=ClampToQuantum
cristy3ed852e2009-09-05 21:47:34 +0000481 (((double)image->colormap[i].blue*QuantumRange+(PalHeader.MaxBlue>>1))/PalHeader.MaxBlue);
482 }
483
484 }
485 }
486
487
488
489 NoPalette:
490 if(palette==NULL)
491 {
492
493 image->colors=256;
494 if (AcquireImageColormap(image,image->colors) == MagickFalse)
495 {
496 NoMemory:
497 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
498 }
499
cristybb503372010-05-27 20:51:26 +0000500 for (i=0; i < (ssize_t)image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000501 {
502 image->colormap[i].red=ScaleCharToQuantum((unsigned char) i);
503 image->colormap[i].green=ScaleCharToQuantum((unsigned char) i);
504 image->colormap[i].blue=ScaleCharToQuantum((unsigned char) i);
505 }
506 }
507
508
509 /* ----- Load RLE compressed raster ----- */
510 BImgBuff=(unsigned char *) AcquireQuantumMemory((size_t) ldblk,
511 sizeof(*BImgBuff)); /*Ldblk was set in the check phase*/
512 if(BImgBuff==NULL) goto NoMemory;
513
514 offset=SeekBlob(image,6 /*sizeof(Header)*/,SEEK_SET);
515 if (offset < 0)
516 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
517 for (i=0; i < (int) Header.Height; i++)
518 {
519 EncodedByte=ReadBlobLSBShort(image);
520
521 ptrB=BImgBuff;
522 j=ldblk;
523
524 RunCount=(unsigned char) ReadBlobByte(image);
525 RunCountMasked=RunCount & 0x7F;
526
cristy4e82e512011-04-24 01:33:42 +0000527 while ((int) RunCountMasked != 0)
528 {
cristybb503372010-05-27 20:51:26 +0000529 if((ssize_t) RunCountMasked>j)
cristy3ed852e2009-09-05 21:47:34 +0000530 { /*Wrong Data*/
531 RunCountMasked=(unsigned char) j;
532 if(j==0)
533 {
534 break;
535 }
536 }
537
538 if((int) RunCount>0x80)
539 {
540 RunValue=(unsigned char) ReadBlobByte(image);
541 (void) ResetMagickMemory(ptrB,(int) RunValue,(size_t) RunCountMasked);
542 }
543 else {
cristyda16f162011-02-19 23:52:17 +0000544 (void) ReadBlob(image,(size_t) RunCountMasked,ptrB);
cristy3ed852e2009-09-05 21:47:34 +0000545 }
546
547 ptrB+=(int) RunCountMasked;
548 j-=(int) RunCountMasked;
549
550 if (EOFBlob(image) != MagickFalse) goto Finish; /* wrong data: unexpected eof in line */
551 RunCount=(unsigned char) ReadBlobByte(image);
552 RunCountMasked=RunCount & 0x7F;
553 }
554
555 InsertRow(depth,BImgBuff,i,image);
556 }
cristy4e82e512011-04-24 01:33:42 +0000557 (void) SyncImage(image);
cristy3ed852e2009-09-05 21:47:34 +0000558
559
560 /*detect monochrome image*/
561
562 if(palette==NULL)
563 { /*attempt to detect binary (black&white) images*/
564 if ((image->storage_class == PseudoClass) &&
cristy4c08aed2011-07-01 19:47:50 +0000565 (IsImageGray(image,&image->exception) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +0000566 {
567 if(GetCutColors(image)==2)
568 {
cristybb503372010-05-27 20:51:26 +0000569 for (i=0; i < (ssize_t)image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000570 {
571 register Quantum
572 sample;
573 sample=ScaleCharToQuantum((unsigned char) i);
574 if(image->colormap[i].red!=sample) goto Finish;
575 if(image->colormap[i].green!=sample) goto Finish;
576 if(image->colormap[i].blue!=sample) goto Finish;
577 }
578
cristy9fff7b42011-04-29 01:09:31 +0000579 image->colormap[1].red=image->colormap[1].green=
580 image->colormap[1].blue=(Quantum) QuantumRange;
cristybb503372010-05-27 20:51:26 +0000581 for (i=0; i < (ssize_t)image->rows; i++)
cristy3ed852e2009-09-05 21:47:34 +0000582 {
583 q=QueueAuthenticPixels(image,0,i,image->columns,1,exception);
cristybb503372010-05-27 20:51:26 +0000584 for (j=0; j < (ssize_t)image->columns; j++)
cristy3ed852e2009-09-05 21:47:34 +0000585 {
cristy4c08aed2011-07-01 19:47:50 +0000586 if (GetPixelRed(image,q) == ScaleCharToQuantum(1))
cristy3ed852e2009-09-05 21:47:34 +0000587 {
cristy4c08aed2011-07-01 19:47:50 +0000588 SetPixelRed(image,QuantumRange,q);
589 SetPixelGreen(image,QuantumRange,q);
590 SetPixelBlue(image,QuantumRange,q);
cristy3ed852e2009-09-05 21:47:34 +0000591 }
cristyed231572011-07-14 02:18:59 +0000592 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000593 }
594 if (SyncAuthenticPixels(image,exception) == MagickFalse) goto Finish;
595 }
596 }
597 }
598 }
599
600 Finish:
601 if (BImgBuff != NULL)
602 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
603 if (palette != NULL)
604 palette=DestroyImage(palette);
605 if (clone_info != NULL)
606 clone_info=DestroyImageInfo(clone_info);
607 if (EOFBlob(image) != MagickFalse)
608 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
609 image->filename);
610 (void) CloseBlob(image);
611 return(GetFirstImageInList(image));
612}
613
614/*
615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616% %
617% %
618% %
619% R e g i s t e r C U T I m a g e %
620% %
621% %
622% %
623%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
624%
625% RegisterCUTImage() adds attributes for the CUT image format to
626% the list of supported formats. The attributes include the image format
627% tag, a method to read and/or write the format, whether the format
628% supports the saving of more than one frame to the same file or blob,
629% whether the format supports native in-memory I/O, and a brief
630% description of the format.
631%
632% The format of the RegisterCUTImage method is:
633%
cristybb503372010-05-27 20:51:26 +0000634% size_t RegisterCUTImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000635%
636*/
cristybb503372010-05-27 20:51:26 +0000637ModuleExport size_t RegisterCUTImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000638{
639 MagickInfo
640 *entry;
641
642 entry=SetMagickInfo("CUT");
643 entry->decoder=(DecodeImageHandler *) ReadCUTImage;
644 entry->seekable_stream=MagickTrue;
645 entry->description=ConstantString("DR Halo");
646 entry->module=ConstantString("CUT");
647 (void) RegisterMagickInfo(entry);
648 return(MagickImageCoderSignature);
649}
650
651/*
652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
653% %
654% %
655% %
656% U n r e g i s t e r C U T I m a g e %
657% %
658% %
659% %
660%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
661%
662% UnregisterCUTImage() removes format registrations made by the
663% CUT module from the list of supported formats.
664%
665% The format of the UnregisterCUTImage method is:
666%
667% UnregisterCUTImage(void)
668%
669*/
670ModuleExport void UnregisterCUTImage(void)
671{
672 (void) UnregisterMagickInfo("CUT");
673}