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