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