1 /*
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 "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"
72 #include "MagickCore/utility-private.h"
73
74 typedef struct
75 {
76 unsigned Width;
77 unsigned Height;
78 unsigned Reserved;
79 } CUTHeader;
80
81 typedef 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
InsertRow(Image * image,ssize_t bpp,unsigned char * p,ssize_t y,ExceptionInfo * exception)98 static MagickBooleanType InsertRow(Image *image,ssize_t bpp,unsigned char *p,
99 ssize_t y,ExceptionInfo *exception)
100 {
101 int
102 bit;
103
104 Quantum
105 index;
106
107 register Quantum
108 *q;
109
110 ssize_t
111 x;
112
113 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
114 if (q == (Quantum *) NULL)
115 return(MagickFalse);
116 switch (bpp)
117 {
118 case 1: /* Convert bitmap scanline. */
119 {
120 for (x=0; x < ((ssize_t) image->columns-7); x+=8)
121 {
122 for (bit=0; bit < 8; bit++)
123 {
124 index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
125 SetPixelIndex(image,index,q);
126 if (index < image->colors)
127 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
128 q+=GetPixelChannels(image);
129 }
130 p++;
131 }
132 if ((image->columns % 8) != 0)
133 {
134 for (bit=0; bit < (ssize_t) (image->columns % 8); bit++)
135 {
136 index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
137 SetPixelIndex(image,index,q);
138 if (index < image->colors)
139 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
140 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
141 q+=GetPixelChannels(image);
142 }
143 p++;
144 }
145 break;
146 }
147 case 2: /* Convert PseudoColor scanline. */
148 {
149 for (x=0; x < ((ssize_t) image->columns-3); x+=4)
150 {
151 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
152 SetPixelIndex(image,index,q);
153 if (index < image->colors)
154 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
155 q+=GetPixelChannels(image);
156 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
157 SetPixelIndex(image,index,q);
158 if (index < image->colors)
159 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
160 q+=GetPixelChannels(image);
161 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,exception);
162 SetPixelIndex(image,index,q);
163 if (index < image->colors)
164 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
165 q+=GetPixelChannels(image);
166 index=ConstrainColormapIndex(image,(*p) & 0x3,exception);
167 SetPixelIndex(image,index,q);
168 if (index < image->colors)
169 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
170 q+=GetPixelChannels(image);
171 p++;
172 }
173 if ((image->columns % 4) != 0)
174 {
175 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
176 SetPixelIndex(image,index,q);
177 if (index < image->colors)
178 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
179 q+=GetPixelChannels(image);
180 if ((image->columns % 4) > 1)
181 {
182 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
183 SetPixelIndex(image,index,q);
184 if (index < image->colors)
185 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
186 q+=GetPixelChannels(image);
187 if ((image->columns % 4) > 2)
188 {
189 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,
190 exception);
191 SetPixelIndex(image,index,q);
192 if (index < image->colors)
193 SetPixelViaPixelInfo(image,image->colormap+(ssize_t)
194 index,q);
195 q+=GetPixelChannels(image);
196 }
197 }
198 p++;
199 }
200 break;
201 }
202
203 case 4: /* Convert PseudoColor scanline. */
204 {
205 for (x=0; x < ((ssize_t) image->columns-1); x+=2)
206 {
207 index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
208 SetPixelIndex(image,index,q);
209 if (index < image->colors)
210 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
211 q+=GetPixelChannels(image);
212 index=ConstrainColormapIndex(image,(*p) & 0x0f,exception);
213 SetPixelIndex(image,index,q);
214 if (index < image->colors)
215 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
216 p++;
217 q+=GetPixelChannels(image);
218 }
219 if ((image->columns % 2) != 0)
220 {
221 index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
222 SetPixelIndex(image,index,q);
223 if (index < image->colors)
224 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
225 p++;
226 q+=GetPixelChannels(image);
227 }
228 break;
229 }
230 case 8: /* Convert PseudoColor scanline. */
231 {
232 for (x=0; x < (ssize_t) image->columns; x++)
233 {
234 index=ConstrainColormapIndex(image,*p,exception);
235 SetPixelIndex(image,index,q);
236 if (index < image->colors)
237 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
238 p++;
239 q+=GetPixelChannels(image);
240 }
241 }
242 break;
243
244 case 24: /* Convert DirectColor scanline. */
245 for (x=0; x < (ssize_t) image->columns; x++)
246 {
247 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
248 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
249 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
250 q+=GetPixelChannels(image);
251 }
252 break;
253 }
254 if (!SyncAuthenticPixels(image,exception))
255 return(MagickFalse);
256 return(MagickTrue);
257 }
258
259 /*
260 Compute the number of colors in Grayed R[i]=G[i]=B[i] image
261 */
GetCutColors(Image * image,ExceptionInfo * exception)262 static int GetCutColors(Image *image,ExceptionInfo *exception)
263 {
264 Quantum
265 intensity,
266 scale_intensity;
267
268 register Quantum
269 *q;
270
271 ssize_t
272 x,
273 y;
274
275 intensity=0;
276 scale_intensity=ScaleCharToQuantum(16);
277 for (y=0; y < (ssize_t) image->rows; y++)
278 {
279 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
280 if (q == (Quantum *) NULL)
281 break;
282 for (x=0; x < (ssize_t) image->columns; x++)
283 {
284 if (intensity < GetPixelRed(image,q))
285 intensity=GetPixelRed(image,q);
286 if (intensity >= scale_intensity)
287 return(255);
288 q+=GetPixelChannels(image);
289 }
290 }
291 if (intensity < ScaleCharToQuantum(2))
292 return(2);
293 if (intensity < ScaleCharToQuantum(16))
294 return(16);
295 return((int) intensity);
296 }
297
298 /*
299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300 % %
301 % %
302 % %
303 % R e a d C U T I m a g e %
304 % %
305 % %
306 % %
307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
308 %
309 % ReadCUTImage() reads an CUT X image file and returns it. It
310 % allocates the memory necessary for the new Image structure and returns a
311 % pointer to the new image.
312 %
313 % The format of the ReadCUTImage method is:
314 %
315 % Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
316 %
317 % A description of each parameter follows:
318 %
319 % o image_info: the image info.
320 %
321 % o exception: return any errors or warnings in this structure.
322 %
323 */
ReadCUTImage(const ImageInfo * image_info,ExceptionInfo * exception)324 static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
325 {
326 #define ThrowCUTReaderException(severity,tag) \
327 { \
328 if (palette != NULL) \
329 palette=DestroyImage(palette); \
330 if (clone_info != NULL) \
331 clone_info=DestroyImageInfo(clone_info); \
332 ThrowReaderException(severity,tag); \
333 }
334
335 Image *image,*palette;
336 ImageInfo *clone_info;
337 MagickBooleanType status;
338
339 MagickOffsetType
340 offset;
341
342 size_t EncodedByte;
343 unsigned char RunCount,RunValue,RunCountMasked;
344 CUTHeader Header;
345 CUTPalHeader PalHeader;
346 ssize_t depth;
347 ssize_t i,j;
348 ssize_t ldblk;
349 unsigned char *BImgBuff=NULL,*ptrB;
350 register Quantum *q;
351
352 /*
353 Open image file.
354 */
355 assert(image_info != (const ImageInfo *) NULL);
356 assert(image_info->signature == MagickCoreSignature);
357 if (image_info->debug != MagickFalse)
358 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
359 image_info->filename);
360 assert(exception != (ExceptionInfo *) NULL);
361 assert(exception->signature == MagickCoreSignature);
362 image=AcquireImage(image_info,exception);
363 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
364 if (status == MagickFalse)
365 {
366 image=DestroyImageList(image);
367 return((Image *) NULL);
368 }
369 /*
370 Read CUT image.
371 */
372 palette=NULL;
373 clone_info=NULL;
374 Header.Width=ReadBlobLSBShort(image);
375 Header.Height=ReadBlobLSBShort(image);
376 Header.Reserved=ReadBlobLSBShort(image);
377
378 if (Header.Width==0 || Header.Height==0 || Header.Reserved!=0)
379 CUT_KO: ThrowCUTReaderException(CorruptImageError,"ImproperImageHeader");
380
381 /*---This code checks first line of image---*/
382 EncodedByte=ReadBlobLSBShort(image);
383 RunCount=(unsigned char) ReadBlobByte(image);
384 RunCountMasked=RunCount & 0x7F;
385 ldblk=0;
386 while((int) RunCountMasked!=0) /*end of line?*/
387 {
388 i=1;
389 if((int) RunCount<0x80) i=(ssize_t) RunCountMasked;
390 offset=SeekBlob(image,TellBlob(image)+i,SEEK_SET);
391 if (offset < 0)
392 ThrowCUTReaderException(CorruptImageError,"ImproperImageHeader");
393 if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data*/
394 EncodedByte-=i+1;
395 ldblk+=(ssize_t) RunCountMasked;
396
397 RunCount=(unsigned char) ReadBlobByte(image);
398 if(EOFBlob(image) != MagickFalse) goto CUT_KO; /*wrong data: unexpected eof in line*/
399 RunCountMasked=RunCount & 0x7F;
400 }
401 if(EncodedByte!=1) goto CUT_KO; /*wrong data: size incorrect*/
402 i=0; /*guess a number of bit planes*/
403 if(ldblk==(int) Header.Width) i=8;
404 if(2*ldblk==(int) Header.Width) i=4;
405 if(8*ldblk==(int) Header.Width) i=1;
406 if(i==0) goto CUT_KO; /*wrong data: incorrect bit planes*/
407 depth=i;
408
409 image->columns=Header.Width;
410 image->rows=Header.Height;
411 image->depth=8;
412 image->colors=(size_t) (GetQuantumRange(1UL*i)+1);
413
414 if (image_info->ping != MagickFalse) goto Finish;
415 status=SetImageExtent(image,image->columns,image->rows,exception);
416 if (status == MagickFalse)
417 return(DestroyImageList(image));
418
419 /* ----- Do something with palette ----- */
420 if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette;
421
422
423 i=(ssize_t) strlen(clone_info->filename);
424 j=i;
425 while(--i>0)
426 {
427 if(clone_info->filename[i]=='.')
428 {
429 break;
430 }
431 if(clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' ||
432 clone_info->filename[i]==':' )
433 {
434 i=j;
435 break;
436 }
437 }
438
439 (void) CopyMagickString(clone_info->filename+i,".PAL",(size_t)
440 (MagickPathExtent-i));
441 if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL)
442 {
443 (void) CopyMagickString(clone_info->filename+i,".pal",(size_t)
444 (MagickPathExtent-i));
445 if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL)
446 {
447 clone_info->filename[i]='\0';
448 if((clone_info->file=fopen_utf8(clone_info->filename,"rb"))==NULL)
449 {
450 clone_info=DestroyImageInfo(clone_info);
451 clone_info=NULL;
452 goto NoPalette;
453 }
454 }
455 }
456
457 if( (palette=AcquireImage(clone_info,exception))==NULL ) goto NoPalette;
458 status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception);
459 if (status == MagickFalse)
460 {
461 ErasePalette:
462 palette=DestroyImage(palette);
463 palette=NULL;
464 goto NoPalette;
465 }
466
467
468 if(palette!=NULL)
469 {
470 (void) ReadBlob(palette,2,(unsigned char *) PalHeader.FileId);
471 if(strncmp(PalHeader.FileId,"AH",2) != 0) goto ErasePalette;
472 PalHeader.Version=ReadBlobLSBShort(palette);
473 PalHeader.Size=ReadBlobLSBShort(palette);
474 PalHeader.FileType=(char) ReadBlobByte(palette);
475 PalHeader.SubType=(char) ReadBlobByte(palette);
476 PalHeader.BoardID=ReadBlobLSBShort(palette);
477 PalHeader.GraphicsMode=ReadBlobLSBShort(palette);
478 PalHeader.MaxIndex=ReadBlobLSBShort(palette);
479 PalHeader.MaxRed=ReadBlobLSBShort(palette);
480 PalHeader.MaxGreen=ReadBlobLSBShort(palette);
481 PalHeader.MaxBlue=ReadBlobLSBShort(palette);
482 (void) ReadBlob(palette,20,(unsigned char *) PalHeader.PaletteId);
483 if (EOFBlob(image))
484 ThrowCUTReaderException(CorruptImageError,"UnexpectedEndOfFile");
485
486 if(PalHeader.MaxIndex<1) goto ErasePalette;
487 image->colors=PalHeader.MaxIndex+1;
488 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) goto NoMemory;
489
490 if(PalHeader.MaxRed==0) PalHeader.MaxRed=(unsigned int) QuantumRange; /*avoid division by 0*/
491 if(PalHeader.MaxGreen==0) PalHeader.MaxGreen=(unsigned int) QuantumRange;
492 if(PalHeader.MaxBlue==0) PalHeader.MaxBlue=(unsigned int) QuantumRange;
493
494 for(i=0;i<=(int) PalHeader.MaxIndex;i++)
495 { /*this may be wrong- I don't know why is palette such strange*/
496 j=(ssize_t) TellBlob(palette);
497 if((j % 512)>512-6)
498 {
499 j=((j / 512)+1)*512;
500 offset=SeekBlob(palette,j,SEEK_SET);
501 if (offset < 0)
502 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
503 }
504 image->colormap[i].red=(Quantum) ReadBlobLSBShort(palette);
505 if (QuantumRange != (Quantum) PalHeader.MaxRed)
506 {
507 image->colormap[i].red=ClampToQuantum(((double)
508 image->colormap[i].red*QuantumRange+(PalHeader.MaxRed>>1))/
509 PalHeader.MaxRed);
510 }
511 image->colormap[i].green=(Quantum) ReadBlobLSBShort(palette);
512 if (QuantumRange != (Quantum) PalHeader.MaxGreen)
513 {
514 image->colormap[i].green=ClampToQuantum
515 (((double) image->colormap[i].green*QuantumRange+(PalHeader.MaxGreen>>1))/PalHeader.MaxGreen);
516 }
517 image->colormap[i].blue=(Quantum) ReadBlobLSBShort(palette);
518 if (QuantumRange != (Quantum) PalHeader.MaxBlue)
519 {
520 image->colormap[i].blue=ClampToQuantum
521 (((double)image->colormap[i].blue*QuantumRange+(PalHeader.MaxBlue>>1))/PalHeader.MaxBlue);
522 }
523
524 }
525 if (EOFBlob(image))
526 ThrowCUTReaderException(CorruptImageError,"UnexpectedEndOfFile");
527 }
528
529
530
531 NoPalette:
532 if(palette==NULL)
533 {
534
535 image->colors=256;
536 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
537 {
538 NoMemory:
539 ThrowCUTReaderException(ResourceLimitError,"MemoryAllocationFailed");
540 }
541
542 for (i=0; i < (ssize_t)image->colors; i++)
543 {
544 image->colormap[i].red=ScaleCharToQuantum((unsigned char) i);
545 image->colormap[i].green=ScaleCharToQuantum((unsigned char) i);
546 image->colormap[i].blue=ScaleCharToQuantum((unsigned char) i);
547 }
548 }
549
550
551 /* ----- Load RLE compressed raster ----- */
552 BImgBuff=(unsigned char *) AcquireQuantumMemory((size_t) ldblk,
553 sizeof(*BImgBuff)); /*Ldblk was set in the check phase*/
554 if(BImgBuff==NULL) goto NoMemory;
555
556 offset=SeekBlob(image,6 /*sizeof(Header)*/,SEEK_SET);
557 if (offset < 0)
558 {
559 if (palette != NULL)
560 palette=DestroyImage(palette);
561 if (clone_info != NULL)
562 clone_info=DestroyImageInfo(clone_info);
563 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
564 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
565 }
566 for (i=0; i < (int) Header.Height; i++)
567 {
568 EncodedByte=ReadBlobLSBShort(image);
569
570 ptrB=BImgBuff;
571 j=ldblk;
572
573 RunCount=(unsigned char) ReadBlobByte(image);
574 RunCountMasked=RunCount & 0x7F;
575
576 while ((int) RunCountMasked != 0)
577 {
578 if((ssize_t) RunCountMasked>j)
579 { /*Wrong Data*/
580 RunCountMasked=(unsigned char) j;
581 if(j==0)
582 {
583 break;
584 }
585 }
586
587 if((int) RunCount>0x80)
588 {
589 RunValue=(unsigned char) ReadBlobByte(image);
590 (void) memset(ptrB,(int) RunValue,(size_t) RunCountMasked);
591 }
592 else {
593 (void) ReadBlob(image,(size_t) RunCountMasked,ptrB);
594 }
595
596 ptrB+=(int) RunCountMasked;
597 j-=(int) RunCountMasked;
598
599 if (EOFBlob(image) != MagickFalse) goto Finish; /* wrong data: unexpected eof in line */
600 RunCount=(unsigned char) ReadBlobByte(image);
601 RunCountMasked=RunCount & 0x7F;
602 }
603
604 InsertRow(image,depth,BImgBuff,i,exception);
605 }
606 (void) SyncImage(image,exception);
607
608
609 /*detect monochrome image*/
610
611 if(palette==NULL)
612 { /*attempt to detect binary (black&white) images*/
613 if ((image->storage_class == PseudoClass) &&
614 (SetImageGray(image,exception) != MagickFalse))
615 {
616 if(GetCutColors(image,exception)==2)
617 {
618 for (i=0; i < (ssize_t)image->colors; i++)
619 {
620 register Quantum
621 sample;
622 sample=ScaleCharToQuantum((unsigned char) i);
623 if(image->colormap[i].red!=sample) goto Finish;
624 if(image->colormap[i].green!=sample) goto Finish;
625 if(image->colormap[i].blue!=sample) goto Finish;
626 }
627
628 image->colormap[1].red=image->colormap[1].green=
629 image->colormap[1].blue=QuantumRange;
630 for (i=0; i < (ssize_t)image->rows; i++)
631 {
632 q=QueueAuthenticPixels(image,0,i,image->columns,1,exception);
633 if (q == (Quantum *) NULL)
634 break;
635 for (j=0; j < (ssize_t)image->columns; j++)
636 {
637 if (GetPixelRed(image,q) == ScaleCharToQuantum(1))
638 {
639 SetPixelRed(image,QuantumRange,q);
640 SetPixelGreen(image,QuantumRange,q);
641 SetPixelBlue(image,QuantumRange,q);
642 }
643 q+=GetPixelChannels(image);
644 }
645 if (SyncAuthenticPixels(image,exception) == MagickFalse) goto Finish;
646 }
647 }
648 }
649 }
650
651 Finish:
652 if (BImgBuff != NULL)
653 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
654 if (palette != NULL)
655 palette=DestroyImage(palette);
656 if (clone_info != NULL)
657 clone_info=DestroyImageInfo(clone_info);
658 if (EOFBlob(image) != MagickFalse)
659 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
660 image->filename);
661 (void) CloseBlob(image);
662 return(GetFirstImageInList(image));
663 }
664
665 /*
666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667 % %
668 % %
669 % %
670 % R e g i s t e r C U T I m a g e %
671 % %
672 % %
673 % %
674 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
675 %
676 % RegisterCUTImage() adds attributes for the CUT image format to
677 % the list of supported formats. The attributes include the image format
678 % tag, a method to read and/or write the format, whether the format
679 % supports the saving of more than one frame to the same file or blob,
680 % whether the format supports native in-memory I/O, and a brief
681 % description of the format.
682 %
683 % The format of the RegisterCUTImage method is:
684 %
685 % size_t RegisterCUTImage(void)
686 %
687 */
RegisterCUTImage(void)688 ModuleExport size_t RegisterCUTImage(void)
689 {
690 MagickInfo
691 *entry;
692
693 entry=AcquireMagickInfo("CUT","CUT","DR Halo");
694 entry->decoder=(DecodeImageHandler *) ReadCUTImage;
695 entry->flags|=CoderDecoderSeekableStreamFlag;
696 (void) RegisterMagickInfo(entry);
697 return(MagickImageCoderSignature);
698 }
699
700 /*
701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
702 % %
703 % %
704 % %
705 % U n r e g i s t e r C U T I m a g e %
706 % %
707 % %
708 % %
709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
710 %
711 % UnregisterCUTImage() removes format registrations made by the
712 % CUT module from the list of supported formats.
713 %
714 % The format of the UnregisterCUTImage method is:
715 %
716 % UnregisterCUTImage(void)
717 %
718 */
UnregisterCUTImage(void)719 ModuleExport void UnregisterCUTImage(void)
720 {
721 (void) UnregisterMagickInfo("CUT");
722 }
723