1 /*
2 % Copyright (C) 2003-2020 GraphicsMagick Group
3 % Copyright (C) 2002 ImageMagick Studio
4 %
5 % This program is covered by multiple licenses, which are described in
6 % Copyright.txt. You should have received a copy of Copyright.txt with this
7 % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
8 %
9 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10 %                                                                             %
11 %                                                                             %
12 %                              CCC  U   U  TTTTT                              %
13 %                             C     U   U    T                                %
14 %                             C     U   U    T                                %
15 %                             C     U   U    T                                %
16 %                              CCC   UUU     T                                %
17 %                                                                             %
18 %                                                                             %
19 %                         Read DR Halo Image Format.                          %
20 %                                                                             %
21 %                                                                             %
22 %                              Software Design                                %
23 %                              Jaroslav Fojtik                                %
24 %                              June 2000 - 2007                               %
25 %                                                                             %
26 %                                                                             %
27 %                                                                             %
28 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
29 %
30 %
31 */
32 
33 /*
34   Include declarations.
35 */
36 #include "magick/studio.h"
37 #include "magick/analyze.h"
38 #include "magick/blob.h"
39 #include "magick/color.h"
40 #include "magick/colormap.h"
41 #include "magick/magick.h"
42 #include "magick/pixel_cache.h"
43 #include "magick/utility.h"
44 
45 typedef struct
46 {
47   unsigned Width;
48   unsigned Height;
49   unsigned Reserved;
50 }CUTHeader;      /*Dr Halo*/
51 typedef struct
52 {
53   char FileId[2];
54   unsigned Version;
55   unsigned Size;
56   char FileType;
57   char SubType;
58   unsigned BoardID;
59   unsigned GraphicsMode;
60   unsigned MaxIndex;
61   unsigned MaxRed;
62   unsigned MaxGreen;
63   unsigned MaxBlue;
64   char PaletteId[20];
65 }CUTPalHeader;
66 
67 
InsertRow(unsigned char * p,long y,Image * image)68 static void InsertRow(unsigned char *p,long y,Image *image)
69 {
70   int bit; long x;
71   register PixelPacket *q;
72   IndexPacket index;
73   register IndexPacket *indexes;
74 
75 
76   switch (image->depth)
77     {
78     case 1:  /* Convert bitmap scanline. */
79       {
80         q=SetImagePixels(image,0,y,image->columns,1);
81         if (q == (PixelPacket *) NULL)
82           break;
83         indexes=AccessMutableIndexes(image);
84         for (x=0; x < ((long) image->columns-7); x+=8)
85           {
86             for (bit=0; bit < 8; bit++)
87               {
88                 index=((*p) & (0x80U >> bit) ? 0x01U : 0x00U);
89                 indexes[x+bit]=index;
90                 *q++=image->colormap[index];
91               }
92             p++;
93           }
94         if ((image->columns % 8) != 0)
95           {
96             for (bit=0; bit < (long) (image->columns % 8); bit++)
97               {
98                 index=((*p) & (0x80 >> bit) ? 0x01U : 0x00U);
99                 indexes[x+bit]=index;
100                 *q++=image->colormap[index];
101               }
102             p++;
103           }
104         if (!SyncImagePixels(image))
105           break;
106         /*            if (image->previous == (Image *) NULL)
107                       if (QuantumTick(y,image->rows))
108                       ProgressMonitor(LoadImageText,image->rows-y-1,image->rows);*/
109         break;
110       }
111     case 2:  /* Convert PseudoColor scanline. */
112       {
113         q=SetImagePixels(image,0,y,image->columns,1);
114         if (q == (PixelPacket *) NULL)
115           break;
116         indexes=AccessMutableIndexes(image);
117         for (x=0; x < ((long) image->columns-1); x+=2)
118           {
119             index=(IndexPacket) ((*p >> 6U) & 0x3U);
120             VerifyColormapIndex(image,index);
121             indexes[x]=index;
122             *q++=image->colormap[index];
123             index=(IndexPacket) ((*p >> 4U) & 0x3U);
124             VerifyColormapIndex(image,index);
125             indexes[x]=index;
126             *q++=image->colormap[index];
127             index=(IndexPacket) ((*p >> 2U) & 0x3U);
128             VerifyColormapIndex(image,index);
129             indexes[x]=index;
130             *q++=image->colormap[index];
131             index=(IndexPacket) ((*p) & 0x3U);
132             VerifyColormapIndex(image,index);
133             indexes[x+1]=index;
134             *q++=image->colormap[index];
135             p++;
136           }
137         if ((image->columns % 4) != 0)
138           {
139             index=(IndexPacket) ((*p >> 6U) & 0x3U);
140             VerifyColormapIndex(image,index);
141             indexes[x]=index;
142             *q++=image->colormap[index];
143             if ((image->columns % 4) >= 1)
144 
145               {
146                 index=(IndexPacket) ((*p >> 4U) & 0x3U);
147                 VerifyColormapIndex(image,index);
148                 indexes[x]=index;
149                 *q++=image->colormap[index];
150                 if ((image->columns % 4) >= 2U)
151 
152                   {
153                     index=(IndexPacket) ((*p >> 2U) & 0x3U);
154                     VerifyColormapIndex(image,index);
155                     indexes[x]=index;
156                     *q++=image->colormap[index];
157                   }
158               }
159             p++;
160           }
161         if (!SyncImagePixels(image))
162           break;
163         /*         if (image->previous == (Image *) NULL)
164                    if (QuantumTick(y,image->rows))
165                    ProgressMonitor(LoadImageText,image->rows-y-1,image->rows);*/
166         break;
167       }
168 
169     case 4:  /* Convert PseudoColor scanline. */
170       {
171         q=SetImagePixels(image,0,y,image->columns,1);
172         if (q == (PixelPacket *) NULL)
173           break;
174         indexes=AccessMutableIndexes(image);
175         for (x=0; x < ((long) image->columns-1); x+=2)
176           {
177             index=(IndexPacket) ((*p >> 4U) & 0xfU);
178             VerifyColormapIndex(image,index);
179             indexes[x]=index;
180             *q++=image->colormap[index];
181             index=(IndexPacket) ((*p) & 0xfU);
182             VerifyColormapIndex(image,index);
183             indexes[x+1]=index;
184             *q++=image->colormap[index];
185             p++;
186           }
187         if ((image->columns % 2) != 0)
188           {
189             index=(IndexPacket) ((*p >> 4U) & 0xfU);
190             VerifyColormapIndex(image,index);
191             indexes[x]=index;
192             *q++=image->colormap[index];
193             p++;
194           }
195         if (!SyncImagePixels(image))
196           break;
197         /*         if (image->previous == (Image *) NULL)
198                    if (QuantumTick(y,image->rows))
199                    ProgressMonitor(LoadImageText,image->rows-y-1,image->rows);*/
200         break;
201       }
202     case 8: /* Convert PseudoColor scanline. */
203       {
204         q=SetImagePixels(image,0,y,image->columns,1);
205         if (q == (PixelPacket *) NULL) break;
206         indexes=AccessMutableIndexes(image);
207 
208         for (x=0; x < (long) image->columns; x++)
209           {
210             index=(IndexPacket) (*p);
211             VerifyColormapIndex(image,index);
212             indexes[x]=index;
213             *q++=image->colormap[index];
214             p++;
215           }
216         if (!SyncImagePixels(image))
217           break;
218         /*           if (image->previous == (Image *) NULL)
219                      if (QuantumTick(y,image->rows))
220                      ProgressMonitor(LoadImageText,image->rows-y-1,image->rows);*/
221       }
222       break;
223 
224     }
225 }
226 
GetCutColors(Image * image)227 static unsigned int GetCutColors(Image *image)
228 {
229   unsigned long
230     x,
231     y;
232 
233   PixelPacket
234     *q;
235 
236   Quantum
237     MaxColor,
238     ScaleCharToQuantum16;
239 
240   /* Compute the number of colors in Grayed R[i]=G[i]=B[i] image */
241   ScaleCharToQuantum16=ScaleCharToQuantum(16U);
242   MaxColor=0U;
243   for (y=0; y < image->rows; y++)
244     {
245 
246       q=SetImagePixels(image,0,y,image->columns,1);
247       if (q == (PixelPacket *) NULL)
248           break;
249       for (x=image->columns; x != 0; x--)
250         {
251           if (MaxColor < q->red)
252             MaxColor=q->red;
253           if (MaxColor >= ScaleCharToQuantum16)
254             return(255U);
255           q++;
256         }
257     }
258   if (MaxColor < ScaleCharToQuantum(2))
259     MaxColor=2U;
260   else if (MaxColor < ScaleCharToQuantum(16U))
261     MaxColor=16U;
262   return (MaxColor);
263 }
264 
265 /*
266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267 %                                                                             %
268 %                                                                             %
269 %                                                                             %
270 %   R e a d C U T I m a g e                                                   %
271 %                                                                             %
272 %                                                                             %
273 %                                                                             %
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275 %
276 %  Method ReadCUTImage reads an CUT X image file and returns it.  It
277 %  allocates the memory necessary for the new Image structure and returns a
278 %  pointer to the new image.
279 %
280 %  The format of the ReadCUTImage method is:
281 %
282 %      Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
283 %
284 %  A description of each parameter follows:
285 %
286 %    o image:  Method ReadCUTImage returns a pointer to the image after
287 %      reading. A null image is returned if there is a memory shortage or if
288 %      the image cannot be read.
289 %
290 %    o image_info: Specifies a pointer to a ImageInfo structure.
291 %
292 %    o exception: return any errors or warnings in this structure.
293 %
294 %
295 */
296 #define ThrowCUTReaderException(code_,reason_,image_) \
297 { \
298   if (palette != (Image *) NULL)              \
299     DestroyImage(palette);                    \
300   if (clone_info != (ImageInfo *) NULL)       \
301     DestroyImageInfo(clone_info);             \
302   ThrowReaderException(code_,reason_,image_); \
303 }
ReadCUTImage(const ImageInfo * image_info,ExceptionInfo * exception)304 static Image *ReadCUTImage(const ImageInfo *image_info,ExceptionInfo *exception)
305 {
306   Image *image,*palette = (Image *) NULL;
307   ImageInfo *clone_info = (ImageInfo *) NULL;
308   unsigned int status;
309   unsigned long EncodedByte;
310   unsigned char RunCount,RunValue,RunCountMasked;
311   CUTHeader  Header;
312   CUTPalHeader PalHeader;
313   long i,j;
314   long ldblk;
315   unsigned char *BImgBuff=NULL,*ptrB;
316   PixelPacket *q;
317 
318   /*
319     Open image file.
320   */
321   assert(image_info != (const ImageInfo *) NULL);
322   assert(image_info->signature == MagickSignature);
323   assert(exception != (ExceptionInfo *) NULL);
324   assert(exception->signature == MagickSignature);
325   image=AllocateImage(image_info);
326   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
327   if (status == False)
328     ThrowReaderException(FileOpenError,UnableToOpenFile,image);
329   /*
330     Read CUT image.
331   */
332   Header.Width=ReadBlobLSBShort(image);
333   Header.Height=ReadBlobLSBShort(image);
334   Header.Reserved=ReadBlobLSBShort(image);
335 
336   if (Header.Width==0 || Header.Height==0 || Header.Reserved!=0 ||
337       (Header.Width > INT_MAX) || (Header.Height > INT_MAX) )
338   CUT_KO:  ThrowCUTReaderException(CorruptImageError,ImproperImageHeader,image);
339 
340   /*---This code checks first line of image---*/
341   EncodedByte=ReadBlobLSBShort(image);
342   RunCount=ReadBlobByte(image);
343   RunCountMasked=RunCount & 0x7F;
344   ldblk=0;
345   while (RunCountMasked != 0)  /*end of line?*/
346     {
347       i=1;
348       if (RunCount<0x80) i=RunCountMasked;
349       (void) SeekBlob(image,TellBlob(image)+i,SEEK_SET);
350       if (EOFBlob(image)) goto CUT_KO;  /*wrong data*/
351       EncodedByte-=i+1;
352       ldblk+=RunCountMasked;
353 
354       RunCount=ReadBlobByte(image);
355       if (EOFBlob(image))  goto CUT_KO;  /*wrong data: unexpected eof in line*/
356       RunCountMasked=RunCount & 0x7F;
357     }
358   if (EncodedByte!=1) goto CUT_KO;  /*wrong data: size incorrect*/
359   i=0;        /*guess a number of bit planes*/
360   if (ldblk==(int) Header.Width)   i=8;
361   if (2*ldblk==(int) Header.Width) i=4;
362   if (8*ldblk==(int) Header.Width) i=1;
363   if (i==0) goto CUT_KO;    /*wrong data: incorrect bit planes*/
364 
365   image->columns=Header.Width;
366   image->rows=Header.Height;
367   image->depth=i;
368   image->colors=1l >> i;
369 
370   /* If ping is true, then only set image size and colors without reading any image data. */
371   if (image_info->ping) goto Finish;
372 
373   if (CheckImagePixelLimits(image, exception) != MagickPass)
374     ThrowCUTReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
375 
376   /* ----- Do something with palette ----- */
377   if ((clone_info=CloneImageInfo(image_info)) == NULL) goto NoPalette;
378 
379   i=(long) strlen(clone_info->filename);
380   j=i;
381   while (--i>0)
382     {
383       if (clone_info->filename[i]=='.')
384         {
385           break;
386         }
387       if (clone_info->filename[i]=='/' || clone_info->filename[i]=='\\' ||
388           clone_info->filename[i]==':' )
389         {
390           i=j;
391           break;
392         }
393     }
394 
395   if (i <= 0)
396     goto NoPalette;
397 
398   (void) strlcpy(clone_info->filename+i,".PAL",sizeof(clone_info->filename)-i);
399   if ((clone_info->file=fopen(clone_info->filename,"rb"))==NULL)
400     {
401       (void) strlcpy(clone_info->filename+i,".pal",sizeof(clone_info->filename)-i);
402       if ((clone_info->file=fopen(clone_info->filename,"rb"))==NULL)
403         {
404           clone_info->filename[i]=0;
405           if ((clone_info->file=fopen(clone_info->filename,"rb"))==NULL)
406             {
407               DestroyImageInfo(clone_info);
408               clone_info=NULL;
409               goto NoPalette;
410             }
411         }
412     }
413 
414   if ( (palette=AllocateImage(clone_info))==NULL ) goto NoPalette;
415   status=OpenBlob(clone_info,palette,ReadBinaryBlobMode,exception);
416   if (status == False)
417     {
418     ErasePalette:
419       DestroyImage(palette);
420       palette=NULL;
421       goto NoPalette;
422     }
423 
424 
425   if (palette!=NULL)
426     {
427       (void) ReadBlob(palette,2,PalHeader.FileId);
428       if (strncmp(PalHeader.FileId,"AH",2)) goto ErasePalette;
429       PalHeader.Version=ReadBlobLSBShort(palette);
430       PalHeader.Size=ReadBlobLSBShort(palette);
431       PalHeader.FileType=ReadBlobByte(palette);
432       PalHeader.SubType=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);
439       (void) ReadBlob(palette,20,PalHeader.PaletteId);
440 
441       if (EOFBlob(image))
442         ThrowCUTReaderException(CorruptImageError,UnexpectedEndOfFile,image);
443 
444       if (PalHeader.MaxIndex<1) goto ErasePalette;
445       image->colors=PalHeader.MaxIndex+1;
446       if (!AllocateImageColormap(image,image->colors)) goto NoMemory;
447 
448       if (PalHeader.MaxRed==0) PalHeader.MaxRed=MaxRGB;  /*avoid division by 0*/
449       if (PalHeader.MaxGreen==0) PalHeader.MaxGreen=MaxRGB;
450       if (PalHeader.MaxBlue==0) PalHeader.MaxBlue=MaxRGB;
451 
452       for (i=0;i<=(int) PalHeader.MaxIndex;i++)
453         {
454           /*this may be wrong- I don't know why is palette such strange*/
455           j=(long) TellBlob(palette);
456           if ((j % 512)>512-6)
457             {
458               j=((j / 512)+1)*512;
459               (void) SeekBlob(palette,j,SEEK_SET);
460             }
461           image->colormap[i].red=ReadBlobLSBShort(palette);
462           if (MaxRGB!=PalHeader.MaxRed)
463             {
464               image->colormap[i].red=(Quantum)
465                 (((double)image->colormap[i].red*MaxRGB+(PalHeader.MaxRed>>1))/PalHeader.MaxRed+0.5);
466             }
467           image->colormap[i].green=ReadBlobLSBShort(palette);
468           if (MaxRGB!=PalHeader.MaxGreen)
469             {
470               image->colormap[i].green=(Quantum)
471                 (((double)image->colormap[i].green*MaxRGB+(PalHeader.MaxGreen>>1))/PalHeader.MaxGreen+0.5);
472             }
473           image->colormap[i].blue=ReadBlobLSBShort(palette);
474           if (MaxRGB!=PalHeader.MaxBlue)
475             {
476               image->colormap[i].blue=(Quantum)
477                 (((double)image->colormap[i].blue*MaxRGB+(PalHeader.MaxBlue>>1))/PalHeader.MaxBlue+0.5);
478             }
479 
480         }
481       if (EOFBlob(image))
482         ThrowCUTReaderException(CorruptImageError,UnexpectedEndOfFile,image);
483     }
484 
485 
486 
487  NoPalette:
488   if (palette==NULL)
489     {
490 
491       image->colors=256;
492       if (!AllocateImageColormap(image,image->colors))
493         {
494         NoMemory:
495           if (clone_info != NULL)
496             {
497               DestroyImageInfo(clone_info);
498               clone_info=(ImageInfo *) NULL;
499             }
500           ThrowCUTReaderException(ResourceLimitError,MemoryAllocationFailed,image);
501         }
502 
503       for (i=0; i < (long)image->colors; i++)
504         {
505           image->colormap[i].red=ScaleCharToQuantum(i);
506           image->colormap[i].green=ScaleCharToQuantum(i);
507           image->colormap[i].blue=ScaleCharToQuantum(i);
508         }
509     }
510 
511 
512   /* ----- Load RLE compressed raster ----- */
513   BImgBuff=MagickAllocateResourceLimitedMemory(unsigned char *,(size_t) (ldblk));  /*Ldblk was set in the check phase*/
514   if (BImgBuff==NULL) goto NoMemory;
515 
516   (void) SeekBlob(image,6 /*sizeof(Header)*/,SEEK_SET);
517   for (i=0;i<(int) Header.Height;i++)
518     {
519       EncodedByte=ReadBlobLSBShort(image);
520 
521       ptrB=BImgBuff;
522       j=ldblk;
523 
524       RunCount=ReadBlobByte(image);
525       RunCountMasked=RunCount & 0x7F;
526 
527       while (RunCountMasked!=0)
528         {
529           if (RunCountMasked>j)
530             {    /*Wrong Data*/
531               RunCountMasked=(unsigned char) j;
532               if (j==0)
533                 {
534                   break;
535                 }
536             }
537 
538           if (RunCount>0x80)
539             {
540               RunValue=ReadBlobByte(image);
541               (void) memset(ptrB,RunValue,RunCountMasked);
542             }
543           else {
544             (void) ReadBlob(image,RunCountMasked,ptrB);
545           }
546 
547           ptrB+=RunCountMasked;
548           j-=RunCountMasked;
549 
550           if (EOFBlob(image)) goto Finish;  /* wrong data: unexpected eof in line */
551           RunCount=ReadBlobByte(image);
552           RunCountMasked=RunCount & 0x7F;
553         }
554 
555       InsertRow(BImgBuff,i,image);
556     }
557 
558 
559   /*detect monochrome image*/
560 
561   if (palette==NULL)
562     {    /*attempt to detect binary (black&white) images*/
563       if ((image->storage_class == PseudoClass) && IsGrayImage(image,&image->exception))
564         {
565           if (GetCutColors(image)==2)
566             {
567               for (i=0; i < (long)image->colors; i++)
568                 {
569                   register Quantum
570                     sample;
571                   sample=ScaleCharToQuantum(i);
572                   if (image->colormap[i].red!=sample) goto Finish;
573                   if (image->colormap[i].green!=sample) goto Finish;
574                   if (image->colormap[i].blue!=sample) goto Finish;
575                 }
576 
577               image->colormap[1].red=image->colormap[1].green=image->colormap[1].blue=MaxRGB;
578               for (i=0; i < (long)image->rows; i++)
579                 {
580                   q=SetImagePixels(image,0,i,image->columns,1);
581                   if (q == (PixelPacket *) NULL)
582                     break;
583                   for (j=0; j < (long)image->columns; j++)
584                     {
585                       if (q->red==ScaleCharToQuantum(1))
586                         {
587                           q->red=q->green=q->blue=MaxRGB;
588                         }
589                       q++;
590                     }
591                   if (!SyncImagePixels(image)) goto Finish;
592                 }
593             }
594         }
595     }
596 
597  Finish:
598   if (BImgBuff!=NULL) MagickFreeResourceLimitedMemory(BImgBuff);
599   if (palette!=NULL)
600     {
601       DestroyImage(palette);
602       palette=(Image *) NULL;
603     }
604   if (clone_info!=NULL)
605     {
606       DestroyImageInfo(clone_info);
607       clone_info=(ImageInfo *) NULL;
608     }
609   if (EOFBlob(image))
610     ThrowCUTReaderException(CorruptImageError,UnexpectedEndOfFile,image);
611   CloseBlob(image);
612   StopTimer(&image->timer);
613   return(image);
614 }
615 
616 /*
617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
618 %                                                                             %
619 %                                                                             %
620 %                                                                             %
621 %   R e g i s t e r C U T I m a g e                                           %
622 %                                                                             %
623 %                                                                             %
624 %                                                                             %
625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
626 %
627 %  Method RegisterCUTImage adds attributes for the CUT image format to
628 %  the list of supported formats.  The attributes include the image format
629 %  tag, a method to read and/or write the format, whether the format
630 %  supports the saving of more than one frame to the same file or blob,
631 %  whether the format supports native in-memory I/O, and a brief
632 %  description of the format.
633 %
634 %  The format of the RegisterCUTImage method is:
635 %
636 %      RegisterCUTImage(void)
637 %
638 */
RegisterCUTImage(void)639 ModuleExport void RegisterCUTImage(void)
640 {
641   MagickInfo
642     *entry;
643 
644   entry=SetMagickInfo("CUT");
645   entry->decoder=(DecoderHandler) ReadCUTImage;
646   entry->seekable_stream=True;
647   entry->description="DR Halo";
648   entry->module="CUT";
649   (void) RegisterMagickInfo(entry);
650 }
651 
652 /*
653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
654 %                                                                             %
655 %                                                                             %
656 %                                                                             %
657 %   U n r e g i s t e r C U T I m a g e                                       %
658 %                                                                             %
659 %                                                                             %
660 %                                                                             %
661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
662 %
663 %  Method UnregisterCUTImage removes format registrations made by the
664 %  CUT module from the list of supported formats.
665 %
666 %  The format of the UnregisterCUTImage method is:
667 %
668 %      UnregisterCUTImage(void)
669 %
670 */
UnregisterCUTImage(void)671 ModuleExport void UnregisterCUTImage(void)
672 {
673   (void) UnregisterMagickInfo("CUT");
674 }
675