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