]> granicus.if.org Git - imagemagick/blob - coders/dib.c
Added missing calls to xmlFreeDoc to fix memory leak reported in #1766.
[imagemagick] / coders / dib.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                            DDDD   IIIII  BBBB                               %
7 %                            D   D    I    B   B                              %
8 %                            D   D    I    BBBB                               %
9 %                            D   D    I    B   B                              %
10 %                            DDDD   IIIII  BBBB                               %
11 %                                                                             %
12 %                                                                             %
13 %                   Read/Write Windows DIB Image Format                       %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2019 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://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/attribute.h"
44 #include "MagickCore/blob.h"
45 #include "MagickCore/blob-private.h"
46 #include "MagickCore/cache.h"
47 #include "MagickCore/color.h"
48 #include "MagickCore/color-private.h"
49 #include "MagickCore/colormap.h"
50 #include "MagickCore/colormap-private.h"
51 #include "MagickCore/colorspace.h"
52 #include "MagickCore/colorspace-private.h"
53 #include "MagickCore/draw.h"
54 #include "MagickCore/exception.h"
55 #include "MagickCore/exception-private.h"
56 #include "MagickCore/geometry.h"
57 #include "MagickCore/image.h"
58 #include "MagickCore/image-private.h"
59 #include "MagickCore/list.h"
60 #include "MagickCore/log.h"
61 #include "MagickCore/magick.h"
62 #include "MagickCore/memory_.h"
63 #include "MagickCore/monitor.h"
64 #include "MagickCore/monitor-private.h"
65 #include "MagickCore/pixel-accessor.h"
66 #include "MagickCore/quantum-private.h"
67 #include "MagickCore/static.h"
68 #include "MagickCore/string_.h"
69 #include "MagickCore/module.h"
70 #include "MagickCore/transform.h"
71 \f
72 /*
73   Typedef declarations.
74 */
75 typedef struct _DIBInfo
76 {
77   unsigned int
78     size;
79
80   int
81     width,
82     height;
83
84   unsigned short
85     planes,
86     bits_per_pixel;
87
88   unsigned int
89     compression,
90     image_size,
91     x_pixels,
92     y_pixels,
93     number_colors,
94     colors_important;
95
96   unsigned short
97     red_mask,
98     green_mask,
99     blue_mask,
100     alpha_mask;
101
102   int
103     colorspace;
104
105   PointInfo
106     red_primary,
107     green_primary,
108     blue_primary,
109     gamma_scale;
110 } DIBInfo;
111 \f
112 /*
113   Forward declarations.
114 */
115 static MagickBooleanType
116   WriteDIBImage(const ImageInfo *,Image *,ExceptionInfo *);
117 \f
118 /*
119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120 %                                                                             %
121 %                                                                             %
122 %                                                                             %
123 %   D e c o d e I m a g e                                                     %
124 %                                                                             %
125 %                                                                             %
126 %                                                                             %
127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128 %
129 %  DecodeImage unpacks the packed image pixels into runlength-encoded
130 %  pixel packets.
131 %
132 %  The format of the DecodeImage method is:
133 %
134 %      MagickBooleanType DecodeImage(Image *image,
135 %        const MagickBooleanType compression,unsigned char *pixels,
136 %        const size_t number_pixels)
137 %
138 %  A description of each parameter follows:
139 %
140 %    o image: the address of a structure of type Image.
141 %
142 %    o compression:  A value of 1 means the compressed pixels are runlength
143 %      encoded for a 256-color bitmap.  A value of 2 means a 16-color bitmap.
144 %
145 %    o pixels:  The address of a byte (8 bits) array of pixel data created by
146 %      the decoding process.
147 %
148 %    o number_pixels:  the number of pixels.
149 %
150 */
151 static MagickBooleanType DecodeImage(Image *image,
152   const MagickBooleanType compression,unsigned char *pixels,
153   const size_t number_pixels)
154 {
155 #if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
156 #define BI_RGB  0
157 #define BI_RLE8  1
158 #define BI_RLE4  2
159 #define BI_BITFIELDS  3
160 #undef BI_JPEG
161 #define BI_JPEG  4
162 #undef BI_PNG
163 #define BI_PNG  5
164 #endif
165
166   int
167     byte,
168     count;
169
170   ssize_t
171     y;
172
173   register ssize_t
174     i,
175     x;
176
177   register unsigned char
178     *p,
179     *q;
180
181   assert(image != (Image *) NULL);
182   assert(image->signature == MagickCoreSignature);
183   if (image->debug != MagickFalse)
184     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
185   assert(pixels != (unsigned char *) NULL);
186   (void) memset(pixels,0,number_pixels*sizeof(*pixels));
187   byte=0;
188   x=0;
189   p=pixels;
190   q=pixels+number_pixels;
191   for (y=0; y < (ssize_t) image->rows; )
192   {
193     MagickBooleanType
194       status;
195
196     if ((p < pixels) || (p >= q))
197       break;
198     count=ReadBlobByte(image);
199     if (count == EOF)
200       break;
201     if (count > 0)
202       {
203         /*
204           Encoded mode.
205         */
206         count=(int) MagickMin((size_t) count,(size_t) (q-p));
207         byte=ReadBlobByte(image);
208         if (byte == EOF)
209           break;
210         if (compression == BI_RLE8)
211           {
212             for (i=0; i < (ssize_t) count; i++)
213               *p++=(unsigned char) byte;
214           }
215         else
216           {
217             for (i=0; i < (ssize_t) count; i++)
218               *p++=(unsigned char)
219                 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
220           }
221         x+=count;
222       }
223     else
224       {
225         /*
226           Escape mode.
227         */
228         count=ReadBlobByte(image);
229         if (count == EOF)
230           break;
231         if (count == 0x01)
232           return(MagickTrue);
233         switch (count)
234         {
235           case 0x00:
236           {
237             /*
238               End of line.
239             */
240             x=0;
241             y++;
242             p=pixels+y*image->columns;
243             break;
244           }
245           case 0x02:
246           {
247             /*
248               Delta mode.
249             */
250             x+=ReadBlobByte(image);
251             y+=ReadBlobByte(image);
252             p=pixels+y*image->columns+x;
253             break;
254           }
255           default:
256           {
257             /*
258               Absolute mode.
259             */
260             count=(int) MagickMin((size_t) count,(size_t) (q-p));
261             if (compression == BI_RLE8)
262               for (i=0; i < (ssize_t) count; i++)
263               {
264                 byte=ReadBlobByte(image);
265                 if (byte == EOF)
266                   break;
267                 *p++=(unsigned char) byte;
268               }
269             else
270               for (i=0; i < (ssize_t) count; i++)
271               {
272                 if ((i & 0x01) == 0)
273                   {
274                     byte=ReadBlobByte(image);
275                     if (byte == EOF)
276                       break;
277                   }
278                 *p++=(unsigned char)
279                   ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
280               }
281             x+=count;
282             /*
283               Read pad byte.
284             */
285             if (compression == BI_RLE8)
286               {
287                 if ((count & 0x01) != 0)
288                   if (ReadBlobByte(image) == EOF)
289                     break;
290               }
291             else
292               if (((count & 0x03) == 1) || ((count & 0x03) == 2))
293                 if (ReadBlobByte(image) == EOF)
294                   break;
295             break;
296           }
297         }
298       }
299     status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
300       image->rows);
301     if (status == MagickFalse)
302       break;
303   }
304   (void) ReadBlobByte(image);  /* end of line */
305   (void) ReadBlobByte(image);
306   return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
307 }
308 \f
309 /*
310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311 %                                                                             %
312 %                                                                             %
313 %                                                                             %
314 %   E n c o d e I m a g e                                                     %
315 %                                                                             %
316 %                                                                             %
317 %                                                                             %
318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319 %
320 %  EncodeImage compresses pixels using a runlength encoded format.
321 %
322 %  The format of the EncodeImage method is:
323 %
324 %    static MagickBooleanType EncodeImage(Image *image,
325 %      const size_t bytes_per_line,const unsigned char *pixels,
326 %      unsigned char *compressed_pixels)
327 %
328 %  A description of each parameter follows:
329 %
330 %    o image:  The image.
331 %
332 %    o bytes_per_line: the number of bytes in a scanline of compressed pixels
333 %
334 %    o pixels:  The address of a byte (8 bits) array of pixel data created by
335 %      the compression process.
336 %
337 %    o compressed_pixels:  The address of a byte (8 bits) array of compressed
338 %      pixel data.
339 %
340 */
341 static size_t EncodeImage(Image *image,const size_t bytes_per_line,
342   const unsigned char *pixels,unsigned char *compressed_pixels)
343 {
344   ssize_t
345     y;
346
347   register const unsigned char
348     *p;
349
350   register ssize_t
351     i,
352     x;
353
354   register unsigned char
355     *q;
356
357   /*
358     Runlength encode pixels.
359   */
360   assert(image != (Image *) NULL);
361   assert(image->signature == MagickCoreSignature);
362   if (image->debug != MagickFalse)
363     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
364   assert(pixels != (const unsigned char *) NULL);
365   assert(compressed_pixels != (unsigned char *) NULL);
366   p=pixels;
367   q=compressed_pixels;
368   i=0;
369   for (y=0; y < (ssize_t) image->rows; y++)
370   {
371     for (x=0; x < (ssize_t) bytes_per_line; x+=i)
372     {
373       /*
374         Determine runlength.
375       */
376       for (i=1; ((x+i) < (ssize_t) bytes_per_line); i++)
377         if ((*(p+i) != *p) || (i == 255))
378           break;
379       *q++=(unsigned char) i;
380       *q++=(*p);
381       p+=i;
382     }
383     /*
384       End of line.
385     */
386     *q++=0x00;
387     *q++=0x00;
388     if (SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,image->rows) == MagickFalse)
389       break;
390   }
391   /*
392     End of bitmap.
393   */
394   *q++=0;
395   *q++=0x01;
396   return((size_t) (q-compressed_pixels));
397 }
398 \f
399 /*
400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
401 %                                                                             %
402 %                                                                             %
403 %                                                                             %
404 %   I s D I B                                                                 %
405 %                                                                             %
406 %                                                                             %
407 %                                                                             %
408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409 %
410 %  IsDIB() returns MagickTrue if the image format type, identified by the
411 %  magick string, is DIB.
412 %
413 %  The format of the IsDIB method is:
414 %
415 %      MagickBooleanType IsDIB(const unsigned char *magick,const size_t length)
416 %
417 %  A description of each parameter follows:
418 %
419 %    o magick: compare image format pattern against these bytes.
420 %
421 %    o length: Specifies the length of the magick string.
422 %
423 */
424 static MagickBooleanType IsDIB(const unsigned char *magick,const size_t length)
425 {
426   if (length < 2)
427     return(MagickFalse);
428   if (memcmp(magick,"\050\000",2) == 0)
429     return(MagickTrue);
430   return(MagickFalse);
431 }
432 \f
433 /*
434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435 %                                                                             %
436 %                                                                             %
437 %                                                                             %
438 %   R e a d D I B I m a g e                                                   %
439 %                                                                             %
440 %                                                                             %
441 %                                                                             %
442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443 %
444 %  ReadDIBImage() reads a Microsoft Windows bitmap image file and
445 %  returns it.  It allocates the memory necessary for the new Image structure
446 %  and returns a pointer to the new image.
447 %
448 %  The format of the ReadDIBImage method is:
449 %
450 %      image=ReadDIBImage(image_info)
451 %
452 %  A description of each parameter follows:
453 %
454 %    o image_info: the image info.
455 %
456 %    o exception: return any errors or warnings in this structure.
457 %
458 */
459 static Image *ReadDIBImage(const ImageInfo *image_info,ExceptionInfo *exception)
460 {
461   DIBInfo
462     dib_info;
463
464   Image
465     *image;
466
467   MagickBooleanType
468     status;
469
470   MemoryInfo
471     *pixel_info;
472
473   Quantum
474     index;
475
476   register ssize_t
477     x;
478
479   register Quantum
480     *q;
481
482   register ssize_t
483     i;
484
485   register unsigned char
486     *p;
487
488   size_t
489     bytes_per_line,
490     length;
491
492   ssize_t
493     bit,
494     count,
495     y;
496
497
498   unsigned char
499     *pixels;
500
501   /*
502     Open image file.
503   */
504   assert(image_info != (const ImageInfo *) NULL);
505   assert(image_info->signature == MagickCoreSignature);
506   if (image_info->debug != MagickFalse)
507     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
508       image_info->filename);
509   assert(exception != (ExceptionInfo *) NULL);
510   assert(exception->signature == MagickCoreSignature);
511   image=AcquireImage(image_info,exception);
512   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
513   if (status == MagickFalse)
514     {
515       image=DestroyImageList(image);
516       return((Image *) NULL);
517     }
518   /*
519     Determine if this a DIB file.
520   */
521   (void) memset(&dib_info,0,sizeof(dib_info));
522   dib_info.size=ReadBlobLSBLong(image);
523   if (dib_info.size != 40)
524     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
525   /*
526     Microsoft Windows 3.X DIB image file.
527   */
528   dib_info.width=ReadBlobLSBSignedLong(image);
529   dib_info.height=ReadBlobLSBSignedLong(image);
530   dib_info.planes=ReadBlobLSBShort(image);
531   dib_info.bits_per_pixel=ReadBlobLSBShort(image);
532   if (dib_info.bits_per_pixel > 32)
533     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
534   dib_info.compression=ReadBlobLSBLong(image);
535   dib_info.image_size=ReadBlobLSBLong(image);
536   dib_info.x_pixels=ReadBlobLSBLong(image);
537   dib_info.y_pixels=ReadBlobLSBLong(image);
538   dib_info.number_colors=ReadBlobLSBLong(image);
539   dib_info.colors_important=ReadBlobLSBLong(image);
540   if ((dib_info.bits_per_pixel != 1) && (dib_info.bits_per_pixel != 4) &&
541       (dib_info.bits_per_pixel != 8) && (dib_info.bits_per_pixel != 16) &&
542       (dib_info.bits_per_pixel != 24) && (dib_info.bits_per_pixel != 32))
543     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
544   if ((dib_info.compression == BI_BITFIELDS) &&
545       ((dib_info.bits_per_pixel == 16) || (dib_info.bits_per_pixel == 32)))
546     {
547       dib_info.red_mask=(unsigned short) ReadBlobLSBLong(image);
548       dib_info.green_mask=(unsigned short) ReadBlobLSBLong(image);
549       dib_info.blue_mask=(unsigned short) ReadBlobLSBLong(image);
550     }
551   if (EOFBlob(image) != MagickFalse)
552     ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
553   if (dib_info.width <= 0)
554     ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
555   if (dib_info.height == 0)
556     ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
557   if (dib_info.planes != 1)
558     ThrowReaderException(CorruptImageError,"StaticPlanesValueNotEqualToOne");
559   if ((dib_info.bits_per_pixel != 1) && (dib_info.bits_per_pixel != 4) &&
560       (dib_info.bits_per_pixel != 8) && (dib_info.bits_per_pixel != 16) &&
561       (dib_info.bits_per_pixel != 24) && (dib_info.bits_per_pixel != 32))
562     ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
563   if ((dib_info.bits_per_pixel < 16) &&
564       (dib_info.number_colors > (unsigned int) (1UL << dib_info.bits_per_pixel)))
565     ThrowReaderException(CorruptImageError,"UnrecognizedNumberOfColors");
566   if ((dib_info.compression == 1) && (dib_info.bits_per_pixel != 8))
567     ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
568   if ((dib_info.compression == 2) && (dib_info.bits_per_pixel != 4))
569     ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
570   if ((dib_info.compression == 3) && (dib_info.bits_per_pixel < 16))
571     ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");
572   switch (dib_info.compression)
573   {
574     case BI_RGB:
575     case BI_RLE8:
576     case BI_RLE4:
577     case BI_BITFIELDS:
578       break;
579     case BI_JPEG:
580       ThrowReaderException(CoderError,"JPEGCompressNotSupported");
581     case BI_PNG:
582       ThrowReaderException(CoderError,"PNGCompressNotSupported");
583     default:
584       ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression");
585   }
586   image->columns=(size_t) MagickAbsoluteValue((ssize_t) dib_info.width);
587   image->rows=(size_t) MagickAbsoluteValue((ssize_t) dib_info.height);
588   image->depth=8;
589   image->alpha_trait=dib_info.bits_per_pixel == 32 ? BlendPixelTrait :
590     UndefinedPixelTrait;
591   if ((dib_info.number_colors > 256) || (dib_info.colors_important > 256))
592     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
593   if ((dib_info.number_colors != 0) && (dib_info.bits_per_pixel > 8))
594     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
595   if ((dib_info.image_size != 0U) && (dib_info.image_size > GetBlobSize(image)))
596     ThrowReaderException(CorruptImageError,"UnexpectedEndOfFile");
597   if ((dib_info.number_colors != 0) || (dib_info.bits_per_pixel < 8))
598     {
599       size_t
600         one;
601
602       image->storage_class=PseudoClass;
603       image->colors=dib_info.number_colors;
604       one=1;
605       if (image->colors == 0)
606         image->colors=one << dib_info.bits_per_pixel;
607     }
608   if (image_info->size)
609     {
610       RectangleInfo
611         geometry;
612
613       MagickStatusType
614         flags;
615
616       flags=ParseAbsoluteGeometry(image_info->size,&geometry);
617       if (flags & WidthValue)
618         if ((geometry.width != 0) && (geometry.width < image->columns))
619           image->columns=geometry.width;
620       if (flags & HeightValue)
621         if ((geometry.height != 0) && (geometry.height < image->rows))
622           image->rows=geometry.height;
623     }
624   status=SetImageExtent(image,image->columns,image->rows,exception);
625   if (status == MagickFalse)
626     return(DestroyImageList(image));
627   if (image->storage_class == PseudoClass)
628     {
629       size_t
630         packet_size;
631
632       unsigned char
633         *dib_colormap;
634
635       /*
636         Read DIB raster colormap.
637       */
638       if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
639         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
640       length=(size_t) image->colors;
641       dib_colormap=(unsigned char *) AcquireQuantumMemory(length,
642         4*sizeof(*dib_colormap));
643       if (dib_colormap == (unsigned char *) NULL)
644         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
645       packet_size=4;
646       count=ReadBlob(image,packet_size*image->colors,dib_colormap);
647       if (count != (ssize_t) (packet_size*image->colors))
648         {
649           dib_colormap=(unsigned char *) RelinquishMagickMemory(dib_colormap);
650           ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
651         }
652       p=dib_colormap;
653       for (i=0; i < (ssize_t) image->colors; i++)
654       {
655         image->colormap[i].blue=(MagickRealType) ScaleCharToQuantum(*p++);
656         image->colormap[i].green=(MagickRealType) ScaleCharToQuantum(*p++);
657         image->colormap[i].red=(MagickRealType) ScaleCharToQuantum(*p++);
658         if (packet_size == 4)
659           p++;
660       }
661       dib_colormap=(unsigned char *) RelinquishMagickMemory(dib_colormap);
662     }
663   /*
664     Read image data.
665   */
666   if (dib_info.compression == BI_RLE4)
667     dib_info.bits_per_pixel<<=1;
668   bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
669   length=bytes_per_line*image->rows;
670   if ((MagickSizeType) length > (256*GetBlobSize(image)))
671     ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
672   pixel_info=AcquireVirtualMemory(image->rows,MagickMax(bytes_per_line,
673     image->columns+256UL)*sizeof(*pixels));
674   if (pixel_info == (MemoryInfo *) NULL)
675     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
676   pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
677   if ((dib_info.compression == BI_RGB) ||
678       (dib_info.compression == BI_BITFIELDS))
679     {
680       count=ReadBlob(image,length,pixels);
681       if (count != (ssize_t) (length))
682         {
683           pixel_info=RelinquishVirtualMemory(pixel_info);
684           ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
685         }
686     }
687   else
688     {
689       /*
690         Convert run-length encoded raster pixels.
691       */
692       status=DecodeImage(image,dib_info.compression ? MagickTrue : MagickFalse,
693         pixels,image->columns*image->rows);
694       if (status == MagickFalse)
695         {
696           pixel_info=RelinquishVirtualMemory(pixel_info);
697           ThrowReaderException(CorruptImageError,
698             "UnableToRunlengthDecodeImage");
699         }
700     }
701   /*
702     Initialize image structure.
703   */
704   image->units=PixelsPerCentimeterResolution;
705   image->resolution.x=(double) dib_info.x_pixels/100.0;
706   image->resolution.y=(double) dib_info.y_pixels/100.0;
707   /*
708     Convert DIB raster image to pixel packets.
709   */
710   switch (dib_info.bits_per_pixel)
711   {
712     case 1:
713     {
714       /*
715         Convert bitmap scanline.
716       */
717       for (y=(ssize_t) image->rows-1; y >= 0; y--)
718       {
719         p=pixels+(image->rows-y-1)*bytes_per_line;
720         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
721         if (q == (Quantum *) NULL)
722           break;
723         for (x=0; x < ((ssize_t) image->columns-7); x+=8)
724         {
725           for (bit=0; bit < 8; bit++)
726           {
727             index=(Quantum) ((*p) & (0x80 >> bit) ? 0x01 : 0x00);
728             SetPixelIndex(image,index,q);
729             q+=GetPixelChannels(image);
730           }
731           p++;
732         }
733         if ((image->columns % 8) != 0)
734           {
735             for (bit=0; bit < (ssize_t) (image->columns % 8); bit++)
736             {
737               index=(Quantum) ((*p) & (0x80 >> bit) ? 0x01 : 0x00);
738               SetPixelIndex(image,index,q);
739               q+=GetPixelChannels(image);
740             }
741             p++;
742           }
743         if (SyncAuthenticPixels(image,exception) == MagickFalse)
744           break;
745         if (image->previous == (Image *) NULL)
746           {
747             status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
748               image->rows-y-1,image->rows);
749             if (status == MagickFalse)
750               break;
751           }
752       }
753       (void) SyncImage(image,exception);
754       break;
755     }
756     case 4:
757     {
758       /*
759         Convert PseudoColor scanline.
760       */
761       for (y=(ssize_t) image->rows-1; y >= 0; y--)
762       {
763         p=pixels+(image->rows-y-1)*bytes_per_line;
764         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
765         if (q == (Quantum *) NULL)
766           break;
767         for (x=0; x < ((ssize_t) image->columns-1); x+=2)
768         {
769           index=(Quantum) ConstrainColormapIndex(image,(ssize_t) (*p >> 4) &
770             0xf,exception);
771           SetPixelIndex(image,index,q);
772           q+=GetPixelChannels(image);
773           index=(Quantum) ConstrainColormapIndex(image,(ssize_t) *p & 0xf,
774             exception);
775           SetPixelIndex(image,index,q);
776           p++;
777           q+=GetPixelChannels(image);
778         }
779         if ((image->columns % 2) != 0)
780           {
781             index=(Quantum) ConstrainColormapIndex(image,(ssize_t) (*p >> 4) &
782               0xf,exception);
783             SetPixelIndex(image,index,q);
784             q+=GetPixelChannels(image);
785             p++;
786           }
787         if (SyncAuthenticPixels(image,exception) == MagickFalse)
788           break;
789         if (image->previous == (Image *) NULL)
790           {
791             status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
792               image->rows-y-1,image->rows);
793             if (status == MagickFalse)
794               break;
795           }
796       }
797       (void) SyncImage(image,exception);
798       break;
799     }
800     case 8:
801     {
802       /*
803         Convert PseudoColor scanline.
804       */
805       if ((dib_info.compression == BI_RLE8) ||
806           (dib_info.compression == BI_RLE4))
807         bytes_per_line=image->columns;
808       for (y=(ssize_t) image->rows-1; y >= 0; y--)
809       {
810         p=pixels+(image->rows-y-1)*bytes_per_line;
811         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
812         if (q == (Quantum *) NULL)
813           break;
814         for (x=0; x < (ssize_t) image->columns; x++)
815         {
816           index=(Quantum) ConstrainColormapIndex(image,(ssize_t) *p,exception);
817           SetPixelIndex(image,index,q);
818           p++;
819           q+=GetPixelChannels(image);
820         }
821         if (SyncAuthenticPixels(image,exception) == MagickFalse)
822           break;
823         if (image->previous == (Image *) NULL)
824           {
825             status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
826               image->rows-y-1,image->rows);
827             if (status == MagickFalse)
828               break;
829           }
830       }
831       (void) SyncImage(image,exception);
832       break;
833     }
834     case 16:
835     {
836       unsigned short
837         word;
838
839       /*
840         Convert PseudoColor scanline.
841       */
842       image->storage_class=DirectClass;
843       if (dib_info.compression == BI_RLE8)
844         bytes_per_line=2*image->columns;
845       for (y=(ssize_t) image->rows-1; y >= 0; y--)
846       {
847         p=pixels+(image->rows-y-1)*bytes_per_line;
848         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
849         if (q == (Quantum *) NULL)
850           break;
851         for (x=0; x < (ssize_t) image->columns; x++)
852         {
853           word=(*p++);
854           word|=(*p++ << 8);
855           if (dib_info.red_mask == 0)
856             {
857               SetPixelRed(image,ScaleCharToQuantum(ScaleColor5to8(
858                 (unsigned char) ((word >> 10) & 0x1f))),q);
859               SetPixelGreen(image,ScaleCharToQuantum(ScaleColor5to8(
860                 (unsigned char) ((word >> 5) & 0x1f))),q);
861               SetPixelBlue(image,ScaleCharToQuantum(ScaleColor5to8(
862                 (unsigned char) (word & 0x1f))),q);
863             }
864           else
865             {
866               SetPixelRed(image,ScaleCharToQuantum(ScaleColor5to8(
867                 (unsigned char) ((word >> 11) & 0x1f))),q);
868               SetPixelGreen(image,ScaleCharToQuantum(ScaleColor6to8(
869                 (unsigned char) ((word >> 5) & 0x3f))),q);
870               SetPixelBlue(image,ScaleCharToQuantum(ScaleColor5to8(
871                 (unsigned char) (word & 0x1f))),q);
872             }
873           q+=GetPixelChannels(image);
874         }
875         if (SyncAuthenticPixels(image,exception) == MagickFalse)
876           break;
877         if (image->previous == (Image *) NULL)
878           {
879             status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
880               image->rows-y-1,image->rows);
881             if (status == MagickFalse)
882               break;
883           }
884       }
885       break;
886     }
887     case 24:
888     case 32:
889     {
890       /*
891         Convert DirectColor scanline.
892       */
893       for (y=(ssize_t) image->rows-1; y >= 0; y--)
894       {
895         p=pixels+(image->rows-y-1)*bytes_per_line;
896         q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
897         if (q == (Quantum *) NULL)
898           break;
899         for (x=0; x < (ssize_t) image->columns; x++)
900         {
901           SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
902           SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
903           SetPixelRed(image,ScaleCharToQuantum(*p++),q);
904           if (image->alpha_trait != UndefinedPixelTrait)
905             SetPixelAlpha(image,ScaleCharToQuantum(*p++),q);
906           q+=GetPixelChannels(image);
907         }
908         if (SyncAuthenticPixels(image,exception) == MagickFalse)
909           break;
910         if (image->previous == (Image *) NULL)
911           {
912             status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
913               image->rows-y-1,image->rows);
914             if (status == MagickFalse)
915               break;
916           }
917       }
918       break;
919     }
920     default:
921       pixel_info=RelinquishVirtualMemory(pixel_info);
922       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
923   }
924   pixel_info=RelinquishVirtualMemory(pixel_info);
925   if (strcmp(image_info->magick,"ICODIB") == 0)
926     {
927       int
928         c;
929
930       /*
931         Handle ICO mask.
932       */
933       for (y=0; y < (ssize_t) image->rows; y++)
934       {
935         register ssize_t
936           x;
937
938         register Quantum
939           *magick_restrict q;
940
941         q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
942         if (q == (Quantum *) NULL)
943           break;
944         for (x=0; x < ((ssize_t) image->columns-7); x+=8)
945         {
946           c=ReadBlobByte(image);
947           for (bit=0; bit < 8; bit++)
948           {
949             if (c & (0x80 >> bit))
950               image->alpha_trait=BlendPixelTrait;
951             SetPixelAlpha(image,c & (0x80 >> bit) ? TransparentAlpha :
952               OpaqueAlpha,q+x*GetPixelChannels(image)+bit);
953           }
954         }
955         if ((image->columns % 8) != 0)
956           {
957             c=ReadBlobByte(image);
958             for (bit=0; bit < (ssize_t) (image->columns % 8); bit++)
959             {
960               if (c & (0x80 >> bit))
961                 image->alpha_trait=BlendPixelTrait;
962               SetPixelAlpha(image,c & (0x80 >> bit) ? TransparentAlpha :
963                 OpaqueAlpha,q+x*GetPixelChannels(image)+bit);
964             }
965           }
966         if (image->columns % 32)
967           for (x=0; x < (ssize_t) ((32-(image->columns % 32))/8); x++)
968             c=ReadBlobByte(image);
969         if (SyncAuthenticPixels(image,exception) == MagickFalse)
970           break;
971       }
972     }
973   if (EOFBlob(image) != MagickFalse)
974     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
975       image->filename);
976   if (dib_info.height < 0)
977     {
978       Image
979         *flipped_image;
980
981       /*
982         Correct image orientation.
983       */
984       flipped_image=FlipImage(image,exception);
985       if (flipped_image != (Image *) NULL)
986         {
987           DuplicateBlob(flipped_image,image);
988           image=DestroyImage(image);
989           image=flipped_image;
990         }
991     }
992   (void) CloseBlob(image);
993   return(GetFirstImageInList(image));
994 }
995 \f
996 /*
997 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
998 %                                                                             %
999 %                                                                             %
1000 %                                                                             %
1001 %   R e g i s t e r D I B I m a g e                                           %
1002 %                                                                             %
1003 %                                                                             %
1004 %                                                                             %
1005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1006 %
1007 %  RegisterDIBImage() adds attributes for the DIB image format to
1008 %  the list of supported formats.  The attributes include the image format
1009 %  tag, a method to read and/or write the format, whether the format
1010 %  supports the saving of more than one frame to the same file or blob,
1011 %  whether the format supports native in-memory I/O, and a brief
1012 %  description of the format.
1013 %
1014 %  The format of the RegisterDIBImage method is:
1015 %
1016 %      size_t RegisterDIBImage(void)
1017 %
1018 */
1019 ModuleExport size_t RegisterDIBImage(void)
1020 {
1021   MagickInfo
1022     *entry;
1023
1024   entry=AcquireMagickInfo("DIB","DIB",
1025     "Microsoft Windows 3.X Packed Device-Independent Bitmap");
1026   entry->decoder=(DecodeImageHandler *) ReadDIBImage;
1027   entry->encoder=(EncodeImageHandler *) WriteDIBImage;
1028   entry->magick=(IsImageFormatHandler *) IsDIB;
1029   entry->flags^=CoderAdjoinFlag;
1030   entry->flags|=CoderStealthFlag;
1031   entry->flags|=CoderDecoderSeekableStreamFlag;
1032   (void) RegisterMagickInfo(entry);
1033   entry=AcquireMagickInfo("DIB","ICODIB",
1034     "Microsoft Windows 3.X Packed Device-Independent Bitmap");
1035   entry->decoder=(DecodeImageHandler *) ReadDIBImage;
1036   entry->magick=(IsImageFormatHandler *) IsDIB;
1037   entry->flags^=CoderAdjoinFlag;
1038   entry->flags|=CoderStealthFlag;
1039   entry->flags|=CoderDecoderSeekableStreamFlag;
1040   (void) RegisterMagickInfo(entry);
1041   return(MagickImageCoderSignature);
1042 }
1043 \f
1044 /*
1045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1046 %                                                                             %
1047 %                                                                             %
1048 %                                                                             %
1049 %   U n r e g i s t e r D I B I m a g e                                       %
1050 %                                                                             %
1051 %                                                                             %
1052 %                                                                             %
1053 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1054 %
1055 %  UnregisterDIBImage() removes format registrations made by the
1056 %  DIB module from the list of supported formats.
1057 %
1058 %  The format of the UnregisterDIBImage method is:
1059 %
1060 %      UnregisterDIBImage(void)
1061 %
1062 */
1063 ModuleExport void UnregisterDIBImage(void)
1064 {
1065   (void) UnregisterMagickInfo("ICODIB");
1066   (void) UnregisterMagickInfo("DIB");
1067 }
1068 \f
1069 /*
1070 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1071 %                                                                             %
1072 %                                                                             %
1073 %                                                                             %
1074 %   W r i t e D I B I m a g e                                                 %
1075 %                                                                             %
1076 %                                                                             %
1077 %                                                                             %
1078 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1079 %
1080 %  WriteDIBImage() writes an image in Microsoft Windows bitmap encoded
1081 %  image format.
1082 %
1083 %  The format of the WriteDIBImage method is:
1084 %
1085 %      MagickBooleanType WriteDIBImage(const ImageInfo *image_info,
1086 %        Image *image,ExceptionInfo *exception)
1087 %
1088 %  A description of each parameter follows.
1089 %
1090 %    o image_info: the image info.
1091 %
1092 %    o image:  The image.
1093 %
1094 %    o exception: return any errors or warnings in this structure.
1095 %
1096 */
1097 static MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image,
1098   ExceptionInfo *exception)
1099 {
1100   DIBInfo
1101     dib_info;
1102
1103   MagickBooleanType
1104     status;
1105
1106   register const Quantum
1107     *p;
1108
1109   register ssize_t
1110     i,
1111     x;
1112
1113   register unsigned char
1114     *q;
1115
1116   size_t
1117     bytes_per_line;
1118
1119   ssize_t
1120     y;
1121
1122   unsigned char
1123     *dib_data,
1124     *pixels;
1125
1126   /*
1127     Open output image file.
1128   */
1129   assert(image_info != (const ImageInfo *) NULL);
1130   assert(image_info->signature == MagickCoreSignature);
1131   assert(image != (Image *) NULL);
1132   assert(image->signature == MagickCoreSignature);
1133   if (image->debug != MagickFalse)
1134     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1135   assert(exception != (ExceptionInfo *) NULL);
1136   assert(exception->signature == MagickCoreSignature);
1137   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1138   if (status == MagickFalse)
1139     return(status);
1140   if (((image->columns << 3) != (int) (image->columns << 3)) ||
1141       ((image->rows << 3) != (int) (image->rows << 3)))
1142     ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1143   /*
1144     Initialize DIB raster file header.
1145   */
1146   (void) TransformImageColorspace(image,sRGBColorspace,exception);
1147   if (image->storage_class == DirectClass)
1148     {
1149       /*
1150         Full color DIB raster.
1151       */
1152       dib_info.number_colors=0;
1153       dib_info.bits_per_pixel=(unsigned short) (image->alpha_trait ? 32 : 24);
1154     }
1155   else
1156     {
1157       /*
1158         Colormapped DIB raster.
1159       */
1160       dib_info.bits_per_pixel=8;
1161       if (image_info->depth > 8)
1162         dib_info.bits_per_pixel=16;
1163       if (SetImageMonochrome(image,exception) != MagickFalse)
1164         dib_info.bits_per_pixel=1;
1165       dib_info.number_colors=(unsigned int) (dib_info.bits_per_pixel == 16 ? 0 :
1166         (1UL << dib_info.bits_per_pixel));
1167     }
1168   bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
1169   dib_info.size=40;
1170   dib_info.width=(int) image->columns;
1171   dib_info.height=(int) image->rows;
1172   dib_info.planes=1;
1173   dib_info.compression=(unsigned int) (dib_info.bits_per_pixel == 16 ?
1174     BI_BITFIELDS : BI_RGB);
1175   dib_info.image_size=(unsigned int) (bytes_per_line*image->rows);
1176   dib_info.x_pixels=75*39;
1177   dib_info.y_pixels=75*39;
1178   switch (image->units)
1179   {
1180     case UndefinedResolution:
1181     case PixelsPerInchResolution:
1182     {
1183       dib_info.x_pixels=(unsigned int) (100.0*image->resolution.x/2.54);
1184       dib_info.y_pixels=(unsigned int) (100.0*image->resolution.y/2.54);
1185       break;
1186     }
1187     case PixelsPerCentimeterResolution:
1188     {
1189       dib_info.x_pixels=(unsigned int) (100.0*image->resolution.x);
1190       dib_info.y_pixels=(unsigned int) (100.0*image->resolution.y);
1191       break;
1192     }
1193   }
1194   dib_info.colors_important=dib_info.number_colors;
1195   /*
1196     Convert MIFF to DIB raster pixels.
1197   */
1198   pixels=(unsigned char *) AcquireQuantumMemory(image->rows,MagickMax(
1199     bytes_per_line,image->columns+256UL)*sizeof(*pixels));
1200   if (pixels == (unsigned char *) NULL)
1201     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1202   (void) memset(pixels,0,dib_info.image_size);
1203   switch (dib_info.bits_per_pixel)
1204   {
1205     case 1:
1206     {
1207       register unsigned char
1208         bit,
1209         byte;
1210
1211       /*
1212         Convert PseudoClass image to a DIB monochrome image.
1213       */
1214       for (y=0; y < (ssize_t) image->rows; y++)
1215       {
1216         p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1217         if (p == (const Quantum *) NULL)
1218           break;
1219         q=pixels+(image->rows-y-1)*bytes_per_line;
1220         bit=0;
1221         byte=0;
1222         for (x=0; x < (ssize_t) image->columns; x++)
1223         {
1224           byte<<=1;
1225           byte|=GetPixelIndex(image,p) != 0 ? 0x01 : 0x00;
1226           bit++;
1227           if (bit == 8)
1228             {
1229               *q++=byte;
1230               bit=0;
1231               byte=0;
1232             }
1233            p+=GetPixelChannels(image);
1234          }
1235          if (bit != 0)
1236            {
1237              *q++=(unsigned char) (byte << (8-bit));
1238              x++;
1239            }
1240         for (x=(ssize_t) (image->columns+7)/8; x < (ssize_t) bytes_per_line; x++)
1241           *q++=0x00;
1242         status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1243           image->rows);
1244         if (status == MagickFalse)
1245           break;
1246       }
1247       break;
1248     }
1249     case 8:
1250     {
1251       /*
1252         Convert PseudoClass packet to DIB pixel.
1253       */
1254       for (y=0; y < (ssize_t) image->rows; y++)
1255       {
1256         p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1257         if (p == (const Quantum *) NULL)
1258           break;
1259         q=pixels+(image->rows-y-1)*bytes_per_line;
1260         for (x=0; x < (ssize_t) image->columns; x++)
1261         {
1262           *q++=(unsigned char) GetPixelIndex(image,p);
1263           p+=GetPixelChannels(image);
1264         }
1265         for ( ; x < (ssize_t) bytes_per_line; x++)
1266           *q++=0x00;
1267         status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1268           image->rows);
1269         if (status == MagickFalse)
1270           break;
1271       }
1272       break;
1273     }
1274     case 16:
1275     {
1276       unsigned short
1277         word;
1278       /*
1279         Convert PseudoClass packet to DIB pixel.
1280       */
1281       for (y=0; y < (ssize_t) image->rows; y++)
1282       {
1283         p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1284         if (p == (const Quantum *) NULL)
1285           break;
1286         q=pixels+(image->rows-y-1)*bytes_per_line;
1287         for (x=0; x < (ssize_t) image->columns; x++)
1288         {
1289           word=(unsigned short) ((ScaleColor8to5((unsigned char)
1290             ScaleQuantumToChar(GetPixelRed(image,p))) << 11) | (ScaleColor8to6(
1291             (unsigned char) ScaleQuantumToChar(GetPixelGreen(image,p))) << 5) |
1292             (ScaleColor8to5((unsigned char) ScaleQuantumToChar((unsigned char)
1293             GetPixelBlue(image,p)) << 0)));
1294           *q++=(unsigned char)(word & 0xff);
1295           *q++=(unsigned char)(word >> 8);
1296           p+=GetPixelChannels(image);
1297         }
1298         for (x=(ssize_t) (2*image->columns); x < (ssize_t) bytes_per_line; x++)
1299           *q++=0x00;
1300         status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1301           image->rows);
1302         if (status == MagickFalse)
1303           break;
1304       }
1305       break;
1306     }
1307     case 24:
1308     case 32:
1309     {
1310       /*
1311         Convert DirectClass packet to DIB RGB pixel.
1312       */
1313       for (y=0; y < (ssize_t) image->rows; y++)
1314       {
1315         p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1316         if (p == (const Quantum *) NULL)
1317           break;
1318         q=pixels+(image->rows-y-1)*bytes_per_line;
1319         for (x=0; x < (ssize_t) image->columns; x++)
1320         {
1321           *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1322           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1323           *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1324           if (image->alpha_trait != UndefinedPixelTrait)
1325             *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
1326           p+=GetPixelChannels(image);
1327         }
1328         if (dib_info.bits_per_pixel == 24)
1329           for (x=(ssize_t) (3*image->columns); x < (ssize_t) bytes_per_line; x++)
1330             *q++=0x00;
1331         status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1332           image->rows);
1333         if (status == MagickFalse)
1334           break;
1335       }
1336       break;
1337     }
1338   }
1339   if (dib_info.bits_per_pixel == 8)
1340     if (image_info->compression != NoCompression)
1341       {
1342         size_t
1343           length;
1344
1345         /*
1346           Convert run-length encoded raster pixels.
1347         */
1348         length=2UL*(bytes_per_line+2UL)+2UL;
1349         dib_data=(unsigned char *) AcquireQuantumMemory(length,
1350           (image->rows+2UL)*sizeof(*dib_data));
1351         if (dib_data == (unsigned char *) NULL)
1352           {
1353             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1354             ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1355           }
1356         dib_info.image_size=(unsigned int) EncodeImage(image,bytes_per_line,
1357           pixels,dib_data);
1358         pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1359         pixels=dib_data;
1360         dib_info.compression = BI_RLE8;
1361       }
1362   /*
1363     Write DIB header.
1364   */
1365   (void) WriteBlobLSBLong(image,dib_info.size);
1366   (void) WriteBlobLSBLong(image,(unsigned int) dib_info.width);
1367   (void) WriteBlobLSBLong(image,(unsigned int) dib_info.height);
1368   (void) WriteBlobLSBShort(image,(unsigned short) dib_info.planes);
1369   (void) WriteBlobLSBShort(image,dib_info.bits_per_pixel);
1370   (void) WriteBlobLSBLong(image,dib_info.compression);
1371   (void) WriteBlobLSBLong(image,dib_info.image_size);
1372   (void) WriteBlobLSBLong(image,dib_info.x_pixels);
1373   (void) WriteBlobLSBLong(image,dib_info.y_pixels);
1374   (void) WriteBlobLSBLong(image,dib_info.number_colors);
1375   (void) WriteBlobLSBLong(image,dib_info.colors_important);
1376   if (image->storage_class == PseudoClass)
1377     {
1378       if (dib_info.bits_per_pixel <= 8)
1379         {
1380           unsigned char
1381             *dib_colormap;
1382
1383           /*
1384             Dump colormap to file.
1385           */
1386           dib_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
1387             (1UL << dib_info.bits_per_pixel),4*sizeof(*dib_colormap));
1388           if (dib_colormap == (unsigned char *) NULL)
1389             {
1390               pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1391               ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1392             }
1393           q=dib_colormap;
1394           for (i=0; i < (ssize_t) MagickMin(image->colors,dib_info.number_colors); i++)
1395           {
1396             *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));
1397             *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
1398             *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
1399             *q++=(Quantum) 0x0;
1400           }
1401           for ( ; i < (ssize_t) (1L << dib_info.bits_per_pixel); i++)
1402           {
1403             *q++=(Quantum) 0x0;
1404             *q++=(Quantum) 0x0;
1405             *q++=(Quantum) 0x0;
1406             *q++=(Quantum) 0x0;
1407           }
1408           (void) WriteBlob(image,(size_t) (4*(1 << dib_info.bits_per_pixel)),
1409             dib_colormap);
1410           dib_colormap=(unsigned char *) RelinquishMagickMemory(dib_colormap);
1411         }
1412       else
1413         if ((dib_info.bits_per_pixel == 16) &&
1414             (dib_info.compression == BI_BITFIELDS))
1415           {
1416             (void) WriteBlobLSBLong(image,0xf800);
1417             (void) WriteBlobLSBLong(image,0x07e0);
1418             (void) WriteBlobLSBLong(image,0x001f);
1419           }
1420     }
1421   (void) WriteBlob(image,dib_info.image_size,pixels);
1422   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1423   (void) CloseBlob(image);
1424   return(MagickTrue);
1425 }