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