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