blob: a5358a5e23eacf0a1f101edb488e375ce823e749 [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*/
50#include "magick/studio.h"
51#include "magick/blob.h"
52#include "magick/blob-private.h"
53#include "magick/cache.h"
54#include "magick/color.h"
55#include "magick/color-private.h"
cristye7e40552010-04-24 21:34:22 +000056#include "magick/colormap.h"
57#include "magick/colormap-private.h"
cristy3ed852e2009-09-05 21:47:34 +000058#include "magick/exception.h"
59#include "magick/exception-private.h"
60#include "magick/image.h"
61#include "magick/image-private.h"
62#include "magick/list.h"
63#include "magick/magick.h"
64#include "magick/memory_.h"
65#include "magick/quantum-private.h"
66#include "magick/static.h"
67#include "magick/string_.h"
68#include "magick/module.h"
69#include "magick/utility.h"
70
71typedef struct
72{
73 unsigned Width;
74 unsigned Height;
75 unsigned Reserved;
76} CUTHeader;
77
78typedef struct
79{
80 char FileId[2];
81 unsigned Version;
82 unsigned Size;
83 char FileType;
84 char SubType;
85 unsigned BoardID;
86 unsigned GraphicsMode;
87 unsigned MaxIndex;
88 unsigned MaxRed;
89 unsigned MaxGreen;
90 unsigned MaxBlue;
91 char PaletteId[20];
92} CUTPalHeader;
93
94
cristybb503372010-05-27 20:51:26 +000095static void InsertRow(ssize_t depth,unsigned char *p,ssize_t y,Image *image)
cristy3ed852e2009-09-05 21:47:34 +000096{
97 ExceptionInfo
98 *exception;
99
cristybb503372010-05-27 20:51:26 +0000100 size_t bit; ssize_t x;
cristy3ed852e2009-09-05 21:47:34 +0000101 register PixelPacket *q;
102 IndexPacket index;
103 register IndexPacket *indexes;
104
105
106 index=(IndexPacket) 0;
107 exception=(&image->exception);
108 switch (depth)
109 {
110 case 1: /* Convert bitmap scanline. */
111 {
112 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
113 if (q == (PixelPacket *) NULL)
114 break;
115 indexes=GetAuthenticIndexQueue(image);
cristybb503372010-05-27 20:51:26 +0000116 for (x=0; x < ((ssize_t) image->columns-7); x+=8)
cristy3ed852e2009-09-05 21:47:34 +0000117 {
118 for (bit=0; bit < 8; bit++)
119 {
120 index=(IndexPacket) ((((*p) & (0x80 >> bit)) != 0) ? 0x01 : 0x00);
121 indexes[x+bit]=index;
cristybb503372010-05-27 20:51:26 +0000122 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000123 }
124 p++;
125 }
126 if ((image->columns % 8) != 0)
127 {
128 for (bit=0; bit < (image->columns % 8); bit++)
129 {
130 index=(IndexPacket) ((((*p) & (0x80 >> bit)) != 0) ? 0x01 : 0x00);
131 indexes[x+bit]=index;
cristybb503372010-05-27 20:51:26 +0000132 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000133 }
134 p++;
135 }
136 if (SyncAuthenticPixels(image,exception) == MagickFalse)
137 break;
cristy3ed852e2009-09-05 21:47:34 +0000138 break;
139 }
140 case 2: /* Convert PseudoColor scanline. */
141 {
142 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
143 if (q == (PixelPacket *) NULL)
144 break;
145 indexes=GetAuthenticIndexQueue(image);
cristybb503372010-05-27 20:51:26 +0000146 for (x=0; x < ((ssize_t) image->columns-1); x+=2)
cristy3ed852e2009-09-05 21:47:34 +0000147 {
148 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3);
149 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +0000150 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000151 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3);
152 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +0000153 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000154 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3);
155 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +0000156 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000157 index=ConstrainColormapIndex(image,(*p) & 0x3);
158 indexes[x+1]=index;
cristybb503372010-05-27 20:51:26 +0000159 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000160 p++;
161 }
162 if ((image->columns % 4) != 0)
163 {
164 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3);
165 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +0000166 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000167 if ((image->columns % 4) >= 1)
168
169 {
170 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3);
171 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +0000172 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000173 if ((image->columns % 4) >= 2)
174
175 {
176 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3);
177 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +0000178 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000179 }
180 }
181 p++;
182 }
183 if (SyncAuthenticPixels(image,exception) == MagickFalse)
184 break;
cristy3ed852e2009-09-05 21:47:34 +0000185 break;
186 }
187
188 case 4: /* Convert PseudoColor scanline. */
189 {
190 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
191 if (q == (PixelPacket *) NULL)
192 break;
193 indexes=GetAuthenticIndexQueue(image);
cristybb503372010-05-27 20:51:26 +0000194 for (x=0; x < ((ssize_t) image->columns-1); x+=2)
cristy3ed852e2009-09-05 21:47:34 +0000195 {
196 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf);
197 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +0000198 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000199 index=ConstrainColormapIndex(image,(*p) & 0xf);
200 indexes[x+1]=index;
cristybb503372010-05-27 20:51:26 +0000201 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000202 p++;
203 }
204 if ((image->columns % 2) != 0)
205 {
206 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf);
207 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +0000208 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000209 p++;
210 }
211 if (SyncAuthenticPixels(image,exception) == MagickFalse)
212 break;
cristy3ed852e2009-09-05 21:47:34 +0000213 break;
214 }
215 case 8: /* Convert PseudoColor scanline. */
216 {
217 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
218 if (q == (PixelPacket *) NULL) break;
219 indexes=GetAuthenticIndexQueue(image);
220
cristybb503372010-05-27 20:51:26 +0000221 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000222 {
223 index=ConstrainColormapIndex(image,*p);
224 indexes[x]=index;
cristybb503372010-05-27 20:51:26 +0000225 *q++=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +0000226 p++;
227 }
228 if (SyncAuthenticPixels(image,exception) == MagickFalse)
229 break;
cristy3ed852e2009-09-05 21:47:34 +0000230 }
231 break;
232
233 }
234}
235
236/*
237 Compute the number of colors in Grayed R[i]=G[i]=B[i] image
238*/
239static int GetCutColors(Image *image)
240{
241 ExceptionInfo
242 *exception;
243
cristybb503372010-05-27 20:51:26 +0000244 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000245 x,
246 y;
247
248 PixelPacket
249 *q;
250
251 Quantum
252 intensity,
253 scale_intensity;
254
255 exception=(&image->exception);
256 intensity=0;
257 scale_intensity=ScaleCharToQuantum(16);
cristybb503372010-05-27 20:51:26 +0000258 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000259 {
260 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
cristybb503372010-05-27 20:51:26 +0000261 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000262 {
263 if (intensity < q->red)
264 intensity=q->red;
265 if (intensity >= scale_intensity)
266 return(255);
267 q++;
268 }
269 }
270 if (intensity < ScaleCharToQuantum(2))
271 return(2);
272 if (intensity < ScaleCharToQuantum(16))
273 return(16);
274 return((int) intensity);
275}
276
277/*
278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279% %
280% %
281% %
282% R e a d C U T I m a g e %
283% %
284% %
285% %
286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
287%
288% ReadCUTImage() reads an CUT X image file and returns it. It
289% allocates the memory necessary for the new Image structure and returns a
290% pointer to the new image.
291%
292% The format of the ReadCUTImage method is:
293%
294% Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
295%
296% A description of each parameter follows:
297%
298% o image_info: the image info.
299%
300% o exception: return any errors or warnings in this structure.
301%
302*/
303static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
304{
305 Image *image,*palette;
306 ImageInfo *clone_info;
307 MagickBooleanType status;
308
309 MagickOffsetType
310 offset;
311
cristybb503372010-05-27 20:51:26 +0000312 size_t EncodedByte;
cristy3ed852e2009-09-05 21:47:34 +0000313 unsigned char RunCount,RunValue,RunCountMasked;
314 CUTHeader Header;
315 CUTPalHeader PalHeader;
cristybb503372010-05-27 20:51:26 +0000316 ssize_t depth;
317 ssize_t i,j;
318 ssize_t ldblk;
cristy3ed852e2009-09-05 21:47:34 +0000319 unsigned char *BImgBuff=NULL,*ptrB;
320 PixelPacket *q;
321
322 ssize_t
323 count;
324
325 /*
326 Open image file.
327 */
328 assert(image_info != (const ImageInfo *) NULL);
329 assert(image_info->signature == MagickSignature);
330 if (image_info->debug != MagickFalse)
331 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
332 image_info->filename);
333 assert(exception != (ExceptionInfo *) NULL);
334 assert(exception->signature == MagickSignature);
335 image=AcquireImage(image_info);
336 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
337 if (status == MagickFalse)
338 {
339 image=DestroyImageList(image);
340 return((Image *) NULL);
341 }
342 /*
343 Read CUT image.
344 */
345 palette=NULL;
346 clone_info=NULL;
347 Header.Width=ReadBlobLSBShort(image);
348 Header.Height=ReadBlobLSBShort(image);
349 Header.Reserved=ReadBlobLSBShort(image);
350
351 if (Header.Width==0 || Header.Height==0 || Header.Reserved!=0)
352 CUT_KO: ThrowReaderException(CorruptImageError,"ImproperImageHeader");
353
354 /*---This code checks first line of image---*/
355 EncodedByte=ReadBlobLSBShort(image);
356 RunCount=(unsigned char) ReadBlobByte(image);
357 RunCountMasked=RunCount & 0x7F;
358 ldblk=0;
359 while((int) RunCountMasked!=0) /*end of line?*/
360 {
361 i=1;
cristybb503372010-05-27 20:51:26 +0000362 if((int) RunCount<0x80) i=(ssize_t) RunCountMasked;
cristy3ed852e2009-09-05 21:47:34 +0000363 offset=SeekBlob(image,TellBlob(image)+i,SEEK_SET);
364 if (offset < 0)
365 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
366 if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data*/
367 EncodedByte-=i+1;
cristybb503372010-05-27 20:51:26 +0000368 ldblk+=(ssize_t) RunCountMasked;
cristy3ed852e2009-09-05 21:47:34 +0000369
370 RunCount=(unsigned char) ReadBlobByte(image);
371 if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data: unexpected eof in line*/
372 RunCountMasked=RunCount & 0x7F;
373 }
374 if(EncodedByte!=1) goto CUT_KO; /*wrong data: size incorrect*/
375 i=0; /*guess a number of bit planes*/
376 if(ldblk==(int) Header.Width) i=8;
377 if(2*ldblk==(int) Header.Width) i=4;
378 if(8*ldblk==(int) Header.Width) i=1;
379 if(i==0) goto CUT_KO; /*wrong data: incorrect bit planes*/
380 depth=i;
381
382 image->columns=Header.Width;
383 image->rows=Header.Height;
384 image->depth=8;
cristybb503372010-05-27 20:51:26 +0000385 image->colors=(size_t) (GetQuantumRange(1UL*i)+1);
cristy3ed852e2009-09-05 21:47:34 +0000386
387 if (image_info->ping) goto Finish;
388
389 /* ----- Do something with palette ----- */
390 if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette;
391
392
cristybb503372010-05-27 20:51:26 +0000393 i=(ssize_t) strlen(clone_info->filename);
cristy3ed852e2009-09-05 21:47:34 +0000394 j=i;
395 while(--i>0)
396 {
397 if(clone_info->filename[i]=='.')
398 {
399 break;
400 }
401 if(clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' ||
402 clone_info->filename[i]==':' )
403 {
404 i=j;
405 break;
406 }
407 }
408
409 (void) CopyMagickString(clone_info->filename+i,".PAL",(size_t)
410 (MaxTextExtent-i));
411 if((clone_info->file=OpenMagickStream(clone_info->filename,"rb"))==NULL)
412 {
413 (void) CopyMagickString(clone_info->filename+i,".pal",(size_t)
414 (MaxTextExtent-i));
415 if((clone_info->file=OpenMagickStream(clone_info->filename,"rb"))==NULL)
416 {
417 clone_info->filename[i]='\0';
418 if((clone_info->file=OpenMagickStream(clone_info->filename,"rb"))==NULL)
419 {
420 clone_info=DestroyImageInfo(clone_info);
421 clone_info=NULL;
422 goto NoPalette;
423 }
424 }
425 }
426
427 if( (palette=AcquireImage(clone_info))==NULL ) goto NoPalette;
428 status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception);
429 if (status == MagickFalse)
430 {
431 ErasePalette:
432 palette=DestroyImage(palette);
433 palette=NULL;
434 goto NoPalette;
435 }
436
437
438 if(palette!=NULL)
439 {
440 count=ReadBlob(palette,2,(unsigned char *) PalHeader.FileId);
441 if(strncmp(PalHeader.FileId,"AH",2) != 0) goto ErasePalette;
442 PalHeader.Version=ReadBlobLSBShort(palette);
443 PalHeader.Size=ReadBlobLSBShort(palette);
444 PalHeader.FileType=(char) ReadBlobByte(palette);
445 PalHeader.SubType=(char) ReadBlobByte(palette);
446 PalHeader.BoardID=ReadBlobLSBShort(palette);
447 PalHeader.GraphicsMode=ReadBlobLSBShort(palette);
448 PalHeader.MaxIndex=ReadBlobLSBShort(palette);
449 PalHeader.MaxRed=ReadBlobLSBShort(palette);
450 PalHeader.MaxGreen=ReadBlobLSBShort(palette);
451 PalHeader.MaxBlue=ReadBlobLSBShort(palette);
452 count=ReadBlob(palette,20,(unsigned char *) PalHeader.PaletteId);
453
454 if(PalHeader.MaxIndex<1) goto ErasePalette;
455 image->colors=PalHeader.MaxIndex+1;
456 if (AcquireImageColormap(image,image->colors) == MagickFalse) goto NoMemory;
457
458 if(PalHeader.MaxRed==0) PalHeader.MaxRed=(unsigned int) QuantumRange; /*avoid division by 0*/
459 if(PalHeader.MaxGreen==0) PalHeader.MaxGreen=(unsigned int) QuantumRange;
460 if(PalHeader.MaxBlue==0) PalHeader.MaxBlue=(unsigned int) QuantumRange;
461
462 for(i=0;i<=(int) PalHeader.MaxIndex;i++)
463 { /*this may be wrong- I don't know why is palette such strange*/
cristybb503372010-05-27 20:51:26 +0000464 j=(ssize_t) TellBlob(palette);
cristy3ed852e2009-09-05 21:47:34 +0000465 if((j % 512)>512-6)
466 {
467 j=((j / 512)+1)*512;
468 offset=SeekBlob(palette,j,SEEK_SET);
469 if (offset < 0)
470 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
471 }
472 image->colormap[i].red=(Quantum) ReadBlobLSBShort(palette);
cristy4f3c0be2009-09-12 16:04:05 +0000473 if (QuantumRange != (Quantum) PalHeader.MaxRed)
cristy3ed852e2009-09-05 21:47:34 +0000474 {
cristyce70c172010-01-07 17:15:30 +0000475 image->colormap[i].red=ClampToQuantum(((double)
cristy3ed852e2009-09-05 21:47:34 +0000476 image->colormap[i].red*QuantumRange+(PalHeader.MaxRed>>1))/
477 PalHeader.MaxRed);
478 }
479 image->colormap[i].green=(Quantum) ReadBlobLSBShort(palette);
cristy4f3c0be2009-09-12 16:04:05 +0000480 if (QuantumRange != (Quantum) PalHeader.MaxGreen)
cristy3ed852e2009-09-05 21:47:34 +0000481 {
cristyce70c172010-01-07 17:15:30 +0000482 image->colormap[i].green=ClampToQuantum
cristy3ed852e2009-09-05 21:47:34 +0000483 (((double) image->colormap[i].green*QuantumRange+(PalHeader.MaxGreen>>1))/PalHeader.MaxGreen);
484 }
485 image->colormap[i].blue=(Quantum) ReadBlobLSBShort(palette);
cristy4f3c0be2009-09-12 16:04:05 +0000486 if (QuantumRange != (Quantum) PalHeader.MaxBlue)
cristy3ed852e2009-09-05 21:47:34 +0000487 {
cristyce70c172010-01-07 17:15:30 +0000488 image->colormap[i].blue=ClampToQuantum
cristy3ed852e2009-09-05 21:47:34 +0000489 (((double)image->colormap[i].blue*QuantumRange+(PalHeader.MaxBlue>>1))/PalHeader.MaxBlue);
490 }
491
492 }
493 }
494
495
496
497 NoPalette:
498 if(palette==NULL)
499 {
500
501 image->colors=256;
502 if (AcquireImageColormap(image,image->colors) == MagickFalse)
503 {
504 NoMemory:
505 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
506 }
507
cristybb503372010-05-27 20:51:26 +0000508 for (i=0; i < (ssize_t)image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000509 {
510 image->colormap[i].red=ScaleCharToQuantum((unsigned char) i);
511 image->colormap[i].green=ScaleCharToQuantum((unsigned char) i);
512 image->colormap[i].blue=ScaleCharToQuantum((unsigned char) i);
513 }
514 }
515
516
517 /* ----- Load RLE compressed raster ----- */
518 BImgBuff=(unsigned char *) AcquireQuantumMemory((size_t) ldblk,
519 sizeof(*BImgBuff)); /*Ldblk was set in the check phase*/
520 if(BImgBuff==NULL) goto NoMemory;
521
522 offset=SeekBlob(image,6 /*sizeof(Header)*/,SEEK_SET);
523 if (offset < 0)
524 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
525 for (i=0; i < (int) Header.Height; i++)
526 {
527 EncodedByte=ReadBlobLSBShort(image);
528
529 ptrB=BImgBuff;
530 j=ldblk;
531
532 RunCount=(unsigned char) ReadBlobByte(image);
533 RunCountMasked=RunCount & 0x7F;
534
535 while((int) RunCountMasked!=0)
536 {
cristybb503372010-05-27 20:51:26 +0000537 if((ssize_t) RunCountMasked>j)
cristy3ed852e2009-09-05 21:47:34 +0000538 { /*Wrong Data*/
539 RunCountMasked=(unsigned char) j;
540 if(j==0)
541 {
542 break;
543 }
544 }
545
546 if((int) RunCount>0x80)
547 {
548 RunValue=(unsigned char) ReadBlobByte(image);
549 (void) ResetMagickMemory(ptrB,(int) RunValue,(size_t) RunCountMasked);
550 }
551 else {
552 count=ReadBlob(image,(size_t) RunCountMasked,ptrB);
553 }
554
555 ptrB+=(int) RunCountMasked;
556 j-=(int) RunCountMasked;
557
558 if (EOFBlob(image) != MagickFalse) goto Finish; /* wrong data: unexpected eof in line */
559 RunCount=(unsigned char) ReadBlobByte(image);
560 RunCountMasked=RunCount & 0x7F;
561 }
562
563 InsertRow(depth,BImgBuff,i,image);
564 }
565
566
567 /*detect monochrome image*/
568
569 if(palette==NULL)
570 { /*attempt to detect binary (black&white) images*/
571 if ((image->storage_class == PseudoClass) &&
572 (IsGrayImage(image,&image->exception) != MagickFalse))
573 {
574 if(GetCutColors(image)==2)
575 {
cristybb503372010-05-27 20:51:26 +0000576 for (i=0; i < (ssize_t)image->colors; i++)
cristy3ed852e2009-09-05 21:47:34 +0000577 {
578 register Quantum
579 sample;
580 sample=ScaleCharToQuantum((unsigned char) i);
581 if(image->colormap[i].red!=sample) goto Finish;
582 if(image->colormap[i].green!=sample) goto Finish;
583 if(image->colormap[i].blue!=sample) goto Finish;
584 }
585
586 image->colormap[1].red=image->colormap[1].green=image->colormap[1].blue=(Quantum) QuantumRange;
cristybb503372010-05-27 20:51:26 +0000587 for (i=0; i < (ssize_t)image->rows; i++)
cristy3ed852e2009-09-05 21:47:34 +0000588 {
589 q=QueueAuthenticPixels(image,0,i,image->columns,1,exception);
cristybb503372010-05-27 20:51:26 +0000590 for (j=0; j < (ssize_t)image->columns; j++)
cristy3ed852e2009-09-05 21:47:34 +0000591 {
592 if(q->red==ScaleCharToQuantum(1))
593 {
594 q->red=q->green=q->blue=(Quantum) QuantumRange;
595 }
596 q++;
597 }
598 if (SyncAuthenticPixels(image,exception) == MagickFalse) goto Finish;
599 }
600 }
601 }
602 }
603
604 Finish:
605 if (BImgBuff != NULL)
606 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
607 if (palette != NULL)
608 palette=DestroyImage(palette);
609 if (clone_info != NULL)
610 clone_info=DestroyImageInfo(clone_info);
611 if (EOFBlob(image) != MagickFalse)
612 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
613 image->filename);
614 (void) CloseBlob(image);
615 return(GetFirstImageInList(image));
616}
617
618/*
619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
620% %
621% %
622% %
623% R e g i s t e r C U T I m a g e %
624% %
625% %
626% %
627%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
628%
629% RegisterCUTImage() adds attributes for the CUT image format to
630% the list of supported formats. The attributes include the image format
631% tag, a method to read and/or write the format, whether the format
632% supports the saving of more than one frame to the same file or blob,
633% whether the format supports native in-memory I/O, and a brief
634% description of the format.
635%
636% The format of the RegisterCUTImage method is:
637%
cristybb503372010-05-27 20:51:26 +0000638% size_t RegisterCUTImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000639%
640*/
cristybb503372010-05-27 20:51:26 +0000641ModuleExport size_t RegisterCUTImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000642{
643 MagickInfo
644 *entry;
645
646 entry=SetMagickInfo("CUT");
647 entry->decoder=(DecodeImageHandler *) ReadCUTImage;
648 entry->seekable_stream=MagickTrue;
649 entry->description=ConstantString("DR Halo");
650 entry->module=ConstantString("CUT");
651 (void) RegisterMagickInfo(entry);
652 return(MagickImageCoderSignature);
653}
654
655/*
656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
657% %
658% %
659% %
660% U n r e g i s t e r C U T I m a g e %
661% %
662% %
663% %
664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665%
666% UnregisterCUTImage() removes format registrations made by the
667% CUT module from the list of supported formats.
668%
669% The format of the UnregisterCUTImage method is:
670%
671% UnregisterCUTImage(void)
672%
673*/
674ModuleExport void UnregisterCUTImage(void)
675{
676 (void) UnregisterMagickInfo("CUT");
677}