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