]> granicus.if.org Git - imagemagick/blob - coders/rle.c
Remove --enable-zero-configuration as per https://github.com/ImageMagick/ImageMagick...
[imagemagick] / coders / rle.c
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-2017 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 %    https://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 \f
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 \f
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 */
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 \f
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 */
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 #define ThrowRLEException(exception,message) \
136 { \
137   if (colormap != (unsigned char *) NULL) \
138     colormap=(unsigned char *) RelinquishMagickMemory(colormap); \
139   if (pixel_info != (MemoryInfo *) NULL) \
140     pixel_info=RelinquishVirtualMemory(pixel_info); \
141   ThrowReaderException((exception),(message)); \
142 }
143
144   char
145     magick[12];
146
147   Image
148     *image;
149
150   int
151     opcode,
152     operand,
153     status;
154
155   MagickStatusType
156     flags;
157
158   MagickSizeType
159     number_pixels;
160
161   MemoryInfo
162     *pixel_info;
163
164   Quantum
165     index;
166
167   register ssize_t
168     x;
169
170   register Quantum
171     *q;
172
173   register ssize_t
174     i;
175
176   register unsigned char
177     *p;
178
179   size_t
180     bits_per_pixel,
181     map_length,
182     number_colormaps,
183     number_planes,
184     number_planes_filled,
185     one,
186     pixel_info_length;
187
188   ssize_t
189     count,
190     offset,
191     y;
192
193   unsigned char
194     background_color[256],
195     *colormap,
196     pixel,
197     plane,
198     *pixels;
199
200   /*
201     Open image file.
202   */
203   assert(image_info != (const ImageInfo *) NULL);
204   assert(image_info->signature == MagickCoreSignature);
205   if (image_info->debug != MagickFalse)
206     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
207       image_info->filename);
208   assert(exception != (ExceptionInfo *) NULL);
209   assert(exception->signature == MagickCoreSignature);
210   image=AcquireImage(image_info,exception);
211   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
212   if (status == MagickFalse)
213     return(DestroyImageList(image));
214   /*
215     Determine if this a RLE file.
216   */
217   colormap=(unsigned char *) NULL;
218   pixel_info=(MemoryInfo *) NULL;
219   count=ReadBlob(image,2,(unsigned char *) magick);
220   if ((count != 2) || (memcmp(magick,"\122\314",2) != 0))
221     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
222   do
223   {
224     /*
225       Read image header.
226     */
227     image->page.x=(ssize_t) ReadBlobLSBShort(image);
228     image->page.y=(ssize_t) ReadBlobLSBShort(image);
229     image->columns=ReadBlobLSBShort(image);
230     image->rows=ReadBlobLSBShort(image);
231     flags=(MagickStatusType) ReadBlobByte(image);
232     image->alpha_trait=flags & 0x04 ? BlendPixelTrait : UndefinedPixelTrait;
233     number_planes=(size_t) ReadBlobByte(image);
234     bits_per_pixel=(size_t) ReadBlobByte(image);
235     number_colormaps=(size_t) ReadBlobByte(image);
236     map_length=(unsigned char) ReadBlobByte(image);
237     if (map_length >= 22)
238       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
239     if (EOFBlob(image) != MagickFalse)
240       ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
241     one=1;
242     map_length=one << map_length;
243     if ((number_planes == 0) || (number_planes == 2) || ((flags & 0x04) &&
244         ((number_planes <= 2) || number_planes > 254)) || (bits_per_pixel != 8))
245       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
246     if ((image->columns == 0) || (image->columns >= 32768) ||
247         (image->rows == 0) || (image->rows >= 32768))
248       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
249     if (flags & 0x02)
250       {
251         /*
252           No background color-- initialize to black.
253         */
254         for (i=0; i < (ssize_t) number_planes; i++)
255           background_color[i]=0;
256         (void) ReadBlobByte(image);
257       }
258     else
259       {
260         /*
261           Initialize background color.
262         */
263         p=background_color;
264         for (i=0; i < (ssize_t) number_planes; i++)
265           *p++=(unsigned char) ReadBlobByte(image);
266       }
267     if ((number_planes & 0x01) == 0)
268       (void) ReadBlobByte(image);
269     if (EOFBlob(image) != MagickFalse)
270       ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
271     if (image->alpha_trait != UndefinedPixelTrait)
272       number_planes++;
273     number_pixels=(MagickSizeType) image->columns*image->rows;
274     if ((GetBlobSize(image) == 0) || ((((MagickSizeType) number_pixels*
275          number_planes*bits_per_pixel/8)/GetBlobSize(image)) > 254.0))
276       ThrowRLEException(CorruptImageError,"InsufficientImageDataInFile")
277     if (((MagickSizeType) number_colormaps*map_length) > GetBlobSize(image))
278       ThrowRLEException(CorruptImageError,"InsufficientImageDataInFile")
279     if (number_colormaps != 0)
280       {
281         /*
282           Read image colormaps.
283         */
284         colormap=(unsigned char *) AcquireQuantumMemory(number_colormaps,
285           3*map_length*sizeof(*colormap));
286         if (colormap == (unsigned char *) NULL)
287           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
288         p=colormap;
289         for (i=0; i < (ssize_t) number_colormaps; i++)
290           for (x=0; x < (ssize_t) map_length; x++)
291           {
292             *p++=(unsigned char) ScaleQuantumToChar(ScaleShortToQuantum(
293               ReadBlobLSBShort(image)));
294             if (EOFBlob(image) != MagickFalse)
295               ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
296           }
297       }
298     if ((flags & 0x08) != 0)
299       {
300         char
301           *comment;
302
303         size_t
304           length;
305
306         /*
307           Read image comment.
308         */
309         length=ReadBlobLSBShort(image);
310         if (length != 0)
311           {
312             comment=(char *) AcquireQuantumMemory(length,sizeof(*comment));
313             if (comment == (char *) NULL)
314               ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
315             count=ReadBlob(image,length-1,(unsigned char *) comment);
316             comment[length-1]='\0';
317             (void) SetImageProperty(image,"comment",comment,exception);
318             comment=DestroyString(comment);
319             if ((length & 0x01) == 0)
320               (void) ReadBlobByte(image);
321           }
322       }
323     if (EOFBlob(image) != MagickFalse)
324       ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
325     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
326       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
327         break;
328     status=SetImageExtent(image,image->columns,image->rows,exception);
329     if (status == MagickFalse)
330       return(DestroyImageList(image));
331     /*
332       Allocate RLE pixels.
333     */
334     number_planes_filled=(number_planes % 2 == 0) ? number_planes :
335       number_planes+1;
336     if ((number_pixels*number_planes_filled) != (size_t) (number_pixels*
337          number_planes_filled))
338       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
339     pixel_info=AcquireVirtualMemory(image->columns,image->rows*
340       MagickMax(number_planes_filled,4)*sizeof(*pixels));
341     if (pixel_info == (MemoryInfo *) NULL)
342       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
343     pixel_info_length=image->columns*image->rows*
344       MagickMax(number_planes_filled,4);
345     pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
346     (void) ResetMagickMemory(pixels,0,pixel_info_length);
347     if ((flags & 0x01) && !(flags & 0x02))
348       {
349         ssize_t
350           j;
351
352         /*
353           Set background color.
354         */
355         p=pixels;
356         for (i=0; i < (ssize_t) number_pixels; i++)
357         {
358           if (image->alpha_trait == UndefinedPixelTrait)
359             for (j=0; j < (ssize_t) number_planes; j++)
360               *p++=background_color[j];
361           else
362             {
363               for (j=0; j < (ssize_t) (number_planes-1); j++)
364                 *p++=background_color[j];
365               *p++=0;  /* initialize matte channel */
366             }
367         }
368       }
369     /*
370       Read runlength-encoded image.
371     */
372     plane=0;
373     x=0;
374     y=0;
375     opcode=ReadBlobByte(image);
376     if (opcode == EOF)
377       ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
378     do
379     {
380       switch (opcode & 0x3f)
381       {
382         case SkipLinesOp:
383         {
384           operand=ReadBlobByte(image);
385           if (operand == EOF)
386             ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
387           if (opcode & 0x40)
388             {
389               operand=ReadBlobLSBSignedShort(image);
390               if (operand == EOF)
391                 ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
392             }
393           x=0;
394           y+=operand;
395           break;
396         }
397         case SetColorOp:
398         {
399           operand=ReadBlobByte(image);
400           if (operand == EOF)
401             ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
402           plane=(unsigned char) operand;
403           if (plane == 255)
404             plane=(unsigned char) (number_planes-1);
405           x=0;
406           break;
407         }
408         case SkipPixelsOp:
409         {
410           operand=ReadBlobByte(image);
411           if (operand == EOF)
412             ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
413           if (opcode & 0x40)
414             {
415               operand=ReadBlobLSBSignedShort(image);
416               if (operand == EOF)
417                 ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
418             }
419           x+=operand;
420           break;
421         }
422         case ByteDataOp:
423         {
424           operand=ReadBlobByte(image);
425           if (operand == EOF)
426             ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
427           if (opcode & 0x40)
428             {
429               operand=ReadBlobLSBSignedShort(image);
430               if (operand == EOF)
431                 ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
432             }
433           offset=(ssize_t) (((image->rows-y-1)*image->columns*number_planes)+x*
434             number_planes+plane);
435           operand++;
436           if ((offset < 0) ||
437               ((size_t) (offset+operand*number_planes) > pixel_info_length))
438             {
439               if (number_colormaps != 0)
440                 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
441               pixel_info=RelinquishVirtualMemory(pixel_info);
442               ThrowReaderException(CorruptImageError,"UnableToReadImageData");
443             }
444           p=pixels+offset;
445           for (i=0; i < (ssize_t) operand; i++)
446           {
447             pixel=(unsigned char) ReadBlobByte(image);
448             if ((y < (ssize_t) image->rows) &&
449                 ((x+i) < (ssize_t) image->columns))
450               *p=pixel;
451             p+=number_planes;
452           }
453           if (operand & 0x01)
454             (void) ReadBlobByte(image);
455           x+=operand;
456           break;
457         }
458         case RunDataOp:
459         {
460           operand=ReadBlobByte(image);
461           if (operand == EOF)
462             ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
463           if (opcode & 0x40)
464             {
465               operand=ReadBlobLSBSignedShort(image);
466               if (operand == EOF)
467                 ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
468             }
469           pixel=(unsigned char) ReadBlobByte(image);
470           (void) ReadBlobByte(image);
471           offset=(ssize_t) (((image->rows-y-1)*image->columns*number_planes)+x*
472             number_planes+plane);
473           operand++;
474           if ((offset < 0) ||
475               ((size_t) (offset+operand*number_planes) > pixel_info_length))
476             {
477               if (number_colormaps != 0)
478                 colormap=(unsigned char *) RelinquishMagickMemory(colormap);
479               pixel_info=RelinquishVirtualMemory(pixel_info);
480               ThrowReaderException(CorruptImageError,"UnableToReadImageData");
481             }
482           p=pixels+offset;
483           for (i=0; i < (ssize_t) operand; i++)
484           {
485             if ((y < (ssize_t) image->rows) &&
486                 ((x+i) < (ssize_t) image->columns))
487               *p=pixel;
488             p+=number_planes;
489           }
490           x+=operand;
491           break;
492         }
493         default:
494           break;
495       }
496       opcode=ReadBlobByte(image);
497       if (opcode == EOF)
498         ThrowRLEException(CorruptImageError,"UnexpectedEndOfFile");
499     } while (((opcode & 0x3f) != EOFOp) && (opcode != EOF));
500     if (number_colormaps != 0)
501       {
502         MagickStatusType
503           mask;
504
505         /*
506           Apply colormap affineation to image.
507         */
508         mask=(MagickStatusType) (map_length-1);
509         p=pixels;
510         x=(ssize_t) number_planes;
511         if (number_colormaps == 1)
512           for (i=0; i < (ssize_t) number_pixels; i++)
513           {
514             ValidateColormapValue(image,(ssize_t) (*p & mask),&index,exception);
515             *p=colormap[(ssize_t) index];
516             p++;
517           }
518         else
519           if ((number_planes >= 3) && (number_colormaps >= 3))
520             for (i=0; i < (ssize_t) number_pixels; i++)
521               for (x=0; x < (ssize_t) number_planes; x++)
522               {
523                 ValidateColormapValue(image,(ssize_t) (x*map_length+
524                   (*p & mask)),&index,exception);
525                 *p=colormap[(ssize_t) index];
526                 p++;
527               }
528         if ((i < (ssize_t) number_pixels) || (x < (ssize_t) number_planes))
529           {
530             colormap=(unsigned char *) RelinquishMagickMemory(colormap);
531             pixel_info=RelinquishVirtualMemory(pixel_info);
532             ThrowReaderException(CorruptImageError,"UnableToReadImageData");
533           }
534       }
535     /*
536       Initialize image structure.
537     */
538     if (number_planes >= 3)
539       {
540         /*
541           Convert raster image to DirectClass pixel packets.
542         */
543         p=pixels;
544         for (y=0; y < (ssize_t) image->rows; y++)
545         {
546           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
547           if (q == (Quantum *) NULL)
548             break;
549           for (x=0; x < (ssize_t) image->columns; x++)
550           {
551             SetPixelRed(image,ScaleCharToQuantum(*p++),q);
552             SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
553             SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
554             if (image->alpha_trait != UndefinedPixelTrait)
555               SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
556             q+=GetPixelChannels(image);
557           }
558           if (SyncAuthenticPixels(image,exception) == MagickFalse)
559             break;
560           if (image->previous == (Image *) NULL)
561             {
562               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
563                 image->rows);
564               if (status == MagickFalse)
565                 break;
566             }
567         }
568       }
569     else
570       {
571         /*
572           Create colormap.
573         */
574         if (number_colormaps == 0)
575           map_length=256;
576         if (AcquireImageColormap(image,map_length,exception) == MagickFalse)
577           ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
578         p=colormap;
579         if (number_colormaps == 1)
580           for (i=0; i < (ssize_t) image->colors; i++)
581           {
582             /*
583               Pseudocolor.
584             */
585             image->colormap[i].red=(MagickRealType)
586               ScaleCharToQuantum((unsigned char) i);
587             image->colormap[i].green=(MagickRealType)
588               ScaleCharToQuantum((unsigned char) i);
589             image->colormap[i].blue=(MagickRealType)
590               ScaleCharToQuantum((unsigned char) i);
591           }
592         else
593           if (number_colormaps > 1)
594             for (i=0; i < (ssize_t) image->colors; i++)
595             {
596               image->colormap[i].red=(MagickRealType)
597                 ScaleCharToQuantum(*p);
598               image->colormap[i].green=(MagickRealType)
599                 ScaleCharToQuantum(*(p+map_length));
600               image->colormap[i].blue=(MagickRealType)
601                 ScaleCharToQuantum(*(p+map_length*2));
602               p++;
603             }
604         p=pixels;
605         if (image->alpha_trait == UndefinedPixelTrait)
606           {
607             /*
608               Convert raster image to PseudoClass pixel packets.
609             */
610             for (y=0; y < (ssize_t) image->rows; y++)
611             {
612               q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
613               if (q == (Quantum *) NULL)
614                 break;
615               for (x=0; x < (ssize_t) image->columns; x++)
616               {
617                 SetPixelIndex(image,(Quantum) *p++,q);
618                 q+=GetPixelChannels(image);
619               }
620               if (SyncAuthenticPixels(image,exception) == MagickFalse)
621                 break;
622               if (image->previous == (Image *) NULL)
623                 {
624                   status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
625                     y,image->rows);
626                   if (status == MagickFalse)
627                     break;
628                 }
629             }
630             (void) SyncImage(image,exception);
631           }
632         else
633           {
634             /*
635               Image has a matte channel-- promote to DirectClass.
636             */
637             for (y=0; y < (ssize_t) image->rows; y++)
638             {
639               q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
640               if (q == (Quantum *) NULL)
641                 break;
642               for (x=0; x < (ssize_t) image->columns; x++)
643               {
644                 ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
645                 SetPixelRed(image,ClampToQuantum(image->colormap[(ssize_t)
646                   index].red),q);
647                 ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
648                 SetPixelGreen(image,ClampToQuantum(image->colormap[(ssize_t)
649                   index].green),q);
650                 ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
651                 SetPixelBlue(image,ClampToQuantum(image->colormap[(ssize_t)
652                   index].blue),q);
653                 SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
654                 q+=GetPixelChannels(image);
655               }
656               if (x < (ssize_t) image->columns)
657                 break;
658               if (SyncAuthenticPixels(image,exception) == MagickFalse)
659                 break;
660               if (image->previous == (Image *) NULL)
661                 {
662                   status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
663                     y,image->rows);
664                   if (status == MagickFalse)
665                     break;
666                 }
667             }
668             image->colormap=(PixelInfo *) RelinquishMagickMemory(
669               image->colormap);
670             image->storage_class=DirectClass;
671             image->colors=0;
672           }
673       }
674     if (number_colormaps != 0)
675       colormap=(unsigned char *) RelinquishMagickMemory(colormap);
676     pixel_info=RelinquishVirtualMemory(pixel_info);
677     if (EOFBlob(image) != MagickFalse)
678       {
679         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
680           image->filename);
681         break;
682       }
683     /*
684       Proceed to next image.
685     */
686     if (image_info->number_scenes != 0)
687       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
688         break;
689     (void) ReadBlobByte(image);
690     count=ReadBlob(image,2,(unsigned char *) magick);
691     if ((count != 0) && (memcmp(magick,"\122\314",2) == 0))
692       {
693         /*
694           Allocate next image structure.
695         */
696         AcquireNextImage(image_info,image,exception);
697         if (GetNextImageInList(image) == (Image *) NULL)
698           {
699             image=DestroyImageList(image);
700             return((Image *) NULL);
701           }
702         image=SyncNextImageInList(image);
703         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
704           GetBlobSize(image));
705         if (status == MagickFalse)
706           break;
707       }
708   } while ((count != 0) && (memcmp(magick,"\122\314",2) == 0));
709   (void) CloseBlob(image);
710   return(GetFirstImageInList(image));
711 }
712 \f
713 /*
714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
715 %                                                                             %
716 %                                                                             %
717 %                                                                             %
718 %   R e g i s t e r R L E I m a g e                                           %
719 %                                                                             %
720 %                                                                             %
721 %                                                                             %
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 %
724 %  RegisterRLEImage() adds attributes for the RLE image format to
725 %  the list of supported formats.  The attributes include the image format
726 %  tag, a method to read and/or write the format, whether the format
727 %  supports the saving of more than one frame to the same file or blob,
728 %  whether the format supports native in-memory I/O, and a brief
729 %  description of the format.
730 %
731 %  The format of the RegisterRLEImage method is:
732 %
733 %      size_t RegisterRLEImage(void)
734 %
735 */
736 ModuleExport size_t RegisterRLEImage(void)
737 {
738   MagickInfo
739     *entry;
740
741   entry=AcquireMagickInfo("RLE","RLE","Utah Run length encoded image");
742   entry->decoder=(DecodeImageHandler *) ReadRLEImage;
743   entry->magick=(IsImageFormatHandler *) IsRLE;
744   entry->flags|=CoderDecoderSeekableStreamFlag;
745   entry->flags^=CoderAdjoinFlag;
746   (void) RegisterMagickInfo(entry);
747   return(MagickImageCoderSignature);
748 }
749 \f
750 /*
751 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
752 %                                                                             %
753 %                                                                             %
754 %                                                                             %
755 %   U n r e g i s t e r R L E I m a g e                                       %
756 %                                                                             %
757 %                                                                             %
758 %                                                                             %
759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760 %
761 %  UnregisterRLEImage() removes format registrations made by the
762 %  RLE module from the list of supported formats.
763 %
764 %  The format of the UnregisterRLEImage method is:
765 %
766 %      UnregisterRLEImage(void)
767 %
768 */
769 ModuleExport void UnregisterRLEImage(void)
770 {
771   (void) UnregisterMagickInfo("RLE");
772 }