• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 
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 
112 /*
113   Forward declarations.
114 */
115 static MagickBooleanType
116   WriteDIBImage(const ImageInfo *,Image *,ExceptionInfo *);
117 
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 */
DecodeImage(Image * image,const MagickBooleanType compression,unsigned char * pixels,const size_t number_pixels)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 
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 */
EncodeImage(Image * image,const size_t bytes_per_line,const unsigned char * pixels,unsigned char * compressed_pixels)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 
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 */
IsDIB(const unsigned char * magick,const size_t length)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 
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 */
ReadDIBImage(const ImageInfo * image_info,ExceptionInfo * exception)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       image->storage_class=DirectClass;
934       image->alpha_trait=BlendPixelTrait;
935       for (y=0; y < (ssize_t) image->rows; y++)
936       {
937         register ssize_t
938           x;
939 
940         register Quantum
941           *magick_restrict q;
942 
943         q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
944         if (q == (Quantum *) NULL)
945           break;
946         for (x=0; x < ((ssize_t) image->columns-7); x+=8)
947         {
948           c=ReadBlobByte(image);
949           for (bit=0; bit < 8; bit++)
950             SetPixelAlpha(image,c & (0x80 >> bit) ? TransparentAlpha :
951               OpaqueAlpha,q+x*GetPixelChannels(image)+bit);
952         }
953         if ((image->columns % 8) != 0)
954           {
955             c=ReadBlobByte(image);
956             for (bit=0; bit < (ssize_t) (image->columns % 8); bit++)
957               SetPixelAlpha(image,c & (0x80 >> bit) ? TransparentAlpha :
958                 OpaqueAlpha,q+x*GetPixelChannels(image)+bit);
959           }
960         if (image->columns % 32)
961           for (x=0; x < (ssize_t) ((32-(image->columns % 32))/8); x++)
962             c=ReadBlobByte(image);
963         if (SyncAuthenticPixels(image,exception) == MagickFalse)
964           break;
965       }
966     }
967   if (EOFBlob(image) != MagickFalse)
968     ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
969       image->filename);
970   if (dib_info.height < 0)
971     {
972       Image
973         *flipped_image;
974 
975       /*
976         Correct image orientation.
977       */
978       flipped_image=FlipImage(image,exception);
979       if (flipped_image != (Image *) NULL)
980         {
981           DuplicateBlob(flipped_image,image);
982           image=DestroyImage(image);
983           image=flipped_image;
984         }
985     }
986   (void) CloseBlob(image);
987   return(GetFirstImageInList(image));
988 }
989 
990 /*
991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992 %                                                                             %
993 %                                                                             %
994 %                                                                             %
995 %   R e g i s t e r D I B I m a g e                                           %
996 %                                                                             %
997 %                                                                             %
998 %                                                                             %
999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1000 %
1001 %  RegisterDIBImage() adds attributes for the DIB image format to
1002 %  the list of supported formats.  The attributes include the image format
1003 %  tag, a method to read and/or write the format, whether the format
1004 %  supports the saving of more than one frame to the same file or blob,
1005 %  whether the format supports native in-memory I/O, and a brief
1006 %  description of the format.
1007 %
1008 %  The format of the RegisterDIBImage method is:
1009 %
1010 %      size_t RegisterDIBImage(void)
1011 %
1012 */
RegisterDIBImage(void)1013 ModuleExport size_t RegisterDIBImage(void)
1014 {
1015   MagickInfo
1016     *entry;
1017 
1018   entry=AcquireMagickInfo("DIB","DIB",
1019     "Microsoft Windows 3.X Packed Device-Independent Bitmap");
1020   entry->decoder=(DecodeImageHandler *) ReadDIBImage;
1021   entry->encoder=(EncodeImageHandler *) WriteDIBImage;
1022   entry->magick=(IsImageFormatHandler *) IsDIB;
1023   entry->flags^=CoderAdjoinFlag;
1024   entry->flags|=CoderStealthFlag;
1025   entry->flags|=CoderDecoderSeekableStreamFlag;
1026   (void) RegisterMagickInfo(entry);
1027   entry=AcquireMagickInfo("DIB","ICODIB",
1028     "Microsoft Windows 3.X Packed Device-Independent Bitmap");
1029   entry->decoder=(DecodeImageHandler *) ReadDIBImage;
1030   entry->magick=(IsImageFormatHandler *) IsDIB;
1031   entry->flags^=CoderAdjoinFlag;
1032   entry->flags|=CoderStealthFlag;
1033   entry->flags|=CoderDecoderSeekableStreamFlag;
1034   (void) RegisterMagickInfo(entry);
1035   return(MagickImageCoderSignature);
1036 }
1037 
1038 /*
1039 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1040 %                                                                             %
1041 %                                                                             %
1042 %                                                                             %
1043 %   U n r e g i s t e r D I B I m a g e                                       %
1044 %                                                                             %
1045 %                                                                             %
1046 %                                                                             %
1047 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1048 %
1049 %  UnregisterDIBImage() removes format registrations made by the
1050 %  DIB module from the list of supported formats.
1051 %
1052 %  The format of the UnregisterDIBImage method is:
1053 %
1054 %      UnregisterDIBImage(void)
1055 %
1056 */
UnregisterDIBImage(void)1057 ModuleExport void UnregisterDIBImage(void)
1058 {
1059   (void) UnregisterMagickInfo("ICODIB");
1060   (void) UnregisterMagickInfo("DIB");
1061 }
1062 
1063 /*
1064 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1065 %                                                                             %
1066 %                                                                             %
1067 %                                                                             %
1068 %   W r i t e D I B I m a g e                                                 %
1069 %                                                                             %
1070 %                                                                             %
1071 %                                                                             %
1072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1073 %
1074 %  WriteDIBImage() writes an image in Microsoft Windows bitmap encoded
1075 %  image format.
1076 %
1077 %  The format of the WriteDIBImage method is:
1078 %
1079 %      MagickBooleanType WriteDIBImage(const ImageInfo *image_info,
1080 %        Image *image,ExceptionInfo *exception)
1081 %
1082 %  A description of each parameter follows.
1083 %
1084 %    o image_info: the image info.
1085 %
1086 %    o image:  The image.
1087 %
1088 %    o exception: return any errors or warnings in this structure.
1089 %
1090 */
WriteDIBImage(const ImageInfo * image_info,Image * image,ExceptionInfo * exception)1091 static MagickBooleanType WriteDIBImage(const ImageInfo *image_info,Image *image,
1092   ExceptionInfo *exception)
1093 {
1094   DIBInfo
1095     dib_info;
1096 
1097   MagickBooleanType
1098     status;
1099 
1100   register const Quantum
1101     *p;
1102 
1103   register ssize_t
1104     i,
1105     x;
1106 
1107   register unsigned char
1108     *q;
1109 
1110   size_t
1111     bytes_per_line;
1112 
1113   ssize_t
1114     y;
1115 
1116   unsigned char
1117     *dib_data,
1118     *pixels;
1119 
1120   /*
1121     Open output image file.
1122   */
1123   assert(image_info != (const ImageInfo *) NULL);
1124   assert(image_info->signature == MagickCoreSignature);
1125   assert(image != (Image *) NULL);
1126   assert(image->signature == MagickCoreSignature);
1127   if (image->debug != MagickFalse)
1128     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1129   assert(exception != (ExceptionInfo *) NULL);
1130   assert(exception->signature == MagickCoreSignature);
1131   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1132   if (status == MagickFalse)
1133     return(status);
1134   /*
1135     Initialize DIB raster file header.
1136   */
1137   (void) TransformImageColorspace(image,sRGBColorspace,exception);
1138   if (image->storage_class == DirectClass)
1139     {
1140       /*
1141         Full color DIB raster.
1142       */
1143       dib_info.number_colors=0;
1144       dib_info.bits_per_pixel=(unsigned short) (image->alpha_trait ? 32 : 24);
1145     }
1146   else
1147     {
1148       /*
1149         Colormapped DIB raster.
1150       */
1151       dib_info.bits_per_pixel=8;
1152       if (image_info->depth > 8)
1153         dib_info.bits_per_pixel=16;
1154       if (SetImageMonochrome(image,exception) != MagickFalse)
1155         dib_info.bits_per_pixel=1;
1156       dib_info.number_colors=(unsigned int) (dib_info.bits_per_pixel == 16 ? 0 :
1157         (1UL << dib_info.bits_per_pixel));
1158     }
1159   bytes_per_line=4*((image->columns*dib_info.bits_per_pixel+31)/32);
1160   dib_info.size=40;
1161   dib_info.width=(int) image->columns;
1162   dib_info.height=(int) image->rows;
1163   dib_info.planes=1;
1164   dib_info.compression=(unsigned int) (dib_info.bits_per_pixel == 16 ?
1165     BI_BITFIELDS : BI_RGB);
1166   dib_info.image_size=(unsigned int) (bytes_per_line*image->rows);
1167   dib_info.x_pixels=75*39;
1168   dib_info.y_pixels=75*39;
1169   switch (image->units)
1170   {
1171     case UndefinedResolution:
1172     case PixelsPerInchResolution:
1173     {
1174       dib_info.x_pixels=(unsigned int) (100.0*image->resolution.x/2.54);
1175       dib_info.y_pixels=(unsigned int) (100.0*image->resolution.y/2.54);
1176       break;
1177     }
1178     case PixelsPerCentimeterResolution:
1179     {
1180       dib_info.x_pixels=(unsigned int) (100.0*image->resolution.x);
1181       dib_info.y_pixels=(unsigned int) (100.0*image->resolution.y);
1182       break;
1183     }
1184   }
1185   dib_info.colors_important=dib_info.number_colors;
1186   /*
1187     Convert MIFF to DIB raster pixels.
1188   */
1189   pixels=(unsigned char *) AcquireQuantumMemory(image->rows,MagickMax(
1190     bytes_per_line,image->columns+256UL)*sizeof(*pixels));
1191   if (pixels == (unsigned char *) NULL)
1192     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1193   (void) memset(pixels,0,dib_info.image_size);
1194   switch (dib_info.bits_per_pixel)
1195   {
1196     case 1:
1197     {
1198       register unsigned char
1199         bit,
1200         byte;
1201 
1202       /*
1203         Convert PseudoClass image to a DIB monochrome image.
1204       */
1205       for (y=0; y < (ssize_t) image->rows; y++)
1206       {
1207         p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1208         if (p == (const Quantum *) NULL)
1209           break;
1210         q=pixels+(image->rows-y-1)*bytes_per_line;
1211         bit=0;
1212         byte=0;
1213         for (x=0; x < (ssize_t) image->columns; x++)
1214         {
1215           byte<<=1;
1216           byte|=GetPixelIndex(image,p) != 0 ? 0x01 : 0x00;
1217           bit++;
1218           if (bit == 8)
1219             {
1220               *q++=byte;
1221               bit=0;
1222               byte=0;
1223             }
1224            p+=GetPixelChannels(image);
1225          }
1226          if (bit != 0)
1227            {
1228              *q++=(unsigned char) (byte << (8-bit));
1229              x++;
1230            }
1231         for (x=(ssize_t) (image->columns+7)/8; x < (ssize_t) bytes_per_line; x++)
1232           *q++=0x00;
1233         status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1234           image->rows);
1235         if (status == MagickFalse)
1236           break;
1237       }
1238       break;
1239     }
1240     case 8:
1241     {
1242       /*
1243         Convert PseudoClass packet to DIB pixel.
1244       */
1245       for (y=0; y < (ssize_t) image->rows; y++)
1246       {
1247         p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1248         if (p == (const Quantum *) NULL)
1249           break;
1250         q=pixels+(image->rows-y-1)*bytes_per_line;
1251         for (x=0; x < (ssize_t) image->columns; x++)
1252         {
1253           *q++=(unsigned char) GetPixelIndex(image,p);
1254           p+=GetPixelChannels(image);
1255         }
1256         for ( ; x < (ssize_t) bytes_per_line; x++)
1257           *q++=0x00;
1258         status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1259           image->rows);
1260         if (status == MagickFalse)
1261           break;
1262       }
1263       break;
1264     }
1265     case 16:
1266     {
1267       unsigned short
1268         word;
1269       /*
1270         Convert PseudoClass packet to DIB pixel.
1271       */
1272       for (y=0; y < (ssize_t) image->rows; y++)
1273       {
1274         p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1275         if (p == (const Quantum *) NULL)
1276           break;
1277         q=pixels+(image->rows-y-1)*bytes_per_line;
1278         for (x=0; x < (ssize_t) image->columns; x++)
1279         {
1280           word=(unsigned short) ((ScaleColor8to5((unsigned char)
1281             ScaleQuantumToChar(GetPixelRed(image,p))) << 11) | (ScaleColor8to6(
1282             (unsigned char) ScaleQuantumToChar(GetPixelGreen(image,p))) << 5) |
1283             (ScaleColor8to5((unsigned char) ScaleQuantumToChar((unsigned char)
1284             GetPixelBlue(image,p)) << 0)));
1285           *q++=(unsigned char)(word & 0xff);
1286           *q++=(unsigned char)(word >> 8);
1287           p+=GetPixelChannels(image);
1288         }
1289         for (x=(ssize_t) (2*image->columns); x < (ssize_t) bytes_per_line; x++)
1290           *q++=0x00;
1291         status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1292           image->rows);
1293         if (status == MagickFalse)
1294           break;
1295       }
1296       break;
1297     }
1298     case 24:
1299     case 32:
1300     {
1301       /*
1302         Convert DirectClass packet to DIB RGB pixel.
1303       */
1304       for (y=0; y < (ssize_t) image->rows; y++)
1305       {
1306         p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1307         if (p == (const Quantum *) NULL)
1308           break;
1309         q=pixels+(image->rows-y-1)*bytes_per_line;
1310         for (x=0; x < (ssize_t) image->columns; x++)
1311         {
1312           *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1313           *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1314           *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1315           if (image->alpha_trait != UndefinedPixelTrait)
1316             *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
1317           p+=GetPixelChannels(image);
1318         }
1319         if (dib_info.bits_per_pixel == 24)
1320           for (x=(ssize_t) (3*image->columns); x < (ssize_t) bytes_per_line; x++)
1321             *q++=0x00;
1322         status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1323           image->rows);
1324         if (status == MagickFalse)
1325           break;
1326       }
1327       break;
1328     }
1329   }
1330   if (dib_info.bits_per_pixel == 8)
1331     if (image_info->compression != NoCompression)
1332       {
1333         size_t
1334           length;
1335 
1336         /*
1337           Convert run-length encoded raster pixels.
1338         */
1339         length=2UL*(bytes_per_line+2UL)+2UL;
1340         dib_data=(unsigned char *) AcquireQuantumMemory(length,
1341           (image->rows+2UL)*sizeof(*dib_data));
1342         if (dib_data == (unsigned char *) NULL)
1343           {
1344             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1345             ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1346           }
1347         dib_info.image_size=(unsigned int) EncodeImage(image,bytes_per_line,
1348           pixels,dib_data);
1349         pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1350         pixels=dib_data;
1351         dib_info.compression = BI_RLE8;
1352       }
1353   /*
1354     Write DIB header.
1355   */
1356   (void) WriteBlobLSBLong(image,dib_info.size);
1357   (void) WriteBlobLSBLong(image,(unsigned int) dib_info.width);
1358   (void) WriteBlobLSBLong(image,(unsigned int) dib_info.height);
1359   (void) WriteBlobLSBShort(image,(unsigned short) dib_info.planes);
1360   (void) WriteBlobLSBShort(image,dib_info.bits_per_pixel);
1361   (void) WriteBlobLSBLong(image,dib_info.compression);
1362   (void) WriteBlobLSBLong(image,dib_info.image_size);
1363   (void) WriteBlobLSBLong(image,dib_info.x_pixels);
1364   (void) WriteBlobLSBLong(image,dib_info.y_pixels);
1365   (void) WriteBlobLSBLong(image,dib_info.number_colors);
1366   (void) WriteBlobLSBLong(image,dib_info.colors_important);
1367   if (image->storage_class == PseudoClass)
1368     {
1369       if (dib_info.bits_per_pixel <= 8)
1370         {
1371           unsigned char
1372             *dib_colormap;
1373 
1374           /*
1375             Dump colormap to file.
1376           */
1377           dib_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
1378             (1UL << dib_info.bits_per_pixel),4*sizeof(*dib_colormap));
1379           if (dib_colormap == (unsigned char *) NULL)
1380             {
1381               pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1382               ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1383             }
1384           q=dib_colormap;
1385           for (i=0; i < (ssize_t) MagickMin(image->colors,dib_info.number_colors); i++)
1386           {
1387             *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));
1388             *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
1389             *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
1390             *q++=(Quantum) 0x0;
1391           }
1392           for ( ; i < (ssize_t) (1L << dib_info.bits_per_pixel); i++)
1393           {
1394             *q++=(Quantum) 0x0;
1395             *q++=(Quantum) 0x0;
1396             *q++=(Quantum) 0x0;
1397             *q++=(Quantum) 0x0;
1398           }
1399           (void) WriteBlob(image,(size_t) (4*(1 << dib_info.bits_per_pixel)),
1400             dib_colormap);
1401           dib_colormap=(unsigned char *) RelinquishMagickMemory(dib_colormap);
1402         }
1403       else
1404         if ((dib_info.bits_per_pixel == 16) &&
1405             (dib_info.compression == BI_BITFIELDS))
1406           {
1407             (void) WriteBlobLSBLong(image,0xf800);
1408             (void) WriteBlobLSBLong(image,0x07e0);
1409             (void) WriteBlobLSBLong(image,0x001f);
1410           }
1411     }
1412   (void) WriteBlob(image,dib_info.image_size,pixels);
1413   pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1414   (void) CloseBlob(image);
1415   return(MagickTrue);
1416 }
1417