blob: e863be9ba6918027628a7fdfa2b9edf25e559581 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% BBBB M M PPPP %
7% B B MM MM P P %
8% BBBB M M M PPPP %
9% B B M M P %
10% BBBB M M P %
11% %
12% %
13% Read/Write Microsoft Windows Bitmap Image Format %
14% %
15% Software Design %
16% John Cristy %
17% Glenn Randers-Pehrson %
18% December 2001 %
19% %
20% %
21% Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
22% dedicated to making software imaging solutions freely available. %
23% %
24% You may not use this file except in compliance with the License. You may %
25% obtain a copy of the License at %
26% %
27% http://www.imagemagick.org/script/license.php %
28% %
29% Unless required by applicable law or agreed to in writing, software %
30% distributed under the License is distributed on an "AS IS" BASIS, %
31% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
32% See the License for the specific language governing permissions and %
33% limitations under the License. %
34% %
35%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
43#include "magick/studio.h"
44#include "magick/blob.h"
45#include "magick/blob-private.h"
46#include "magick/cache.h"
cristy316d5172009-09-17 19:31:25 +000047#include "magick/colormap-private.h"
cristy3ed852e2009-09-05 21:47:34 +000048#include "magick/color-private.h"
49#include "magick/colorspace.h"
50#include "magick/exception.h"
51#include "magick/exception-private.h"
52#include "magick/image.h"
53#include "magick/image-private.h"
54#include "magick/list.h"
55#include "magick/log.h"
56#include "magick/magick.h"
57#include "magick/memory_.h"
58#include "magick/monitor.h"
59#include "magick/monitor-private.h"
60#include "magick/profile.h"
61#include "magick/quantum-private.h"
62#include "magick/static.h"
63#include "magick/string_.h"
64#include "magick/module.h"
65#include "magick/transform.h"
66
67/*
68 Macro definitions (from Windows wingdi.h).
69*/
70#undef BI_JPEG
71#define BI_JPEG 4
72#undef BI_PNG
73#define BI_PNG 5
74#if !defined(__WINDOWS__) || defined(__MINGW32__)
75#define BI_RGB 0
76#define BI_RLE8 1
77#define BI_RLE4 2
78#define BI_BITFIELDS 3
79
80#define LCS_CALIBRATED_RBG 0
81#define LCS_sRGB 1
82#define LCS_WINDOWS_COLOR_SPACE 2
83#define PROFILE_LINKED 3
84#define PROFILE_EMBEDDED 4
85
86#define LCS_GM_BUSINESS 1 /* Saturation */
87#define LCS_GM_GRAPHICS 2 /* Relative */
88#define LCS_GM_IMAGES 4 /* Perceptual */
89#define LCS_GM_ABS_COLORIMETRIC 8 /* Absolute */
90#endif
91
92/*
93 Typedef declarations.
94*/
95typedef struct _BMPInfo
96{
97 unsigned int
98 file_size,
99 ba_offset,
100 offset_bits,
101 size;
102
103 long
104 width,
105 height;
106
107 unsigned short
108 planes,
109 bits_per_pixel;
110
111 unsigned int
112 compression,
113 image_size,
114 x_pixels,
115 y_pixels,
116 number_colors,
117 red_mask,
118 green_mask,
119 blue_mask,
120 alpha_mask,
121 colors_important;
122
123 int
124 colorspace;
125
126 PrimaryInfo
127 red_primary,
128 green_primary,
129 blue_primary,
130 gamma_scale;
131} BMPInfo;
132
133/*
134 Forward declarations.
135*/
136static MagickBooleanType
137 WriteBMPImage(const ImageInfo *,Image *);
138
139/*
140%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141% %
142% %
143% %
144% D e c o d e I m a g e %
145% %
146% %
147% %
148%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149%
150% DecodeImage unpacks the packed image pixels into runlength-encoded
151% pixel packets.
152%
153% The format of the DecodeImage method is:
154%
155% MagickBooleanType DecodeImage(Image *image,
156% const unsigned long compression,unsigned char *pixels)
157%
158% A description of each parameter follows:
159%
160% o image: the address of a structure of type Image.
161%
162% o compression: Zero means uncompressed. A value of 1 means the
163% compressed pixels are runlength encoded for a 256-color bitmap.
164% A value of 2 means a 16-color bitmap. A value of 3 means bitfields
165% encoding.
166%
167% o pixels: The address of a byte (8 bits) array of pixel data created by
168% the decoding process.
169%
170*/
171
172static inline long MagickAbsoluteValue(const long x)
173{
174 if (x < 0)
175 return(-x);
176 return(x);
177}
178
179static inline size_t MagickMax(const size_t x,const size_t y)
180{
181 if (x > y)
182 return(x);
183 return(y);
184}
185
186static inline long MagickMin(const long x,const long y)
187{
188 if (x < y)
189 return(x);
190 return(y);
191}
192
193static MagickBooleanType DecodeImage(Image *image,
194 const unsigned long compression,unsigned char *pixels)
195{
196 int
197 count;
198
199 long
200 y;
201
202 register long
203 i,
204 x;
205
206 register unsigned char
207 *p,
208 *q;
209
210 unsigned char
211 byte;
212
213 assert(image != (Image *) NULL);
214 assert(image->signature == MagickSignature);
215 if (image->debug != MagickFalse)
216 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
217 assert(pixels != (unsigned char *) NULL);
218 (void) ResetMagickMemory(pixels,0,(size_t) image->columns*image->rows*
219 sizeof(*pixels));
220 byte=0;
221 x=0;
222 p=pixels;
223 q=pixels+(size_t) image->columns*image->rows;
224 for (y=0; y < (long) image->rows; )
225 {
226 if ((p < pixels) || (p >= q))
227 break;
228 count=ReadBlobByte(image);
229 if (count == EOF)
230 break;
231 if (count != 0)
232 {
233 /*
234 Encoded mode.
235 */
236 count=MagickMin(count,(int) (q-p));
237 byte=(unsigned char) ReadBlobByte(image);
238 if (compression == BI_RLE8)
239 {
240 for (i=0; i < count; i++)
241 *p++=(unsigned char) byte;
242 }
243 else
244 {
245 for (i=0; i < count; i++)
246 *p++=(unsigned char)
247 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
248 }
249 x+=count;
250 }
251 else
252 {
253 /*
254 Escape mode.
255 */
256 count=ReadBlobByte(image);
257 if (count == 0x01)
258 return(MagickTrue);
259 switch (count)
260 {
261 case 0x00:
262 {
263 /*
264 End of line.
265 */
266 x=0;
267 y++;
268 p=pixels+y*image->columns;
269 break;
270 }
271 case 0x02:
272 {
273 /*
274 Delta mode.
275 */
276 x+=ReadBlobByte(image);
277 y+=ReadBlobByte(image);
278 p=pixels+y*image->columns+x;
279 break;
280 }
281 default:
282 {
283 /*
284 Absolute mode.
285 */
286 count=MagickMin(count,(int) (q-p));
287 if (compression == BI_RLE8)
288 for (i=0; i < count; i++)
289 *p++=(unsigned char) ReadBlobByte(image);
290 else
291 for (i=0; i < count; i++)
292 {
293 if ((i & 0x01) == 0)
294 byte=(unsigned char) ReadBlobByte(image);
295 *p++=(unsigned char)
296 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
297 }
298 x+=count;
299 /*
300 Read pad byte.
301 */
302 if (compression == BI_RLE8)
303 {
304 if ((count & 0x01) != 0)
305 (void) ReadBlobByte(image);
306 }
307 else
308 if (((count & 0x03) == 1) || ((count & 0x03) == 2))
309 (void) ReadBlobByte(image);
310 break;
311 }
312 }
313 }
314 if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
315 break;
316 }
317 (void) ReadBlobByte(image); /* end of line */
318 (void) ReadBlobByte(image);
319 return(MagickTrue);
320}
321
322/*
323%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
324% %
325% %
326% %
327% E n c o d e I m a g e %
328% %
329% %
330% %
331%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332%
333% EncodeImage compresses pixels using a runlength encoded format.
334%
335% The format of the EncodeImage method is:
336%
337% static MagickBooleanType EncodeImage(Image *image,
338% const unsigned long bytes_per_line,const unsigned char *pixels,
339% unsigned char *compressed_pixels)
340%
341% A description of each parameter follows:
342%
343% o image: The image.
344%
345% o bytes_per_line: the number of bytes in a scanline of compressed pixels
346%
347% o pixels: The address of a byte (8 bits) array of pixel data created by
348% the compression process.
349%
350% o compressed_pixels: The address of a byte (8 bits) array of compressed
351% pixel data.
352%
353*/
354static size_t EncodeImage(Image *image,const unsigned long bytes_per_line,
355 const unsigned char *pixels,unsigned char *compressed_pixels)
356{
357 long
358 y;
359
360 MagickBooleanType
361 status;
362
363 register const unsigned char
364 *p;
365
366 register long
367 i,
368 x;
369
370 register unsigned char
371 *q;
372
373 /*
374 Runlength encode pixels.
375 */
376 assert(image != (Image *) NULL);
377 assert(image->signature == MagickSignature);
378 if (image->debug != MagickFalse)
379 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
380 assert(pixels != (const unsigned char *) NULL);
381 assert(compressed_pixels != (unsigned char *) NULL);
382 p=pixels;
383 q=compressed_pixels;
384 i=0;
385 for (y=0; y < (long) image->rows; y++)
386 {
387 for (x=0; x < (long) bytes_per_line; x+=i)
388 {
389 /*
390 Determine runlength.
391 */
392 for (i=1; ((x+i) < (long) bytes_per_line); i++)
393 if ((i == 255) || (*(p+i) != *p))
394 break;
395 *q++=(unsigned char) i;
396 *q++=(*p);
397 p+=i;
398 }
399 /*
400 End of line.
401 */
402 *q++=(unsigned char) 0x00;
403 *q++=(unsigned char) 0x00;
404 status=SetImageProgress(image,SaveImageTag,y,image->rows);
405 if (status == MagickFalse)
406 break;
407 }
408 /*
409 End of bitmap.
410 */
411 *q++=(unsigned char) 0x00;
412 *q++=(unsigned char) 0x01;
413 return((size_t) (q-compressed_pixels));
414}
415
416/*
417%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
418% %
419% %
420% %
421% I s B M P %
422% %
423% %
424% %
425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
426%
427% IsBMP() returns MagickTrue if the image format type, identified by the
428% magick string, is BMP.
429%
430% The format of the IsBMP method is:
431%
432% MagickBooleanType IsBMP(const unsigned char *magick,const size_t length)
433%
434% A description of each parameter follows:
435%
436% o magick: compare image format pattern against these bytes.
437%
438% o length: Specifies the length of the magick string.
439%
440*/
441static MagickBooleanType IsBMP(const unsigned char *magick,const size_t length)
442{
443 if (length < 2)
444 return(MagickFalse);
445 if ((LocaleNCompare((char *) magick,"BA",2) == 0) ||
446 (LocaleNCompare((char *) magick,"BM",2) == 0) ||
447 (LocaleNCompare((char *) magick,"IC",2) == 0) ||
448 (LocaleNCompare((char *) magick,"PI",2) == 0) ||
449 (LocaleNCompare((char *) magick,"CI",2) == 0) ||
450 (LocaleNCompare((char *) magick,"CP",2) == 0))
451 return(MagickTrue);
452 return(MagickFalse);
453}
454
455/*
456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457% %
458% %
459% %
460% R e a d B M P I m a g e %
461% %
462% %
463% %
464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
465%
466% ReadBMPImage() reads a Microsoft Windows bitmap image file, Version
467% 2, 3 (for Windows or NT), or 4, and returns it. It allocates the memory
468% necessary for the new Image structure and returns a pointer to the new
469% image.
470%
471% The format of the ReadBMPImage method is:
472%
473% image=ReadBMPImage(image_info)
474%
475% A description of each parameter follows:
476%
477% o image_info: the image info.
478%
479% o exception: return any errors or warnings in this structure.
480%
481*/
482
483static Image *ReadBMPImage(const ImageInfo *image_info,ExceptionInfo *exception)
484{
485 BMPInfo
486 bmp_info;
487
488 Image
489 *image;
490
491 IndexPacket
492 index;
493
494 long
495 y;
496
497 MagickBooleanType
498 status;
499
500 MagickOffsetType
501 offset,
502 start_position;
503
504 register IndexPacket
505 *indexes;
506
507 register long
508 x;
509
510 register PixelPacket
511 *q;
512
513 register long
514 i;
515
516 register unsigned char
517 *p;
518
519 ssize_t
520 count;
521
522 size_t
523 length;
524
525 unsigned char
526 magick[12],
527 *pixels;
528
529 unsigned long
530 bit,
531 blue,
532 bytes_per_line,
533 green,
534 opacity,
535 red;
536
537 /*
538 Open image file.
539 */
540 assert(image_info != (const ImageInfo *) NULL);
541 assert(image_info->signature == MagickSignature);
542 if (image_info->debug != MagickFalse)
543 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
544 image_info->filename);
545 assert(exception != (ExceptionInfo *) NULL);
546 assert(exception->signature == MagickSignature);
547 image=AcquireImage(image_info);
548 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
549 if (status == MagickFalse)
550 {
551 image=DestroyImageList(image);
552 return((Image *) NULL);
553 }
554 /*
555 Determine if this a BMP file.
556 */
557 (void) ResetMagickMemory(&bmp_info,0,sizeof(bmp_info));
558 bmp_info.ba_offset=0;
559 start_position=0;
560 count=ReadBlob(image,2,magick);
561 do
562 {
563 LongPixelPacket
564 shift;
565
566 PixelPacket
567 quantum_bits;
568
569 unsigned long
570 profile_data,
571 profile_size;
572
573 /*
574 Verify BMP identifier.
575 */
576 if (bmp_info.ba_offset == 0)
577 start_position=TellBlob(image)-2;
578 bmp_info.ba_offset=0;
579 while (LocaleNCompare((char *) magick,"BA",2) == 0)
580 {
581 bmp_info.file_size=ReadBlobLSBLong(image);
582 bmp_info.ba_offset=ReadBlobLSBLong(image);
583 bmp_info.offset_bits=ReadBlobLSBLong(image);
584 count=ReadBlob(image,2,magick);
585 if (count != 2)
586 break;
587 }
588 if (image->debug != MagickFalse)
589 (void) LogMagickEvent(CoderEvent,GetMagickModule()," Magick: %c%c",
590 magick[0],magick[1]);
591 if ((count == 0) || ((LocaleNCompare((char *) magick,"BM",2) != 0) &&
592 (LocaleNCompare((char *) magick,"CI",2) != 0)))
593 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
594 bmp_info.file_size=ReadBlobLSBLong(image);
595 (void) ReadBlobLSBLong(image);
596 bmp_info.offset_bits=ReadBlobLSBLong(image);
597 bmp_info.size=ReadBlobLSBLong(image);
598 if (image->debug != MagickFalse)
599 (void) LogMagickEvent(CoderEvent,GetMagickModule()," BMP size: %u",
600 bmp_info.size);
601 if (bmp_info.size == 12)
602 {
603 /*
604 OS/2 BMP image file.
605 */
606 bmp_info.width=(short) ReadBlobLSBShort(image);
607 bmp_info.height=(short) ReadBlobLSBShort(image);
608 bmp_info.planes=ReadBlobLSBShort(image);
609 bmp_info.bits_per_pixel=ReadBlobLSBShort(image);
610 bmp_info.x_pixels=0;
611 bmp_info.y_pixels=0;
612 bmp_info.number_colors=0;
613 bmp_info.compression=BI_RGB;
614 bmp_info.image_size=0;
615 bmp_info.alpha_mask=0;
616 if (image->debug != MagickFalse)
617 {
618 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
619 " Format: OS/2 Bitmap");
620 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
621 " Geometry: %ldx%ld",bmp_info.width,bmp_info.height);
622 }
623 }
624 else
625 {
626 /*
627 Microsoft Windows BMP image file.
628 */
629 if (bmp_info.size < 40)
630 ThrowReaderException(CorruptImageError,"NonOS2HeaderSizeError");
631 bmp_info.width=(int) ReadBlobLSBLong(image);
632 bmp_info.height=(int) ReadBlobLSBLong(image);
633 bmp_info.planes=ReadBlobLSBShort(image);
634 bmp_info.bits_per_pixel=ReadBlobLSBShort(image);
635 bmp_info.compression=ReadBlobLSBLong(image);
636 bmp_info.image_size=ReadBlobLSBLong(image);
637 bmp_info.x_pixels=ReadBlobLSBLong(image);
638 bmp_info.y_pixels=ReadBlobLSBLong(image);
639 bmp_info.number_colors=ReadBlobLSBLong(image);
640 bmp_info.colors_important=ReadBlobLSBLong(image);
641 profile_data=0;
642 profile_size=0;
643 if (image->debug != MagickFalse)
644 {
645 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
646 " Format: MS Windows bitmap");
647 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
648 " Geometry: %ldx%ld",bmp_info.width,bmp_info.height);
649 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
650 " Bits per pixel: %d",bmp_info.bits_per_pixel);
651 switch ((int) bmp_info.compression)
652 {
653 case BI_RGB:
654 {
655 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
656 " Compression: BI_RGB");
657 break;
658 }
659 case BI_RLE4:
660 {
661 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
662 " Compression: BI_RLE4");
663 break;
664 }
665 case BI_RLE8:
666 {
667 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
668 " Compression: BI_RLE8");
669 break;
670 }
671 case BI_BITFIELDS:
672 {
673 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
674 " Compression: BI_BITFIELDS");
675 break;
676 }
677 case BI_PNG:
678 {
679 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
680 " Compression: BI_PNG");
681 break;
682 }
683 case BI_JPEG:
684 {
685 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
686 " Compression: BI_JPEG");
687 break;
688 }
689 default:
690 {
691 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
692 " Compression: UNKNOWN (%u)",bmp_info.compression);
693 }
694 }
695 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
696 " Number of colors: %u",bmp_info.number_colors);
697 }
698 bmp_info.red_mask=ReadBlobLSBLong(image);
699 bmp_info.green_mask=ReadBlobLSBLong(image);
700 bmp_info.blue_mask=ReadBlobLSBLong(image);
701 if (bmp_info.size > 40)
702 {
703 double
704 sum;
705
706 /*
707 Read color management information.
708 */
709 bmp_info.alpha_mask=ReadBlobLSBLong(image);
710 bmp_info.colorspace=(long) ReadBlobLSBLong(image);
711 /*
712 Decode 2^30 fixed point formatted CIE primaries.
713 */
714 bmp_info.red_primary.x=(double) ReadBlobLSBLong(image)/0x3ffffff;
715 bmp_info.red_primary.y=(double) ReadBlobLSBLong(image)/0x3ffffff;
716 bmp_info.red_primary.z=(double) ReadBlobLSBLong(image)/0x3ffffff;
717 bmp_info.green_primary.x=(double) ReadBlobLSBLong(image)/0x3ffffff;
718 bmp_info.green_primary.y=(double) ReadBlobLSBLong(image)/0x3ffffff;
719 bmp_info.green_primary.z=(double) ReadBlobLSBLong(image)/0x3ffffff;
720 bmp_info.blue_primary.x=(double) ReadBlobLSBLong(image)/0x3ffffff;
721 bmp_info.blue_primary.y=(double) ReadBlobLSBLong(image)/0x3ffffff;
722 bmp_info.blue_primary.z=(double) ReadBlobLSBLong(image)/0x3ffffff;
723 sum=bmp_info.red_primary.x+bmp_info.red_primary.x+
724 bmp_info.red_primary.z;
725 image->chromaticity.red_primary.x/=sum;
726 image->chromaticity.red_primary.y/=sum;
727 sum=bmp_info.green_primary.x+bmp_info.green_primary.x+
728 bmp_info.green_primary.z;
729 image->chromaticity.green_primary.x/=sum;
730 image->chromaticity.green_primary.y/=sum;
731 sum=bmp_info.blue_primary.x+bmp_info.blue_primary.x+
732 bmp_info.blue_primary.z;
733 image->chromaticity.blue_primary.x/=sum;
734 image->chromaticity.blue_primary.y/=sum;
735 /*
736 Decode 16^16 fixed point formatted gamma_scales.
737 */
738 bmp_info.gamma_scale.x=(double) ReadBlobLSBLong(image)/0xffff;
739 bmp_info.gamma_scale.y=(double) ReadBlobLSBLong(image)/0xffff;
740 bmp_info.gamma_scale.z=(double) ReadBlobLSBLong(image)/0xffff;
741 /*
742 Compute a single gamma from the BMP 3-channel gamma.
743 */
744 image->gamma=(bmp_info.gamma_scale.x+bmp_info.gamma_scale.y+
745 bmp_info.gamma_scale.z)/3.0;
746 }
747 if (bmp_info.size > 108)
748 {
749 unsigned long
750 intent;
751
752 /*
753 Read BMP Version 5 color management information.
754 */
755 intent=ReadBlobLSBLong(image);
756 switch ((int) intent)
757 {
758 case LCS_GM_BUSINESS:
759 {
760 image->rendering_intent=SaturationIntent;
761 break;
762 }
763 case LCS_GM_GRAPHICS:
764 {
765 image->rendering_intent=RelativeIntent;
766 break;
767 }
768 case LCS_GM_IMAGES:
769 {
770 image->rendering_intent=PerceptualIntent;
771 break;
772 }
773 case LCS_GM_ABS_COLORIMETRIC:
774 {
775 image->rendering_intent=AbsoluteIntent;
776 break;
777 }
778 }
779 profile_data=ReadBlobLSBLong(image);
780 profile_size=ReadBlobLSBLong(image);
781 (void) ReadBlobLSBLong(image); /* Reserved byte */
782 }
783 }
784 if ((bmp_info.compression != BI_RGB) &&
785 ((MagickSizeType) bmp_info.file_size != GetBlobSize(image)))
786 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
787 "LengthAndFilesizeDoNotMatch","`%s'",image->filename);
788 if (bmp_info.width <= 0)
789 ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
790 if (bmp_info.height == 0)
791 ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");
792 if (bmp_info.planes != 1)
793 ThrowReaderException(CorruptImageError,"StaticPlanesValueNotEqualToOne");
794 if ((bmp_info.bits_per_pixel != 1) && (bmp_info.bits_per_pixel != 4) &&
795 (bmp_info.bits_per_pixel != 8) && (bmp_info.bits_per_pixel != 16) &&
796 (bmp_info.bits_per_pixel != 24) && (bmp_info.bits_per_pixel != 32))
797 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
798 if (bmp_info.number_colors > (1U << bmp_info.bits_per_pixel))
799 {
800 if (bmp_info.bits_per_pixel < 24)
801 ThrowReaderException(CorruptImageError,"UnrecognizedNumberOfColors");
802 bmp_info.number_colors=0;
803 }
804 if (bmp_info.compression > 3)
805 ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression");
806 if ((bmp_info.compression == 1) && (bmp_info.bits_per_pixel != 8))
807 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
808 if ((bmp_info.compression == 2) && (bmp_info.bits_per_pixel != 4))
809 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
810 if ((bmp_info.compression == 3) && (bmp_info.bits_per_pixel < 16))
811 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
812 switch (bmp_info.compression)
813 {
814 case BI_RGB:
815 case BI_RLE8:
816 case BI_RLE4:
817 case BI_BITFIELDS:
818 break;
819 case BI_JPEG:
820 ThrowReaderException(CoderError,"JPEGCompressNotSupported");
821 case BI_PNG:
822 ThrowReaderException(CoderError,"PNGCompressNotSupported");
823 default:
824 ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression");
825 }
826 image->columns=(unsigned long) MagickAbsoluteValue(bmp_info.width);
827 image->rows=(unsigned long) MagickAbsoluteValue(bmp_info.height);
828 image->depth=bmp_info.bits_per_pixel <= 8 ? bmp_info.bits_per_pixel : 8;
829 image->matte=bmp_info.alpha_mask != 0 ? MagickTrue : MagickFalse;
830 if ((bmp_info.number_colors != 0) || (bmp_info.bits_per_pixel < 16))
831 {
832 image->storage_class=PseudoClass;
833 image->colors=bmp_info.number_colors;
834 if (image->colors == 0)
835 image->colors=1L << bmp_info.bits_per_pixel;
836 }
837 if (image->storage_class == PseudoClass)
838 {
839 unsigned char
840 *bmp_colormap;
841
842 size_t
843 packet_size;
844
845 /*
846 Read BMP raster colormap.
847 */
848 if (image->debug != MagickFalse)
849 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
850 " Reading colormap of %ld colors",image->colors);
851 if (AcquireImageColormap(image,image->colors) == MagickFalse)
852 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
853 bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
854 image->colors,4*sizeof(*bmp_colormap));
855 if (bmp_colormap == (unsigned char *) NULL)
856 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
857 if ((bmp_info.size == 12) || (bmp_info.size == 64))
858 packet_size=3;
859 else
860 packet_size=4;
861 offset=SeekBlob(image,start_position+14+bmp_info.size,SEEK_SET);
862 if (offset < 0)
863 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
864 count=ReadBlob(image,packet_size*image->colors,bmp_colormap);
865 if (count != (ssize_t) (packet_size*image->colors))
866 ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
867 p=bmp_colormap;
868 for (i=0; i < (long) image->colors; i++)
869 {
870 image->colormap[i].blue=ScaleCharToQuantum(*p++);
871 image->colormap[i].green=ScaleCharToQuantum(*p++);
872 image->colormap[i].red=ScaleCharToQuantum(*p++);
873 if (packet_size == 4)
874 p++;
875 }
876 bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
877 }
878 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
879 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
880 break;
881 /*
882 Read image data.
883 */
884 offset=SeekBlob(image,start_position+bmp_info.offset_bits,SEEK_SET);
885 if (offset < 0)
886 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
887 if (bmp_info.compression == BI_RLE4)
888 bmp_info.bits_per_pixel<<=1;
889 bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);
890 length=(size_t) bytes_per_line*image->rows;
891 pixels=(unsigned char *) AcquireQuantumMemory((size_t) image->rows,
892 MagickMax(bytes_per_line,image->columns+256UL)*sizeof(*pixels));
893 if (pixels == (unsigned char *) NULL)
894 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
895 if ((bmp_info.compression == BI_RGB) ||
896 (bmp_info.compression == BI_BITFIELDS))
897 {
898 if (image->debug != MagickFalse)
899 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
900 " Reading pixels (%ld bytes)",(long) length);
901 count=ReadBlob(image,length,pixels);
902 if (count != (ssize_t) length)
903 ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
904 }
905 else
906 {
907 /*
908 Convert run-length encoded raster pixels.
909 */
910 status=DecodeImage(image,bmp_info.compression,pixels);
911 if (status == MagickFalse)
912 ThrowReaderException(CorruptImageError,
913 "UnableToRunlengthDecodeImage");
914 }
915 /*
916 Initialize image structure.
917 */
918 image->x_resolution=(double) bmp_info.x_pixels/100.0;
919 image->y_resolution=(double) bmp_info.y_pixels/100.0;
920 image->units=PixelsPerCentimeterResolution;
921 /*
922 Convert BMP raster image to pixel packets.
923 */
924 if (bmp_info.compression == BI_RGB)
925 {
926 bmp_info.alpha_mask=0;
927 bmp_info.red_mask=0x00ff0000U;
928 bmp_info.green_mask=0x0000ff00U;
929 bmp_info.blue_mask=0x000000ffU;
930 if (bmp_info.bits_per_pixel == 16)
931 {
932 /*
933 RGB555.
934 */
935 bmp_info.red_mask=0x00007c00U;
936 bmp_info.green_mask=0x000003e0U;
937 bmp_info.blue_mask=0x0000001fU;
938 }
939 }
940 if ((bmp_info.bits_per_pixel == 16) || (bmp_info.bits_per_pixel == 32))
941 {
942 register unsigned long
943 sample;
944
945 /*
946 Get shift and quantum bits info from bitfield masks.
947 */
948 (void) ResetMagickMemory(&shift,0,sizeof(shift));
949 (void) ResetMagickMemory(&quantum_bits,0,sizeof(quantum_bits));
950 if (bmp_info.red_mask != 0)
951 while (((bmp_info.red_mask << shift.red) & 0x80000000UL) == 0)
952 shift.red++;
953 if (bmp_info.green_mask != 0)
954 while (((bmp_info.green_mask << shift.green) & 0x80000000UL) == 0)
955 shift.green++;
956 if (bmp_info.blue_mask != 0)
957 while (((bmp_info.blue_mask << shift.blue) & 0x80000000UL) == 0)
958 shift.blue++;
959 if (bmp_info.alpha_mask != 0)
960 while (((bmp_info.alpha_mask << shift.opacity) & 0x80000000UL) == 0)
961 shift.opacity++;
962 sample=shift.red;
963 while (((bmp_info.red_mask << sample) & 0x80000000UL) != 0)
964 sample++;
965 quantum_bits.red=(Quantum) (sample-shift.red);
966 sample=shift.green;
967 while (((bmp_info.green_mask << sample) & 0x80000000UL) != 0)
968 sample++;
969 quantum_bits.green=(Quantum) (sample-shift.green);
970 sample=shift.blue;
971 while (((bmp_info.blue_mask << sample) & 0x80000000UL) != 0)
972 sample++;
973 quantum_bits.blue=(Quantum) (sample-shift.blue);
974 sample=shift.opacity;
975 while (((bmp_info.alpha_mask << sample) & 0x80000000UL) != 0)
976 sample++;
977 quantum_bits.opacity=(Quantum) (sample-shift.opacity);
978 }
979 switch (bmp_info.bits_per_pixel)
980 {
981 case 1:
982 {
983 /*
984 Convert bitmap scanline.
985 */
986 for (y=(long) image->rows-1; y >= 0; y--)
987 {
988 p=pixels+(image->rows-y-1)*bytes_per_line;
989 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
990 if (q == (PixelPacket *) NULL)
991 break;
992 indexes=GetAuthenticIndexQueue(image);
993 for (x=0; x < ((long) image->columns-7); x+=8)
994 {
995 for (bit=0; bit < 8; bit++)
996 {
997 index=(IndexPacket) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00);
998 indexes[x+bit]=index;
999 *q++=image->colormap[(long) index];
1000 }
1001 p++;
1002 }
1003 if ((image->columns % 8) != 0)
1004 {
1005 for (bit=0; bit < (image->columns % 8); bit++)
1006 {
1007 index=(IndexPacket) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00);
1008 indexes[x+bit]=index;
1009 *q++=image->colormap[(long) index];
1010 }
1011 p++;
1012 }
1013 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1014 break;
1015 if (image->previous == (Image *) NULL)
1016 {
1017 status=SetImageProgress(image,LoadImageTag,y,image->rows);
1018 if (status == MagickFalse)
1019 break;
1020 }
1021 }
1022 break;
1023 }
1024 case 4:
1025 {
1026 /*
1027 Convert PseudoColor scanline.
1028 */
1029 for (y=(long) image->rows-1; y >= 0; y--)
1030 {
1031 p=pixels+(image->rows-y-1)*bytes_per_line;
1032 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1033 if (q == (PixelPacket *) NULL)
1034 break;
1035 indexes=GetAuthenticIndexQueue(image);
1036 for (x=0; x < ((long) image->columns-1); x+=2)
1037 {
1038 index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f);
1039 indexes[x]=index;
1040 *q++=image->colormap[(long) index];
1041 index=ConstrainColormapIndex(image,*p & 0x0f);
1042 indexes[x+1]=index;
1043 *q++=image->colormap[(long) index];
1044 p++;
1045 }
1046 if ((image->columns % 2) != 0)
1047 {
1048 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf);
1049 indexes[x]=index;
1050 *q++=image->colormap[(long) index];
1051 p++;
1052 }
1053 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1054 break;
1055 if (image->previous == (Image *) NULL)
1056 {
1057 status=SetImageProgress(image,LoadImageTag,y,image->rows);
1058 if (status == MagickFalse)
1059 break;
1060 }
1061 }
1062 break;
1063 }
1064 case 8:
1065 {
1066 /*
1067 Convert PseudoColor scanline.
1068 */
1069 if ((bmp_info.compression == BI_RLE8) ||
1070 (bmp_info.compression == BI_RLE4))
1071 bytes_per_line=image->columns;
1072 for (y=(long) image->rows-1; y >= 0; y--)
1073 {
1074 p=pixels+(image->rows-y-1)*bytes_per_line;
1075 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1076 if (q == (PixelPacket *) NULL)
1077 break;
1078 indexes=GetAuthenticIndexQueue(image);
1079 for (x = (long)image->columns; x != 0; --x)
1080 {
1081 index=ConstrainColormapIndex(image,*p);
1082 *indexes++=index;
1083 *q=image->colormap[(long) index];
1084 p++;
1085 q++;
1086 }
1087 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1088 break;
1089 offset=(MagickOffsetType) (image->rows-y-1);
1090 if (image->previous == (Image *) NULL)
1091 {
1092 status=SetImageProgress(image,LoadImageTag,y,image->rows);
1093 if (status == MagickFalse)
1094 break;
1095 }
1096 }
1097 break;
1098 }
1099 case 16:
1100 {
1101 unsigned long
1102 pixel;
1103
1104 /*
1105 Convert bitfield encoded 16-bit PseudoColor scanline.
1106 */
1107 if (bmp_info.compression != BI_RGB &&
1108 bmp_info.compression != BI_BITFIELDS)
1109 ThrowReaderException(CorruptImageError,
1110 "UnrecognizedImageCompression");
1111 bytes_per_line=2*(image->columns+image->columns % 2);
1112 image->storage_class=DirectClass;
1113 for (y=(long) image->rows-1; y >= 0; y--)
1114 {
1115 p=pixels+(image->rows-y-1)*bytes_per_line;
1116 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1117 if (q == (PixelPacket *) NULL)
1118 break;
1119 for (x=0; x < (long) image->columns; x++)
1120 {
1121 pixel=(unsigned long) (*p++);
1122 pixel|=(*p++) << 8;
1123 red=((pixel & bmp_info.red_mask) << shift.red) >> 16;
1124 if (quantum_bits.red == 5)
1125 red|=((red & 0xe000) >> 5);
1126 if (quantum_bits.red <= 8)
1127 red|=((red & 0xff00) >> 8);
1128 green=((pixel & bmp_info.green_mask) << shift.green) >> 16;
1129 if (quantum_bits.green == 5)
1130 green|=((green & 0xe000) >> 5);
1131 if (quantum_bits.green == 6)
1132 green|=((green & 0xc000) >> 6);
1133 if (quantum_bits.green <= 8)
1134 green|=((green & 0xff00) >> 8);
1135 blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16;
1136 if (quantum_bits.blue == 5)
1137 blue|=((blue & 0xe000) >> 5);
1138 if (quantum_bits.blue <= 8)
1139 blue|=((blue & 0xff00) >> 8);
1140 opacity=((pixel & bmp_info.alpha_mask) << shift.opacity) >> 16;
1141 if (quantum_bits.opacity <= 8)
1142 opacity|=((opacity & 0xff00) >> 8);
1143 q->red=ScaleShortToQuantum((unsigned short) red);
1144 q->green=ScaleShortToQuantum((unsigned short) green);
1145 q->blue=ScaleShortToQuantum((unsigned short) blue);
1146 q->opacity=OpaqueOpacity;
1147 if (image->matte != MagickFalse)
1148 q->opacity=ScaleShortToQuantum((unsigned short) opacity);
1149 q++;
1150 }
1151 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1152 break;
1153 offset=(MagickOffsetType) (image->rows-y-1);
1154 if (image->previous == (Image *) NULL)
1155 {
1156 status=SetImageProgress(image,LoadImageTag,y,image->rows);
1157 if (status == MagickFalse)
1158 break;
1159 }
1160 }
1161 break;
1162 }
1163 case 24:
1164 {
1165 /*
1166 Convert DirectColor scanline.
1167 */
1168 bytes_per_line=4*((image->columns*24+31)/32);
1169 for (y=(long) image->rows-1; y >= 0; y--)
1170 {
1171 p=pixels+(image->rows-y-1)*bytes_per_line;
1172 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1173 if (q == (PixelPacket *) NULL)
1174 break;
1175 for (x=0; x < (long) image->columns; x++)
1176 {
1177 q->blue=ScaleCharToQuantum(*p++);
1178 q->green=ScaleCharToQuantum(*p++);
1179 q->red=ScaleCharToQuantum(*p++);
1180 q++;
1181 }
1182 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1183 break;
1184 offset=(MagickOffsetType) (image->rows-y-1);
1185 if (image->previous == (Image *) NULL)
1186 {
1187 status=SetImageProgress(image,LoadImageTag,y,image->rows);
1188 if (status == MagickFalse)
1189 break;
1190 }
1191 }
1192 break;
1193 }
1194 case 32:
1195 {
1196 /*
1197 Convert bitfield encoded DirectColor scanline.
1198 */
1199 if ((bmp_info.compression != BI_RGB) &&
1200 (bmp_info.compression != BI_BITFIELDS))
1201 ThrowReaderException(CorruptImageError,
1202 "UnrecognizedImageCompression");
1203 bytes_per_line=4*(image->columns);
1204 for (y=(long) image->rows-1; y >= 0; y--)
1205 {
1206 unsigned long
1207 pixel;
1208
1209 p=pixels+(image->rows-y-1)*bytes_per_line;
1210 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1211 if (q == (PixelPacket *) NULL)
1212 break;
1213 for (x=0; x < (long) image->columns; x++)
1214 {
1215 pixel=(unsigned long) (*p++);
1216 pixel|=(*p++ << 8);
1217 pixel|=(*p++ << 16);
1218 pixel|=(*p++ << 24);
1219 red=((pixel & bmp_info.red_mask) << shift.red) >> 16;
1220 if (quantum_bits.red == 8)
1221 red|=(red >> 8);
1222 green=((pixel & bmp_info.green_mask) << shift.green) >> 16;
1223 if (quantum_bits.green == 8)
1224 green|=(green >> 8);
1225 blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16;
1226 if (quantum_bits.blue == 8)
1227 blue|=(blue >> 8);
1228 opacity=((pixel & bmp_info.alpha_mask) << shift.opacity) >> 16;
1229 if (quantum_bits.opacity == 8)
1230 opacity|=(opacity >> 8);
1231 q->red=ScaleShortToQuantum((unsigned short) red);
1232 q->green=ScaleShortToQuantum((unsigned short) green);
1233 q->blue=ScaleShortToQuantum((unsigned short) blue);
1234 q->opacity=OpaqueOpacity;
1235 if (image->matte != MagickFalse)
1236 q->opacity=ScaleShortToQuantum((unsigned short) opacity);
1237 q++;
1238 }
1239 if (SyncAuthenticPixels(image,exception) == MagickFalse)
1240 break;
1241 offset=(MagickOffsetType) (image->rows-y-1);
1242 if (image->previous == (Image *) NULL)
1243 {
1244 status=SetImageProgress(image,LoadImageTag,y,image->rows);
1245 if (status == MagickFalse)
1246 break;
1247 }
1248 }
1249 break;
1250 }
1251 default:
1252 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1253 }
1254 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1255 if (EOFBlob(image) != MagickFalse)
1256 {
1257 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
1258 image->filename);
1259 break;
1260 }
1261 if (bmp_info.height < 0)
1262 {
1263 Image
1264 *flipped_image;
1265
1266 /*
1267 Correct image orientation.
1268 */
1269 flipped_image=FlipImage(image,exception);
1270 if (flipped_image == (Image *) NULL)
1271 {
1272 image=DestroyImageList(image);
1273 return((Image *) NULL);
1274 }
1275 DuplicateBlob(flipped_image,image);
1276 image=DestroyImage(image);
1277 image=flipped_image;
1278 }
1279 /*
1280 Proceed to next image.
1281 */
1282 if (image_info->number_scenes != 0)
1283 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1284 break;
1285 *magick='\0';
1286 if (bmp_info.ba_offset != 0)
1287 {
1288 offset=SeekBlob(image,(MagickOffsetType) bmp_info.ba_offset,SEEK_SET);
1289 if (offset < 0)
1290 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1291 }
1292 count=ReadBlob(image,2,magick);
1293 if ((count == 2) && (IsBMP(magick,2) != MagickFalse))
1294 {
1295 /*
1296 Acquire next image structure.
1297 */
1298 AcquireNextImage(image_info,image);
1299 if (GetNextImageInList(image) == (Image *) NULL)
1300 {
1301 image=DestroyImageList(image);
1302 return((Image *) NULL);
1303 }
1304 image=SyncNextImageInList(image);
1305 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
1306 GetBlobSize(image));
1307 if (status == MagickFalse)
1308 break;
1309 }
1310 } while (IsBMP(magick,2) != MagickFalse);
1311 (void) CloseBlob(image);
1312 return(GetFirstImageInList(image));
1313}
1314
1315/*
1316%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1317% %
1318% %
1319% %
1320% R e g i s t e r B M P I m a g e %
1321% %
1322% %
1323% %
1324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1325%
1326% RegisterBMPImage() adds attributes for the BMP image format to
1327% the list of supported formats. The attributes include the image format
1328% tag, a method to read and/or write the format, whether the format
1329% supports the saving of more than one frame to the same file or blob,
1330% whether the format supports native in-memory I/O, and a brief
1331% description of the format.
1332%
1333% The format of the RegisterBMPImage method is:
1334%
1335% unsigned long RegisterBMPImage(void)
1336%
1337*/
1338ModuleExport unsigned long RegisterBMPImage(void)
1339{
1340 MagickInfo
1341 *entry;
1342
1343 entry=SetMagickInfo("BMP");
1344 entry->decoder=(DecodeImageHandler *) ReadBMPImage;
1345 entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1346 entry->magick=(IsImageFormatHandler *) IsBMP;
1347 entry->description=ConstantString("Microsoft Windows bitmap image");
1348 entry->module=ConstantString("BMP");
1349 entry->adjoin=MagickFalse;
1350 entry->seekable_stream=MagickTrue;
1351 (void) RegisterMagickInfo(entry);
1352 entry=SetMagickInfo("BMP2");
1353 entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1354 entry->magick=(IsImageFormatHandler *) IsBMP;
1355 entry->description=ConstantString("Microsoft Windows bitmap image v2");
1356 entry->module=ConstantString("BMP");
1357 entry->adjoin=MagickFalse;
1358 entry->seekable_stream=MagickTrue;
1359 (void) RegisterMagickInfo(entry);
1360 entry=SetMagickInfo("BMP3");
1361 entry->encoder=(EncodeImageHandler *) WriteBMPImage;
1362 entry->magick=(IsImageFormatHandler *) IsBMP;
1363 entry->description=ConstantString("Microsoft Windows bitmap image v3");
1364 entry->module=ConstantString("BMP");
1365 entry->adjoin=MagickFalse;
1366 entry->seekable_stream=MagickTrue;
1367 (void) RegisterMagickInfo(entry);
1368 return(MagickImageCoderSignature);
1369}
1370
1371/*
1372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1373% %
1374% %
1375% %
1376% U n r e g i s t e r B M P I m a g e %
1377% %
1378% %
1379% %
1380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1381%
1382% UnregisterBMPImage() removes format registrations made by the
1383% BMP module from the list of supported formats.
1384%
1385% The format of the UnregisterBMPImage method is:
1386%
1387% UnregisterBMPImage(void)
1388%
1389*/
1390ModuleExport void UnregisterBMPImage(void)
1391{
1392 (void) UnregisterMagickInfo("BMP");
1393 (void) UnregisterMagickInfo("BMP2");
1394 (void) UnregisterMagickInfo("BMP3");
1395}
1396
1397/*
1398%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1399% %
1400% %
1401% %
1402% W r i t e B M P I m a g e %
1403% %
1404% %
1405% %
1406%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1407%
1408% WriteBMPImage() writes an image in Microsoft Windows bitmap encoded
1409% image format, version 3 for Windows or (if the image has a matte channel)
1410% version 4.
1411%
1412% The format of the WriteBMPImage method is:
1413%
1414% MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image)
1415%
1416% A description of each parameter follows.
1417%
1418% o image_info: the image info.
1419%
1420% o image: The image.
1421%
1422*/
1423static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image)
1424{
1425 BMPInfo
1426 bmp_info;
1427
1428 const StringInfo
1429 *profile;
1430
1431 long
1432 y;
1433
1434 MagickBooleanType
1435 have_color_info,
1436 status;
1437
1438 MagickOffsetType
1439 scene;
1440
1441 register const IndexPacket
1442 *indexes;
1443
1444 register const PixelPacket
1445 *p;
1446
1447 register long
1448 i,
1449 x;
1450
1451 register unsigned char
1452 *q;
1453
1454 unsigned char
1455 *bmp_data,
1456 *pixels;
1457
1458 unsigned long
1459 bytes_per_line,
1460 type;
1461
1462 /*
1463 Open output image file.
1464 */
1465 assert(image_info != (const ImageInfo *) NULL);
1466 assert(image_info->signature == MagickSignature);
1467 assert(image != (Image *) NULL);
1468 assert(image->signature == MagickSignature);
1469 if (image->debug != MagickFalse)
1470 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1471 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1472 if (status == MagickFalse)
1473 return(status);
1474 type=4;
1475 if (LocaleCompare(image_info->magick,"BMP2") == 0)
1476 type=2;
1477 else
1478 if (LocaleCompare(image_info->magick,"BMP3") == 0)
1479 type=3;
1480 scene=0;
1481 do
1482 {
1483 /*
1484 Initialize BMP raster file header.
1485 */
1486 if (image->colorspace != RGBColorspace)
1487 (void) TransformImageColorspace(image,RGBColorspace);
1488 (void) ResetMagickMemory(&bmp_info,0,sizeof(bmp_info));
1489 bmp_info.file_size=14+12;
1490 if (type > 2)
1491 bmp_info.file_size+=28;
1492 bmp_info.offset_bits=bmp_info.file_size;
1493 bmp_info.compression=BI_RGB;
1494 if ((image->storage_class == PseudoClass) && (image->colors > 256))
1495 (void) SetImageStorageClass(image,DirectClass);
1496 if (image->storage_class != DirectClass)
1497 {
1498 /*
1499 Colormapped BMP raster.
1500 */
1501 bmp_info.bits_per_pixel=8;
1502 if (image->colors <= 2)
1503 bmp_info.bits_per_pixel=1;
1504 else
1505 if (image->colors <= 16)
1506 bmp_info.bits_per_pixel=4;
1507 else
1508 if (image->colors <= 256)
1509 bmp_info.bits_per_pixel=8;
1510 if (image_info->compression == RLECompression)
1511 bmp_info.bits_per_pixel=8;
1512 bmp_info.number_colors=1U << bmp_info.bits_per_pixel;
1513 if (image->matte != MagickFalse)
1514 (void) SetImageStorageClass(image,DirectClass);
1515 else
1516 if ((unsigned long) bmp_info.number_colors < image->colors)
1517 (void) SetImageStorageClass(image,DirectClass);
1518 else
1519 {
1520 bmp_info.file_size+=3*(1UL << bmp_info.bits_per_pixel);
1521 bmp_info.offset_bits+=3*(1UL << bmp_info.bits_per_pixel);
1522 if (type > 2)
1523 {
1524 bmp_info.file_size+=(1UL << bmp_info.bits_per_pixel);
1525 bmp_info.offset_bits+=(1UL << bmp_info.bits_per_pixel);
1526 }
1527 }
1528 }
1529 if (image->storage_class == DirectClass)
1530 {
1531 /*
1532 Full color BMP raster.
1533 */
1534 bmp_info.number_colors=0;
1535 bmp_info.bits_per_pixel=(unsigned short)
1536 ((type > 3) && (image->matte != MagickFalse) ? 32 : 24);
1537 bmp_info.compression=(unsigned int) ((type > 3) &&
1538 (image->matte != MagickFalse) ? BI_BITFIELDS : BI_RGB);
1539 }
1540 bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);
1541 bmp_info.ba_offset=0;
1542 profile=GetImageProfile(image,"icc");
1543 have_color_info=(image->rendering_intent != UndefinedIntent) ||
1544 (profile != (StringInfo *) NULL) || (image->gamma != 0.0) ? MagickTrue :
1545 MagickFalse;
1546 if (type == 2)
1547 bmp_info.size=12;
1548 else
1549 if ((type == 3) || ((image->matte == MagickFalse) &&
1550 (have_color_info == MagickFalse)))
1551 {
1552 type=3;
1553 bmp_info.size=40;
1554 }
1555 else
1556 {
1557 int
1558 extra_size;
1559
1560 bmp_info.size=108;
1561 extra_size=68;
1562 if ((image->rendering_intent != UndefinedIntent) ||
1563 (profile != (StringInfo *) NULL))
1564 {
1565 bmp_info.size=124;
1566 extra_size+=16;
1567 }
1568 bmp_info.file_size+=extra_size;
1569 bmp_info.offset_bits+=extra_size;
1570 }
1571 bmp_info.width=(long) image->columns;
1572 bmp_info.height=(long) image->rows;
1573 bmp_info.planes=1;
1574 bmp_info.image_size=(unsigned int) (bytes_per_line*image->rows);
1575 bmp_info.file_size+=bmp_info.image_size;
1576 bmp_info.x_pixels=75*39;
1577 bmp_info.y_pixels=75*39;
1578 switch (image->units)
1579 {
1580 case UndefinedResolution:
1581 case PixelsPerInchResolution:
1582 {
1583 bmp_info.x_pixels=(unsigned int) (100.0*image->x_resolution/2.54);
1584 bmp_info.y_pixels=(unsigned int) (100.0*image->y_resolution/2.54);
1585 break;
1586 }
1587 case PixelsPerCentimeterResolution:
1588 {
1589 bmp_info.x_pixels=(unsigned int) (100.0*image->x_resolution);
1590 bmp_info.y_pixels=(unsigned int) (100.0*image->y_resolution);
1591 break;
1592 }
1593 }
1594 bmp_info.colors_important=bmp_info.number_colors;
1595 /*
1596 Convert MIFF to BMP raster pixels.
1597 */
1598 pixels=(unsigned char *) AcquireQuantumMemory((size_t) bmp_info.image_size,
1599 sizeof(*pixels));
1600 if (pixels == (unsigned char *) NULL)
1601 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1602 (void) ResetMagickMemory(pixels,0,(size_t) bmp_info.image_size);
1603 switch (bmp_info.bits_per_pixel)
1604 {
1605 case 1:
1606 {
1607 unsigned long
1608 bit,
1609 byte;
1610
1611 /*
1612 Convert PseudoClass image to a BMP monochrome image.
1613 */
1614 for (y=0; y < (long) image->rows; y++)
1615 {
1616 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1617 if (p == (const PixelPacket *) NULL)
1618 break;
1619 indexes=GetVirtualIndexQueue(image);
1620 q=pixels+(image->rows-y-1)*bytes_per_line;
1621 bit=0;
1622 byte=0;
1623 for (x=0; x < (long) image->columns; x++)
1624 {
1625 byte<<=1;
1626 byte|=indexes[x] != 0 ? 0x01 : 0x00;
1627 bit++;
1628 if (bit == 8)
1629 {
1630 *q++=(unsigned char) byte;
1631 bit=0;
1632 byte=0;
1633 }
1634 }
1635 if (bit != 0)
1636 {
1637 *q++=(unsigned char) (byte << (8-bit));
1638 x++;
1639 }
1640 for (x=(long) (image->columns+7)/8; x < (long) bytes_per_line; x++)
1641 *q++=0x00;
1642 if (image->previous == (Image *) NULL)
1643 {
1644 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1645 if (status == MagickFalse)
1646 break;
1647 }
1648 }
1649 break;
1650 }
1651 case 4:
1652 {
1653 unsigned long
1654 nibble,
1655 byte;
1656
1657 /*
1658 Convert PseudoClass image to a BMP monochrome image.
1659 */
1660 for (y=0; y < (long) image->rows; y++)
1661 {
1662 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1663 if (p == (const PixelPacket *) NULL)
1664 break;
1665 indexes=GetVirtualIndexQueue(image);
1666 q=pixels+(image->rows-y-1)*bytes_per_line;
1667 nibble=0;
1668 byte=0;
1669 for (x=0; x < (long) image->columns; x++)
1670 {
1671 byte<<=4;
1672 byte|=((unsigned long) indexes[x] & 0x0f);
1673 nibble++;
1674 if (nibble == 2)
1675 {
1676 *q++=(unsigned char) byte;
1677 nibble=0;
1678 byte=0;
1679 }
1680 }
1681 if (nibble != 0)
1682 {
1683 *q++=(unsigned char) (byte << 4);
1684 x++;
1685 }
1686 for (x=(long) (image->columns+1)/2; x < (long) bytes_per_line; x++)
1687 *q++=0x00;
1688 if (image->previous == (Image *) NULL)
1689 {
1690 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1691 if (status == MagickFalse)
1692 break;
1693 }
1694 }
1695 break;
1696 }
1697 case 8:
1698 {
1699 /*
1700 Convert PseudoClass packet to BMP pixel.
1701 */
1702 for (y=0; y < (long) image->rows; y++)
1703 {
1704 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1705 if (p == (const PixelPacket *) NULL)
1706 break;
1707 indexes=GetVirtualIndexQueue(image);
1708 q=pixels+(image->rows-y-1)*bytes_per_line;
1709 for (x=0; x < (long) image->columns; x++)
1710 *q++=(unsigned char) indexes[x];
1711 for ( ; x < (long) bytes_per_line; x++)
1712 *q++=0x00;
1713 if (image->previous == (Image *) NULL)
1714 {
1715 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1716 if (status == MagickFalse)
1717 break;
1718 }
1719 }
1720 break;
1721 }
1722 case 24:
1723 {
1724 /*
1725 Convert DirectClass packet to BMP BGR888.
1726 */
1727 for (y=0; y < (long) image->rows; y++)
1728 {
1729 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1730 if (p == (const PixelPacket *) NULL)
1731 break;
1732 q=pixels+(image->rows-y-1)*bytes_per_line;
1733 for (x=0; x < (long) image->columns; x++)
1734 {
1735 *q++=ScaleQuantumToChar(p->blue);
1736 *q++=ScaleQuantumToChar(p->green);
1737 *q++=ScaleQuantumToChar(p->red);
1738 p++;
1739 }
1740 for (x=3L*(long) image->columns; x < (long) bytes_per_line; x++)
1741 *q++=0x00;
1742 if (image->previous == (Image *) NULL)
1743 {
1744 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1745 if (status == MagickFalse)
1746 break;
1747 }
1748 }
1749 break;
1750 }
1751 case 32:
1752 {
1753 /*
1754 Convert DirectClass packet to ARGB8888 pixel.
1755 */
1756 for (y=0; y < (long) image->rows; y++)
1757 {
1758 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1759 if (p == (const PixelPacket *) NULL)
1760 break;
1761 q=pixels+(image->rows-y-1)*bytes_per_line;
1762 for (x=0; x < (long) image->columns; x++)
1763 {
1764 *q++=ScaleQuantumToChar(p->blue);
1765 *q++=ScaleQuantumToChar(p->green);
1766 *q++=ScaleQuantumToChar(p->red);
1767 *q++=ScaleQuantumToChar(p->opacity);
1768 p++;
1769 }
1770 if (image->previous == (Image *) NULL)
1771 {
1772 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1773 if (status == MagickFalse)
1774 break;
1775 }
1776 }
1777 break;
1778 }
1779 }
1780 if ((type > 2) && (bmp_info.bits_per_pixel == 8))
1781 if (image_info->compression != NoCompression)
1782 {
1783 size_t
1784 length;
1785
1786 /*
1787 Convert run-length encoded raster pixels.
1788 */
1789 length=(size_t) (2*(bytes_per_line+2)*(image->rows+2)+2);
1790 bmp_data=(unsigned char *) NULL;
1791 if (~length >= bytes_per_line)
1792 bmp_data=(unsigned char *) AcquireQuantumMemory(length+
1793 bytes_per_line,sizeof(*bmp_data));
1794 if (bmp_data == (unsigned char *) NULL)
1795 {
1796 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1797 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1798 }
1799 bmp_info.file_size-=bmp_info.image_size;
1800 bmp_info.image_size=(unsigned int) EncodeImage(image,bytes_per_line,
1801 pixels,bmp_data);
1802 bmp_info.file_size+=bmp_info.image_size;
1803 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1804 pixels=bmp_data;
1805 bmp_info.compression=BI_RLE8;
1806 }
1807 /*
1808 Write BMP for Windows, all versions, 14-byte header.
1809 */
1810 if (image->debug != MagickFalse)
1811 {
1812 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1813 " Writing BMP version %ld datastream",type);
1814 if (image->storage_class == DirectClass)
1815 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1816 " Storage class=DirectClass");
1817 else
1818 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1819 " Storage class=PseudoClass");
1820 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1821 " Image depth=%lu",image->depth);
1822 if (image->matte != MagickFalse)
1823 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1824 " Matte=True");
1825 else
1826 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1827 " Matte=MagickFalse");
1828 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1829 " BMP bits_per_pixel=%d",bmp_info.bits_per_pixel);
1830 switch ((int) bmp_info.compression)
1831 {
1832 case BI_RGB:
1833 {
1834 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1835 " Compression=BI_RGB");
1836 break;
1837 }
1838 case BI_RLE8:
1839 {
1840 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1841 " Compression=BI_RLE8");
1842 break;
1843 }
1844 case BI_BITFIELDS:
1845 {
1846 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1847 " Compression=BI_BITFIELDS");
1848 break;
1849 }
1850 default:
1851 {
1852 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1853 " Compression=UNKNOWN (%u)",bmp_info.compression);
1854 break;
1855 }
1856 }
1857 if (bmp_info.number_colors == 0)
1858 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1859 " Number_colors=unspecified");
1860 else
1861 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1862 " Number_colors=%u",bmp_info.number_colors);
1863 }
1864 (void) WriteBlob(image,2,(unsigned char *) "BM");
1865 (void) WriteBlobLSBLong(image,bmp_info.file_size);
1866 (void) WriteBlobLSBLong(image,bmp_info.ba_offset); /* always 0 */
1867 (void) WriteBlobLSBLong(image,bmp_info.offset_bits);
1868 if (type == 2)
1869 {
1870 /*
1871 Write 12-byte version 2 bitmap header.
1872 */
1873 (void) WriteBlobLSBLong(image,bmp_info.size);
1874 (void) WriteBlobLSBShort(image,(unsigned short) bmp_info.width);
1875 (void) WriteBlobLSBShort(image,(unsigned short) bmp_info.height);
1876 (void) WriteBlobLSBShort(image,bmp_info.planes);
1877 (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);
1878 }
1879 else
1880 {
1881 /*
1882 Write 40-byte version 3+ bitmap header.
1883 */
1884 (void) WriteBlobLSBLong(image,bmp_info.size);
1885 (void) WriteBlobLSBLong(image,(unsigned int) bmp_info.width);
1886 (void) WriteBlobLSBLong(image,(unsigned int) bmp_info.height);
1887 (void) WriteBlobLSBShort(image,bmp_info.planes);
1888 (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);
1889 (void) WriteBlobLSBLong(image,bmp_info.compression);
1890 (void) WriteBlobLSBLong(image,bmp_info.image_size);
1891 (void) WriteBlobLSBLong(image,bmp_info.x_pixels);
1892 (void) WriteBlobLSBLong(image,bmp_info.y_pixels);
1893 (void) WriteBlobLSBLong(image,bmp_info.number_colors);
1894 (void) WriteBlobLSBLong(image,bmp_info.colors_important);
1895 }
1896 if ((type > 3) && ((image->matte != MagickFalse) ||
1897 (have_color_info != MagickFalse)))
1898 {
1899 /*
1900 Write the rest of the 108-byte BMP Version 4 header.
1901 */
1902 (void) WriteBlobLSBLong(image,0x00ff0000U); /* Red mask */
1903 (void) WriteBlobLSBLong(image,0x0000ff00U); /* Green mask */
1904 (void) WriteBlobLSBLong(image,0x000000ffU); /* Blue mask */
1905 (void) WriteBlobLSBLong(image,0xff000000U); /* Alpha mask */
1906 (void) WriteBlobLSBLong(image,0x00000001U); /* CSType==Calib. RGB */
1907 (void) WriteBlobLSBLong(image,(unsigned int)
1908 image->chromaticity.red_primary.x*0x3ffffff);
1909 (void) WriteBlobLSBLong(image,(unsigned int)
1910 image->chromaticity.red_primary.y*0x3ffffff);
1911 (void) WriteBlobLSBLong(image,(unsigned int)
1912 (1.000f-(image->chromaticity.red_primary.x+
1913 image->chromaticity.red_primary.y)*0x3ffffff));
1914 (void) WriteBlobLSBLong(image,(unsigned int)
1915 image->chromaticity.green_primary.x*0x3ffffff);
1916 (void) WriteBlobLSBLong(image,(unsigned int)
1917 image->chromaticity.green_primary.y*0x3ffffff);
1918 (void) WriteBlobLSBLong(image,(unsigned int)
1919 (1.000f-(image->chromaticity.green_primary.x+
1920 image->chromaticity.green_primary.y)*0x3ffffff));
1921 (void) WriteBlobLSBLong(image,(unsigned int)
1922 image->chromaticity.blue_primary.x*0x3ffffff);
1923 (void) WriteBlobLSBLong(image,(unsigned int)
1924 image->chromaticity.blue_primary.y*0x3ffffff);
1925 (void) WriteBlobLSBLong(image,(unsigned int)
1926 (1.000f-(image->chromaticity.blue_primary.x+
1927 image->chromaticity.blue_primary.y)*0x3ffffff));
1928 (void) WriteBlobLSBLong(image,(unsigned int)
1929 bmp_info.gamma_scale.x*0xffff);
1930 (void) WriteBlobLSBLong(image,(unsigned int)
1931 bmp_info.gamma_scale.y*0xffff);
1932 (void) WriteBlobLSBLong(image,(unsigned int)
1933 bmp_info.gamma_scale.z*0xffff);
1934 if ((image->rendering_intent != UndefinedIntent) ||
1935 (profile != (StringInfo *) NULL))
1936 {
1937 long
1938 intent;
1939
1940 switch ((int) image->rendering_intent)
1941 {
1942 case SaturationIntent:
1943 {
1944 intent=LCS_GM_BUSINESS;
1945 break;
1946 }
1947 case RelativeIntent:
1948 {
1949 intent=LCS_GM_GRAPHICS;
1950 break;
1951 }
1952 case PerceptualIntent:
1953 {
1954 intent=LCS_GM_IMAGES;
1955 break;
1956 }
1957 case AbsoluteIntent:
1958 {
1959 intent=LCS_GM_ABS_COLORIMETRIC;
1960 break;
1961 }
1962 default:
1963 {
1964 intent=0;
1965 break;
1966 }
1967 }
1968 (void) WriteBlobLSBLong(image,(unsigned int) intent);
1969 (void) WriteBlobLSBLong(image,0x00); /* dummy profile data */
1970 (void) WriteBlobLSBLong(image,0x00); /* dummy profile length */
1971 (void) WriteBlobLSBLong(image,0x00); /* reserved */
1972 }
1973 }
1974 if (image->storage_class == PseudoClass)
1975 {
1976 unsigned char
1977 *bmp_colormap;
1978
1979 /*
1980 Dump colormap to file.
1981 */
1982 if (image->debug != MagickFalse)
1983 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1984 " Colormap: %ld entries",image->colors);
1985 bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t) (1UL <<
1986 bmp_info.bits_per_pixel),4*sizeof(*bmp_colormap));
1987 if (bmp_colormap == (unsigned char *) NULL)
1988 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1989 q=bmp_colormap;
1990 for (i=0; i < (long) MagickMin((long) image->colors,(long) bmp_info.number_colors); i++)
1991 {
1992 *q++=ScaleQuantumToChar(image->colormap[i].blue);
1993 *q++=ScaleQuantumToChar(image->colormap[i].green);
1994 *q++=ScaleQuantumToChar(image->colormap[i].red);
1995 if (type > 2)
1996 *q++=(unsigned char) 0x0;
1997 }
1998 for ( ; i < (long) (1UL << bmp_info.bits_per_pixel); i++)
1999 {
2000 *q++=(unsigned char) 0x00;
2001 *q++=(unsigned char) 0x00;
2002 *q++=(unsigned char) 0x00;
2003 if (type > 2)
2004 *q++=(unsigned char) 0x00;
2005 }
2006 if (type <= 2)
2007 (void) WriteBlob(image,(size_t) (3*(1L << bmp_info.bits_per_pixel)),
2008 bmp_colormap);
2009 else
2010 (void) WriteBlob(image,(size_t) (4*(1L << bmp_info.bits_per_pixel)),
2011 bmp_colormap);
2012 bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
2013 }
2014 if (image->debug != MagickFalse)
2015 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2016 " Pixels: %u bytes",bmp_info.image_size);
2017 (void) WriteBlob(image,(size_t) bmp_info.image_size,pixels);
2018 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2019 if (GetNextImageInList(image) == (Image *) NULL)
2020 break;
2021 image=SyncNextImageInList(image);
2022 status=SetImageProgress(image,SaveImagesTag,scene++,
2023 GetImageListLength(image));
2024 if (status == MagickFalse)
2025 break;
2026 } while (image_info->adjoin != MagickFalse);
2027 (void) CloseBlob(image);
2028 return(MagickTrue);
2029}