1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                            RRRR   L      EEEEE                              %
7 %                            R   R  L      E                                  %
8 %                            RRRR   L      EEE                                %
9 %                            R R    L      E                                  %
10 %                            R  R   LLLLL  EEEEE                              %
11 %                                                                             %
12 %                                                                             %
13 %                          Read URT RLE Image Format                          %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/blob-private.h"
45 #include "MagickCore/cache.h"
46 #include "MagickCore/colormap.h"
47 #include "MagickCore/colormap-private.h"
48 #include "MagickCore/exception.h"
49 #include "MagickCore/exception-private.h"
50 #include "MagickCore/image.h"
51 #include "MagickCore/image-private.h"
52 #include "MagickCore/list.h"
53 #include "MagickCore/magick.h"
54 #include "MagickCore/memory_.h"
55 #include "MagickCore/monitor.h"
56 #include "MagickCore/monitor-private.h"
57 #include "MagickCore/pixel-accessor.h"
58 #include "MagickCore/pixel.h"
59 #include "MagickCore/property.h"
60 #include "MagickCore/quantum-private.h"
61 #include "MagickCore/static.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/module.h"
64 
65 /*
66 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
67 %                                                                             %
68 %                                                                             %
69 %                                                                             %
70 %   I s R L E                                                                 %
71 %                                                                             %
72 %                                                                             %
73 %                                                                             %
74 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75 %
76 %  IsRLE() returns MagickTrue if the image format type, identified by the
77 %  magick string, is RLE.
78 %
79 %  The format of the ReadRLEImage method is:
80 %
81 %      MagickBooleanType IsRLE(const unsigned char *magick,const size_t length)
82 %
83 %  A description of each parameter follows:
84 %
85 %    o magick: compare image format pattern against these bytes.
86 %
87 %    o length: Specifies the length of the magick string.
88 %
89 %
90 */
IsRLE(const unsigned char * magick,const size_t length)91 static MagickBooleanType IsRLE(const unsigned char *magick,const size_t length)
92 {
93   if (length < 2)
94     return(MagickFalse);
95   if (memcmp(magick,"\122\314",2) == 0)
96     return(MagickTrue);
97   return(MagickFalse);
98 }
99 
100 /*
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 %                                                                             %
103 %                                                                             %
104 %                                                                             %
105 %   R e a d R L E I m a g e                                                   %
106 %                                                                             %
107 %                                                                             %
108 %                                                                             %
109 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 %
111 %  ReadRLEImage() reads a run-length encoded Utah Raster Toolkit
112 %  image file and returns it.  It allocates the memory necessary for the new
113 %  Image structure and returns a pointer to the new image.
114 %
115 %  The format of the ReadRLEImage method is:
116 %
117 %      Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
118 %
119 %  A description of each parameter follows:
120 %
121 %    o image_info: the image info.
122 %
123 %    o exception: return any errors or warnings in this structure.
124 %
125 %
126 */
ReadRLEImage(const ImageInfo * image_info,ExceptionInfo * exception)127 static Image *ReadRLEImage(const ImageInfo *image_info,ExceptionInfo *exception)
128 {
129 #define SkipLinesOp  0x01
130 #define SetColorOp  0x02
131 #define SkipPixelsOp  0x03
132 #define ByteDataOp  0x05
133 #define RunDataOp  0x06
134 #define EOFOp  0x07
135 
136   char
137     magick[12];
138 
139   Image
140     *image;
141 
142   int
143     opcode,
144     operand,
145     status;
146 
147   MagickStatusType
148     flags;
149 
150   MagickSizeType
151     number_pixels;
152 
153   MemoryInfo
154     *pixel_info;
155 
156   Quantum
157     index;
158 
159   register ssize_t
160     x;
161 
162   register Quantum
163     *q;
164 
165   register ssize_t
166     i;
167 
168   register unsigned char
169     *p;
170 
171   size_t
172     bits_per_pixel,
173     map_length,
174     number_colormaps,
175     number_planes,
176     number_planes_filled,
177     one,
178     pixel_info_length;
179 
180   ssize_t
181     count,
182     offset,
183     y;
184 
185   unsigned char
186     background_color[256],
187     *colormap,
188     pixel,
189     plane,
190     *pixels;
191 
192   /*
193     Open image file.
194   */
195   assert(image_info != (const ImageInfo *) NULL);
196   assert(image_info->signature == MagickCoreSignature);
197   if (image_info->debug != MagickFalse)
198     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
199       image_info->filename);
200   assert(exception != (ExceptionInfo *) NULL);
201   assert(exception->signature == MagickCoreSignature);
202   image=AcquireImage(image_info,exception);
203   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
204   if (status == MagickFalse)
205     return(DestroyImageList(image));
206   /*
207     Determine if this a RLE file.
208   */
209   count=ReadBlob(image,2,(unsigned char *) magick);
210   if ((count != 2) || (memcmp(magick,"\122\314",2) != 0))
211     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
212   do
213   {
214     /*
215       Read image header.
216     */
217     image->page.x=ReadBlobLSBShort(image);
218     image->page.y=ReadBlobLSBShort(image);
219     image->columns=ReadBlobLSBShort(image);
220     image->rows=ReadBlobLSBShort(image);
221     flags=(MagickStatusType) ReadBlobByte(image);
222     image->alpha_trait=flags & 0x04 ? BlendPixelTrait : UndefinedPixelTrait;
223     number_planes=(size_t) ReadBlobByte(image);
224     bits_per_pixel=(size_t) ReadBlobByte(image);
225     number_colormaps=(size_t) ReadBlobByte(image);
226     map_length=(unsigned char) ReadBlobByte(image);
227     if (map_length >= 64)
228       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
229     one=1;
230     map_length=one << map_length;
231     if ((number_planes == 0) || (number_planes == 2) ||
232         ((flags & 0x04) && (number_colormaps > 254)) || (bits_per_pixel != 8) ||
233         (image->columns == 0))
234       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
235     if (flags & 0x02)
236       {
237         /*
238           No background color-- initialize to black.
239         */
240         for (i=0; i < (ssize_t) number_planes; i++)
241           background_color[i]=0;
242         (void) ReadBlobByte(image);
243       }
244     else
245       {
246         /*
247           Initialize background color.
248         */
249         p=background_color;
250         for (i=0; i < (ssize_t) number_planes; i++)
251           *p++=(unsigned char) ReadBlobByte(image);
252       }
253     if ((number_planes & 0x01) == 0)
254       (void) ReadBlobByte(image);
255     if (EOFBlob(image) != MagickFalse)
256       {
257         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
258           image->filename);
259         break;
260       }
261     colormap=(unsigned char *) NULL;
262     if (number_colormaps != 0)
263       {
264         /*
265           Read image colormaps.
266         */
267         colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps,
268           3*map_length*sizeof(*colormap));
269         if (colormap == (unsigned char *) NULL)
270           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
271         p=colormap;
272         for (i=0; i < (ssize_t) number_colormaps; i++)
273           for (x=0; x < (ssize_t) map_length; x++)
274             *p++=(unsigned char) ScaleShortToQuantum(ReadBlobLSBShort(image));
275       }
276     if ((flags & 0x08) != 0)
277       {
278         char
279           *comment;
280 
281         size_t
282           length;
283 
284         /*
285           Read image comment.
286         */
287         length=ReadBlobLSBShort(image);
288         if (length != 0)
289           {
290             comment=(char *) AcquireQuantumMemory(length,sizeof(*comment));
291             if (comment == (char *) NULL)
292               ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
293             count=ReadBlob(image,length-1,(unsigned char *) comment);
294             comment[length-1]='\0';
295             (void) SetImageProperty(image,"comment",comment,exception);
296             comment=DestroyString(comment);
297             if ((length & 0x01) == 0)
298               (void) ReadBlobByte(image);
299           }
300       }
301     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
302       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
303         break;
304     status=SetImageExtent(image,image->columns,image->rows,exception);
305     if (status == MagickFalse)
306       return(DestroyImageList(image));
307     /*
308       Allocate RLE pixels.
309     */
310     if (image->alpha_trait != UndefinedPixelTrait)
311       number_planes++;
312     number_pixels=(MagickSizeType) image->columns*image->rows;
313     number_planes_filled=(number_planes % 2 == 0) ? number_planes :
314       number_planes+1;
315     if ((number_pixels*number_planes_filled) != (size_t) (number_pixels*
316          number_planes_filled))
317       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
318     pixel_info=AcquireVirtualMemory(image->columns,image->rows*
319       MagickMax(number_planes_filled,4)*sizeof(*pixels));
320     if (pixel_info == (MemoryInfo *) NULL)
321       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
322     pixel_info_length=image->columns*image->rows*
323       MagickMax(number_planes_filled,4);
324     pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
325     if ((flags & 0x01) && !(flags & 0x02))
326       {
327         ssize_t
328           j;
329 
330         /*
331           Set background color.
332         */
333         p=pixels;
334         for (i=0; i < (ssize_t) number_pixels; i++)
335         {
336           if (image->alpha_trait == UndefinedPixelTrait)
337             for (j=0; j < (ssize_t) number_planes; j++)
338               *p++=background_color[j];
339           else
340             {
341               for (j=0; j < (ssize_t) (number_planes-1); j++)
342                 *p++=background_color[j];
343               *p++=0;  /* initialize matte channel */
344             }
345         }
346       }
347     /*
348       Read runlength-encoded image.
349     */
350     plane=0;
351     x=0;
352     y=0;
353     opcode=ReadBlobByte(image);
354     do
355     {
356       switch (opcode & 0x3f)
357       {
358         case SkipLinesOp:
359         {
360           operand=ReadBlobByte(image);
361           if (opcode & 0x40)
362             operand=ReadBlobLSBSignedShort(image);
363           x=0;
364           y+=operand;
365           break;
366         }
367         case SetColorOp:
368         {
369           operand=ReadBlobByte(image);
370           plane=(unsigned char) operand;
371           if (plane == 255)
372             plane=(unsigned char) (number_planes-1);
373           x=0;
374           break;
375         }
376         case SkipPixelsOp:
377         {
378           operand=ReadBlobByte(image);
379           if (opcode & 0x40)
380             operand=ReadBlobLSBSignedShort(image);
381           x+=operand;
382           break;
383         }
384         case ByteDataOp:
385         {
386           operand=ReadBlobByte(image);
387           if (opcode & 0x40)
388             operand=ReadBlobLSBSignedShort(image);
389           offset=((image->rows-y-1)*image->columns*number_planes)+x*
390             number_planes+plane;
391           operand++;
392           if ((offset < 0) ||
393               (offset+((size_t) operand*number_planes) > pixel_info_length))
394             {
395               if (number_colormaps != 0)
396                 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
397               pixel_info=RelinquishVirtualMemory(pixel_info);
398               ThrowReaderException(CorruptImageError,"UnableToReadImageData");
399             }
400           p=pixels+offset;
401           for (i=0; i < (ssize_t) operand; i++)
402           {
403             pixel=(unsigned char) ReadBlobByte(image);
404             if ((y < (ssize_t) image->rows) &&
405                 ((x+i) < (ssize_t) image->columns))
406               *p=pixel;
407             p+=number_planes;
408           }
409           if (operand & 0x01)
410             (void) ReadBlobByte(image);
411           x+=operand;
412           break;
413         }
414         case RunDataOp:
415         {
416           operand=ReadBlobByte(image);
417           if (opcode & 0x40)
418             operand=ReadBlobLSBSignedShort(image);
419           pixel=(unsigned char) ReadBlobByte(image);
420           (void) ReadBlobByte(image);
421           offset=((image->rows-y-1)*image->columns*number_planes)+x*
422             number_planes+plane;
423           operand++;
424           if ((offset < 0) ||
425               (offset+((size_t) operand*number_planes) > pixel_info_length))
426             {
427               if (number_colormaps != 0)
428                 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
429               pixel_info=RelinquishVirtualMemory(pixel_info);
430               ThrowReaderException(CorruptImageError,"UnableToReadImageData");
431             }
432           p=pixels+offset;
433           for (i=0; i < (ssize_t) operand; i++)
434           {
435             if ((y < (ssize_t) image->rows) &&
436                 ((x+i) < (ssize_t) image->columns))
437               *p=pixel;
438             p+=number_planes;
439           }
440           x+=operand;
441           break;
442         }
443         default:
444           break;
445       }
446       opcode=ReadBlobByte(image);
447     } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
448     if (number_colormaps != 0)
449       {
450         MagickStatusType
451           mask;
452 
453         /*
454           Apply colormap affineation to image.
455         */
456         mask=(MagickStatusType) (map_length-1);
457         p=pixels;
458         x=(ssize_t) number_planes;
459         if (number_colormaps == 1)
460           for (i=0; i < (ssize_t) number_pixels; i++)
461           {
462             ValidateColormapValue(image,*p & mask,&index,exception);
463             *p=colormap[(ssize_t) index];
464             p++;
465           }
466         else
467           if ((number_planes >= 3) && (number_colormaps >= 3))
468             for (i=0; i < (ssize_t) number_pixels; i++)
469               for (x=0; x < (ssize_t) number_planes; x++)
470               {
471                 ValidateColormapValue(image,(size_t) (x*map_length+
472                     (*p & mask)),&index,exception);
473                 *p=colormap[(ssize_t) index];
474                 p++;
475               }
476         if ((i < (ssize_t) number_pixels) || (x < (ssize_t) number_planes))
477           {
478             colormap=(unsigned char *) RelinquishMagickMemory(colormap);
479             pixel_info=RelinquishVirtualMemory(pixel_info);
480             ThrowReaderException(CorruptImageError,"UnableToReadImageData");
481           }
482       }
483     /*
484       Initialize image structure.
485     */
486     if (number_planes >= 3)
487       {
488         /*
489           Convert raster image to DirectClass pixel packets.
490         */
491         p=pixels;
492         for (y=0; y < (ssize_t) image->rows; y++)
493         {
494           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
495           if (q == (Quantum *) NULL)
496             break;
497           for (x=0; x < (ssize_t) image->columns; x++)
498           {
499             SetPixelRed(image,ScaleCharToQuantum(*p++),q);
500             SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
501             SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
502             if (image->alpha_trait != UndefinedPixelTrait)
503               SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
504             q+=GetPixelChannels(image);
505           }
506           if (SyncAuthenticPixels(image,exception) == MagickFalse)
507             break;
508           if (image->previous == (Image *) NULL)
509             {
510               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
511                 image->rows);
512               if (status == MagickFalse)
513                 break;
514             }
515         }
516       }
517     else
518       {
519         /*
520           Create colormap.
521         */
522         if (number_colormaps == 0)
523           map_length=256;
524         if (AcquireImageColormap(image,map_length,exception) == MagickFalse)
525           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
526         p=colormap;
527         if (number_colormaps == 1)
528           for (i=0; i < (ssize_t) image->colors; i++)
529           {
530             /*
531               Pseudocolor.
532             */
533             image->colormap[i].red=(MagickRealType)
534               ScaleCharToQuantum((unsigned char) i);
535             image->colormap[i].green=(MagickRealType)
536               ScaleCharToQuantum((unsigned char) i);
537             image->colormap[i].blue=(MagickRealType)
538               ScaleCharToQuantum((unsigned char) i);
539           }
540         else
541           if (number_colormaps > 1)
542             for (i=0; i < (ssize_t) image->colors; i++)
543             {
544               image->colormap[i].red=(MagickRealType)
545                 ScaleCharToQuantum(*p);
546               image->colormap[i].green=(MagickRealType)
547                 ScaleCharToQuantum(*(p+map_length));
548               image->colormap[i].blue=(MagickRealType)
549                 ScaleCharToQuantum(*(p+map_length*2));
550               p++;
551             }
552         p=pixels;
553         if (image->alpha_trait == UndefinedPixelTrait)
554           {
555             /*
556               Convert raster image to PseudoClass pixel packets.
557             */
558             for (y=0; y < (ssize_t) image->rows; y++)
559             {
560               q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
561               if (q == (Quantum *) NULL)
562                 break;
563               for (x=0; x < (ssize_t) image->columns; x++)
564               {
565                 SetPixelIndex(image,*p++,q);
566                 q+=GetPixelChannels(image);
567               }
568               if (SyncAuthenticPixels(image,exception) == MagickFalse)
569                 break;
570               if (image->previous == (Image *) NULL)
571                 {
572                   status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
573                     y,image->rows);
574                   if (status == MagickFalse)
575                     break;
576                 }
577             }
578             (void) SyncImage(image,exception);
579           }
580         else
581           {
582             /*
583               Image has a matte channel-- promote to DirectClass.
584             */
585             for (y=0; y < (ssize_t) image->rows; y++)
586             {
587               q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
588               if (q == (Quantum *) NULL)
589                 break;
590               for (x=0; x < (ssize_t) image->columns; x++)
591               {
592                 ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
593                 SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t)
594                   index].red),q);
595                 ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
596                 SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t)
597                   index].green),q);
598                 ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
599                 SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t)
600                   index].blue),q);
601                 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
602                 q+=GetPixelChannels(image);
603               }
604               if (x < (ssize_t) image->columns)
605                 break;
606               if (SyncAuthenticPixels(image,exception) == MagickFalse)
607                 break;
608               if (image->previous == (Image *) NULL)
609                 {
610                   status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
611                     y,image->rows);
612                   if (status == MagickFalse)
613                     break;
614                 }
615             }
616             image->colormap=(PixelInfo *) RelinquishMagickMemory(
617               image->colormap);
618             image->storage_class=DirectClass;
619             image->colors=0;
620           }
621       }
622     if (number_colormaps != 0)
623       colormap=(unsigned char *) RelinquishMagickMemory(colormap);
624     pixel_info=RelinquishVirtualMemory(pixel_info);
625     if (EOFBlob(image) != MagickFalse)
626       {
627         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
628           image->filename);
629         break;
630       }
631     /*
632       Proceed to next image.
633     */
634     if (image_info->number_scenes != 0)
635       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
636         break;
637     (void) ReadBlobByte(image);
638     count=ReadBlob(image,2,(unsigned char *) magick);
639     if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
640       {
641         /*
642           Allocate next image structure.
643         */
644         AcquireNextImage(image_info,image,exception);
645         if (GetNextImageInList(image) == (Image *) NULL)
646           {
647             image=DestroyImageList(image);
648             return((Image *) NULL);
649           }
650         image=SyncNextImageInList(image);
651         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
652           GetBlobSize(image));
653         if (status == MagickFalse)
654           break;
655       }
656   } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
657   (void) CloseBlob(image);
658   return(GetFirstImageInList(image));
659 }
660 
661 /*
662 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
663 %                                                                             %
664 %                                                                             %
665 %                                                                             %
666 %   R e g i s t e r R L E I m a g e                                           %
667 %                                                                             %
668 %                                                                             %
669 %                                                                             %
670 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
671 %
672 %  RegisterRLEImage() adds attributes for the RLE image format to
673 %  the list of supported formats.  The attributes include the image format
674 %  tag, a method to read and/or write the format, whether the format
675 %  supports the saving of more than one frame to the same file or blob,
676 %  whether the format supports native in-memory I/O, and a brief
677 %  description of the format.
678 %
679 %  The format of the RegisterRLEImage method is:
680 %
681 %      size_t RegisterRLEImage(void)
682 %
683 */
RegisterRLEImage(void)684 ModuleExport size_t RegisterRLEImage(void)
685 {
686   MagickInfo
687     *entry;
688 
689   entry=AcquireMagickInfo("RLE","RLE","Utah Run length encoded image");
690   entry->decoder=(DecodeImageHandler *) ReadRLEImage;
691   entry->magick=(IsImageFormatHandler *) IsRLE;
692   entry->flags^=CoderAdjoinFlag;
693   (void) RegisterMagickInfo(entry);
694   return(MagickImageCoderSignature);
695 }
696 
697 /*
698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
699 %                                                                             %
700 %                                                                             %
701 %                                                                             %
702 %   U n r e g i s t e r R L E I m a g e                                       %
703 %                                                                             %
704 %                                                                             %
705 %                                                                             %
706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707 %
708 %  UnregisterRLEImage() removes format registrations made by the
709 %  RLE module from the list of supported formats.
710 %
711 %  The format of the UnregisterRLEImage method is:
712 %
713 %      UnregisterRLEImage(void)
714 %
715 */
UnregisterRLEImage(void)716 ModuleExport void UnregisterRLEImage(void)
717 {
718   (void) UnregisterMagickInfo("RLE");
719 }
720