Powered by Pair ImageMagick logo
Image Magick
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Globals | Related Pages

ImageMagick-6.1.1/coders/bmp.c

Go to the documentation of this file.
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % BBBB M M PPPP % 00007 % B B MM MM P P % 00008 % BBBB M M M PPPP % 00009 % B B M M P % 00010 % BBBB M M P % 00011 % % 00012 % % 00013 % Read/Write Microsoft Windows Bitmap Image Format. % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % Glenn Randers-Pehrson % 00018 % December 2001 % 00019 % % 00020 % % 00021 % Copyright 1999-2004 ImageMagick Studio LLC, a non-profit organization % 00022 % dedicated to making software imaging solutions freely available. % 00023 % % 00024 % You may not use this file except in compliance with the License. You may % 00025 % obtain a copy of the License at % 00026 % % 00027 % http://www.imagemagick.org/www/Copyright.html % 00028 % % 00029 % Unless required by applicable law or agreed to in writing, software % 00030 % distributed under the License is distributed on an "AS IS" BASIS, % 00031 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00032 % See the License for the specific language governing permissions and % 00033 % limitations under the License. % 00034 % % 00035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00036 % 00037 % 00038 */ 00039 00040 /* 00041 Include declarations. 00042 */ 00043 #include "magick/studio.h" 00044 #include "magick/blob.h" 00045 #include "magick/blob_private.h" 00046 #include "magick/color_private.h" 00047 #include "magick/colorspace.h" 00048 #include "magick/error.h" 00049 #include "magick/error_private.h" 00050 #include "magick/image.h" 00051 #include "magick/image_private.h" 00052 #include "magick/list.h" 00053 #include "magick/log.h" 00054 #include "magick/magick.h" 00055 #include "magick/memory_.h" 00056 #include "magick/monitor.h" 00057 #include "magick/profile.h" 00058 #include "magick/static.h" 00059 #include "magick/string_.h" 00060 #include "magick/transform.h" 00061 00062 /* 00063 Macro definitions (from Windows wingdi.h). 00064 */ 00065 #undef BI_JPEG 00066 #define BI_JPEG 4 00067 #undef BI_PNG 00068 #define BI_PNG 5 00069 #if !defined(__WINDOWS__) || defined(__MINGW32__) 00070 #define BI_RGB 0 00071 #define BI_RLE8 1 00072 #define BI_RLE4 2 00073 #define BI_BITFIELDS 3 00074 00075 #define LCS_CALIBRATED_RBG 0 00076 #define LCS_sRGB 1 00077 #define LCS_WINDOWS_COLOR_SPACE 2 00078 #define PROFILE_LINKED 3 00079 #define PROFILE_EMBEDDED 4 00080 00081 #define LCS_GM_BUSINESS 1 /* Saturation */ 00082 #define LCS_GM_GRAPHICS 2 /* Relative */ 00083 #define LCS_GM_IMAGES 4 /* Perceptual */ 00084 #define LCS_GM_ABS_COLORIMETRIC 8 /* Absolute */ 00085 #endif 00086 00087 /* 00088 Typedef declarations. 00089 */ 00090 typedef struct _BMPInfo 00091 { 00092 unsigned long 00093 file_size, 00094 ba_offset, 00095 offset_bits, 00096 size; 00097 00098 long 00099 width, 00100 height; 00101 00102 unsigned short 00103 planes, 00104 bits_per_pixel; 00105 00106 unsigned long 00107 compression, 00108 image_size, 00109 x_pixels, 00110 y_pixels, 00111 number_colors, 00112 red_mask, 00113 green_mask, 00114 blue_mask, 00115 alpha_mask, 00116 colors_important; 00117 00118 long 00119 colorspace; 00120 00121 PrimaryInfo 00122 red_primary, 00123 green_primary, 00124 blue_primary, 00125 gamma_scale; 00126 } BMPInfo; 00127 00128 /* 00129 Forward declarations. 00130 */ 00131 static MagickBooleanType 00132 WriteBMPImage(const ImageInfo *,Image *); 00133 00134 /* 00135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00136 % % 00137 % % 00138 % % 00139 % D e c o d e I m a g e % 00140 % % 00141 % % 00142 % % 00143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00144 % 00145 % DecodeImage unpacks the packed image pixels into runlength-encoded 00146 % pixel packets. 00147 % 00148 % The format of the DecodeImage method is: 00149 % 00150 % MagickBooleanType DecodeImage(Image *image, 00151 % const MagickBooleanType compression,unsigned char *pixels) 00152 % 00153 % A description of each parameter follows: 00154 % 00155 % o image: The address of a structure of type Image. 00156 % 00157 % o compression: Zero means uncompressed. A value of 1 means the 00158 % compressed pixels are runlength encoded for a 256-color bitmap. 00159 % A value of 2 means a 16-color bitmap. A value of 3 means bitfields 00160 % encoding. 00161 % 00162 % o pixels: The address of a byte (8 bits) array of pixel data created by 00163 % the decoding process. 00164 % 00165 % 00166 */ 00167 static MagickBooleanType DecodeImage(Image *image, 00168 const MagickBooleanType compression,unsigned char *pixels) 00169 { 00170 int 00171 count; 00172 00173 long 00174 y; 00175 00176 MagickBooleanType 00177 status; 00178 00179 register long 00180 i, 00181 x; 00182 00183 register unsigned char 00184 *p, 00185 *q; 00186 00187 unsigned char 00188 byte; 00189 00190 assert(image != (Image *) NULL); 00191 assert(image->signature == MagickSignature); 00192 if (image->debug != MagickFalse) 00193 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 00194 assert(pixels != (unsigned char *) NULL); 00195 (void) ResetMagickMemory(pixels,0,(size_t) image->columns*image->rows* 00196 sizeof(*pixels)); 00197 byte=0; 00198 x=0; 00199 p=pixels; 00200 q=pixels+(size_t) image->columns*image->rows; 00201 for (y=0; y < (long) image->rows; ) 00202 { 00203 if ((p < pixels) || (p >= q)) 00204 break; 00205 count=ReadBlobByte(image); 00206 if (count == EOF) 00207 break; 00208 if (count != 0) 00209 { 00210 /* 00211 Encoded mode. 00212 */ 00213 count=Min(count,(int) (q-p)); 00214 byte=(unsigned char) ReadBlobByte(image); 00215 if (compression == BI_RLE8) 00216 { 00217 for (i=0; i < count; i++) 00218 *p++=(unsigned char) byte; 00219 } 00220 else 00221 { 00222 for (i=0; i < count; i++) 00223 *p++=(unsigned char) 00224 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f)); 00225 } 00226 x+=count; 00227 } 00228 else 00229 { 00230 /* 00231 Escape mode. 00232 */ 00233 count=ReadBlobByte(image); 00234 if (count == 0x01) 00235 return(MagickTrue); 00236 switch (count) 00237 { 00238 case 0x00: 00239 { 00240 /* 00241 End of line. 00242 */ 00243 x=0; 00244 y++; 00245 p=pixels+y*image->columns; 00246 break; 00247 } 00248 case 0x02: 00249 { 00250 /* 00251 Delta mode. 00252 */ 00253 x+=ReadBlobByte(image); 00254 y+=ReadBlobByte(image); 00255 p=pixels+y*image->columns+x; 00256 break; 00257 } 00258 default: 00259 { 00260 /* 00261 Absolute mode. 00262 */ 00263 count=Min(count,(int) (q-p)); 00264 if (compression == BI_RLE8) 00265 for (i=0; i < count; i++) 00266 *p++=(unsigned char) ReadBlobByte(image); 00267 else 00268 for (i=0; i < count; i++) 00269 { 00270 if ((i & 0x01) == 0) 00271 byte=(unsigned char) ReadBlobByte(image); 00272 *p++=(unsigned char) 00273 ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f)); 00274 } 00275 x+=count; 00276 /* 00277 Read pad byte. 00278 */ 00279 if (compression == BI_RLE8) 00280 { 00281 if ((count & 0x01) != 0) 00282 (void) ReadBlobByte(image); 00283 } 00284 else 00285 if (((count & 0x03) == 1) || ((count & 0x03) == 2)) 00286 (void) ReadBlobByte(image); 00287 break; 00288 } 00289 } 00290 } 00291 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 00292 (QuantumTick(y,image->rows) != MagickFalse)) 00293 { 00294 status=image->progress_monitor(LoadImageTag,y,image->rows, 00295 image->client_data); 00296 if (status == MagickFalse) 00297 break; 00298 } 00299 } 00300 (void) ReadBlobByte(image); /* end of line */ 00301 (void) ReadBlobByte(image); 00302 return(MagickTrue); 00303 } 00304 00305 /* 00306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00307 % % 00308 % % 00309 % % 00310 % E n c o d e I m a g e % 00311 % % 00312 % % 00313 % % 00314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00315 % 00316 % EncodeImage compresses pixels using a runlength encoded format. 00317 % 00318 % The format of the EncodeImage method is: 00319 % 00320 % static MagickBooleanType EncodeImage(Image *image, 00321 % const unsigned long bytes_per_line,const unsigned char *pixels, 00322 % unsigned char *compressed_pixels) 00323 % 00324 % A description of each parameter follows: 00325 % 00326 % o image: The image. 00327 % 00328 % o bytes_per_line: The number of bytes in a scanline of compressed pixels 00329 % 00330 % o pixels: The address of a byte (8 bits) array of pixel data created by 00331 % the compression process. 00332 % 00333 % o compressed_pixels: The address of a byte (8 bits) array of compressed 00334 % pixel data. 00335 % 00336 % 00337 */ 00338 static size_t EncodeImage(Image *image,const unsigned long bytes_per_line, 00339 const unsigned char *pixels,unsigned char *compressed_pixels) 00340 { 00341 long 00342 y; 00343 00344 MagickBooleanType 00345 status; 00346 00347 register const unsigned char 00348 *p; 00349 00350 register long 00351 i, 00352 x; 00353 00354 register unsigned char 00355 *q; 00356 00357 /* 00358 Runlength encode pixels. 00359 */ 00360 assert(image != (Image *) NULL); 00361 assert(image->signature == MagickSignature); 00362 if (image->debug != MagickFalse) 00363 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 00364 assert(pixels != (const unsigned char *) NULL); 00365 assert(compressed_pixels != (unsigned char *) NULL); 00366 p=pixels; 00367 q=compressed_pixels; 00368 i=0; 00369 for (y=0; y < (long) image->rows; y++) 00370 { 00371 for (x=0; x < (long) bytes_per_line; x+=i) 00372 { 00373 /* 00374 Determine runlength. 00375 */ 00376 for (i=1; ((x+i) < (long) bytes_per_line); i++) 00377 if ((i == 255) || (*(p+i) != *p)) 00378 break; 00379 *q++=(unsigned char) i; 00380 *q++=(*p); 00381 p+=i; 00382 } 00383 /* 00384 End of line. 00385 */ 00386 *q++=(unsigned char) 0x00; 00387 *q++=(unsigned char) 0x00; 00388 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 00389 (QuantumTick(y,image->rows) != MagickFalse)) 00390 { 00391 status=image->progress_monitor(SaveImageTag,y,image->rows, 00392 image->client_data); 00393 if (status == MagickFalse) 00394 break; 00395 } 00396 } 00397 /* 00398 End of bitmap. 00399 */ 00400 *q++=(unsigned char) 0x00; 00401 *q++=(unsigned char) 0x01; 00402 return((size_t) (q-compressed_pixels)); 00403 } 00404 00405 /* 00406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00407 % % 00408 % % 00409 % % 00410 % I s B M P % 00411 % % 00412 % % 00413 % % 00414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00415 % 00416 % IsBMP() returns MagickTrue if the image format type, identified by the 00417 % magick string, is BMP. 00418 % 00419 % The format of the IsBMP method is: 00420 % 00421 % MagickBooleanType IsBMP(const unsigned char *magick,const size_t length) 00422 % 00423 % A description of each parameter follows: 00424 % 00425 % o magick: This string is generally the first few bytes of an image file 00426 % or blob. 00427 % 00428 % o length: Specifies the length of the magick string. 00429 % 00430 % 00431 */ 00432 static MagickBooleanType IsBMP(const unsigned char *magick,const size_t length) 00433 { 00434 if (length < 2) 00435 return(MagickFalse); 00436 if ((LocaleNCompare((char *) magick,"BA",2) == 0) || 00437 (LocaleNCompare((char *) magick,"BM",2) == 0) || 00438 (LocaleNCompare((char *) magick,"IC",2) == 0) || 00439 (LocaleNCompare((char *) magick,"PI",2) == 0) || 00440 (LocaleNCompare((char *) magick,"CI",2) == 0) || 00441 (LocaleNCompare((char *) magick,"CP",2) == 0)) 00442 return(MagickTrue); 00443 return(MagickFalse); 00444 } 00445 00446 /* 00447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00448 % % 00449 % % 00450 % % 00451 % R e a d B M P I m a g e % 00452 % % 00453 % % 00454 % % 00455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00456 % 00457 % ReadBMPImage() reads a Microsoft Windows bitmap image file, Version 00458 % 2, 3 (for Windows or NT), or 4, and returns it. It allocates the memory 00459 % necessary for the new Image structure and returns a pointer to the new 00460 % image. 00461 % 00462 % The format of the ReadBMPImage method is: 00463 % 00464 % image=ReadBMPImage(image_info) 00465 % 00466 % A description of each parameter follows: 00467 % 00468 % o image_info: The image info. 00469 % 00470 % o exception: return any errors or warnings in this structure. 00471 % 00472 % 00473 */ 00474 static Image *ReadBMPImage(const ImageInfo *image_info,ExceptionInfo *exception) 00475 { 00476 BMPInfo 00477 bmp_info; 00478 00479 Image 00480 *image; 00481 00482 IndexPacket 00483 index; 00484 00485 long 00486 y; 00487 00488 MagickBooleanType 00489 status; 00490 00491 MagickOffsetType 00492 start_position; 00493 00494 register IndexPacket 00495 *indexes; 00496 00497 register long 00498 x; 00499 00500 register PixelPacket 00501 *q; 00502 00503 register long 00504 i; 00505 00506 register unsigned char 00507 *p; 00508 00509 ssize_t 00510 count; 00511 00512 size_t 00513 length; 00514 00515 unsigned char 00516 magick[12], 00517 *pixels; 00518 00519 unsigned long 00520 bit, 00521 blue, 00522 bytes_per_line, 00523 green, 00524 opacity, 00525 red; 00526 00527 /* 00528 Open image file. 00529 */ 00530 assert(image_info != (const ImageInfo *) NULL); 00531 assert(image_info->signature == MagickSignature); 00532 if (image_info->debug != MagickFalse) 00533 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image_info->filename); 00534 assert(exception != (ExceptionInfo *) NULL); 00535 assert(exception->signature == MagickSignature); 00536 image=AllocateImage(image_info); 00537 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 00538 if (status == MagickFalse) 00539 { 00540 DestroyImageList(image); 00541 return((Image *) NULL); 00542 } 00543 /* 00544 Determine if this is a BMP file. 00545 */ 00546 (void) ResetMagickMemory(&bmp_info,0,sizeof(bmp_info)); 00547 bmp_info.ba_offset=0; 00548 start_position=0; 00549 count=ReadBlob(image,2,magick); 00550 do 00551 { 00552 PixelPacket 00553 quantum_bits, 00554 shift; 00555 00556 unsigned long 00557 profile_data, 00558 profile_size; 00559 00560 /* 00561 Verify BMP identifier. 00562 */ 00563 if (bmp_info.ba_offset == 0) 00564 start_position=TellBlob(image)-2; 00565 bmp_info.ba_offset=0; 00566 while (LocaleNCompare((char *) magick,"BA",2) == 0) 00567 { 00568 bmp_info.file_size=ReadBlobLSBLong(image); 00569 bmp_info.ba_offset=ReadBlobLSBLong(image); 00570 bmp_info.offset_bits=ReadBlobLSBLong(image); 00571 count=ReadBlob(image,2,magick); 00572 if (count == 0) 00573 break; 00574 } 00575 if (image->debug != MagickFalse) 00576 (void) LogMagickEvent(CoderEvent,GetMagickModule()," Magick: %c%c", 00577 magick[0],magick[1]); 00578 if ((count == 0) || ((LocaleNCompare((char *) magick,"BM",2) != 0) && 00579 (LocaleNCompare((char *) magick,"CI",2) != 0))) 00580 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 00581 bmp_info.file_size=ReadBlobLSBLong(image); 00582 (void) ReadBlobLSBLong(image); 00583 bmp_info.offset_bits=ReadBlobLSBLong(image); 00584 bmp_info.size=ReadBlobLSBLong(image); 00585 if (image->debug != MagickFalse) 00586 (void) LogMagickEvent(CoderEvent,GetMagickModule()," BMP size: %lu", 00587 bmp_info.size); 00588 if (bmp_info.size == 12) 00589 { 00590 /* 00591 OS/2 BMP image file. 00592 */ 00593 bmp_info.width=(short) ReadBlobLSBShort(image); 00594 bmp_info.height=(short) ReadBlobLSBShort(image); 00595 bmp_info.planes=ReadBlobLSBShort(image); 00596 bmp_info.bits_per_pixel=ReadBlobLSBShort(image); 00597 bmp_info.x_pixels=0; 00598 bmp_info.y_pixels=0; 00599 bmp_info.number_colors=0; 00600 bmp_info.compression=BI_RGB; 00601 bmp_info.image_size=0; 00602 bmp_info.alpha_mask=0; 00603 if (image->debug != MagickFalse) 00604 { 00605 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00606 " Format: OS/2 Bitmap"); 00607 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00608 " Geometry: %ldx%ld",bmp_info.width,bmp_info.height); 00609 } 00610 } 00611 else 00612 { 00613 /* 00614 Microsoft Windows BMP image file. 00615 */ 00616 if (bmp_info.size < 40) 00617 ThrowReaderException(CorruptImageError,"NonOS2HeaderSizeError"); 00618 bmp_info.width=(short) ReadBlobLSBLong(image); 00619 bmp_info.height=(short) ReadBlobLSBLong(image); 00620 bmp_info.planes=ReadBlobLSBShort(image); 00621 bmp_info.bits_per_pixel=ReadBlobLSBShort(image); 00622 bmp_info.compression=ReadBlobLSBLong(image); 00623 bmp_info.image_size=ReadBlobLSBLong(image); 00624 bmp_info.x_pixels=ReadBlobLSBLong(image); 00625 bmp_info.y_pixels=ReadBlobLSBLong(image); 00626 bmp_info.number_colors=ReadBlobLSBLong(image); 00627 bmp_info.colors_important=ReadBlobLSBLong(image); 00628 profile_data=0; 00629 profile_size=0; 00630 if (image->debug != MagickFalse) 00631 { 00632 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00633 " Format: MS Windows bitmap"); 00634 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00635 " Geometry: %ldx%ld",bmp_info.width,bmp_info.height); 00636 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00637 " Bits per pixel: %d",bmp_info.bits_per_pixel); 00638 switch ((int) bmp_info.compression) 00639 { 00640 case BI_RGB: 00641 { 00642 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00643 " Compression: BI_RGB"); 00644 break; 00645 } 00646 case BI_RLE4: 00647 { 00648 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00649 " Compression: BI_RLE4"); 00650 break; 00651 } 00652 case BI_RLE8: 00653 { 00654 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00655 " Compression: BI_RLE8"); 00656 break; 00657 } 00658 case BI_BITFIELDS: 00659 { 00660 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00661 " Compression: BI_BITFIELDS"); 00662 break; 00663 } 00664 case BI_PNG: 00665 { 00666 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00667 " Compression: BI_PNG"); 00668 break; 00669 } 00670 case BI_JPEG: 00671 { 00672 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00673 " Compression: BI_JPEG"); 00674 break; 00675 } 00676 default: 00677 { 00678 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00679 " Compression: UNKNOWN (%lu)",bmp_info.compression); 00680 } 00681 } 00682 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00683 " Number of colors: %lu",bmp_info.number_colors); 00684 } 00685 bmp_info.red_mask=ReadBlobLSBLong(image); 00686 bmp_info.green_mask=ReadBlobLSBLong(image); 00687 bmp_info.blue_mask=ReadBlobLSBLong(image); 00688 if (bmp_info.size > 40) 00689 { 00690 double 00691 sum; 00692 00693 /* 00694 Read color management information. 00695 */ 00696 bmp_info.alpha_mask=ReadBlobLSBLong(image); 00697 bmp_info.colorspace=(long) ReadBlobLSBLong(image); 00698 /* 00699 Decode 2^30 fixed point formatted CIE primaries. 00700 */ 00701 bmp_info.red_primary.x=(double) 00702 ReadBlobLSBLong(image)/0x3ffffff; 00703 bmp_info.red_primary.y=(double) 00704 ReadBlobLSBLong(image)/0x3ffffff; 00705 bmp_info.red_primary.z=(double) 00706 ReadBlobLSBLong(image)/0x3ffffff; 00707 bmp_info.green_primary.x=(double) 00708 ReadBlobLSBLong(image)/0x3ffffff; 00709 bmp_info.green_primary.y=(double) 00710 ReadBlobLSBLong(image)/0x3ffffff; 00711 bmp_info.green_primary.z=(double) 00712 ReadBlobLSBLong(image)/0x3ffffff; 00713 bmp_info.blue_primary.x=(double) 00714 ReadBlobLSBLong(image)/0x3ffffff; 00715 bmp_info.blue_primary.y=(double) 00716 ReadBlobLSBLong(image)/0x3ffffff; 00717 bmp_info.blue_primary.z=(double) 00718 ReadBlobLSBLong(image)/0x3ffffff; 00719 sum=bmp_info.red_primary.x+bmp_info.red_primary.x+ 00720 bmp_info.red_primary.z; 00721 image->chromaticity.red_primary.x/=sum; 00722 image->chromaticity.red_primary.y/=sum; 00723 sum=bmp_info.green_primary.x+bmp_info.green_primary.x+ 00724 bmp_info.green_primary.z; 00725 image->chromaticity.green_primary.x/=sum; 00726 image->chromaticity.green_primary.y/=sum; 00727 sum=bmp_info.blue_primary.x+bmp_info.blue_primary.x+ 00728 bmp_info.blue_primary.z; 00729 image->chromaticity.blue_primary.x/=sum; 00730 image->chromaticity.blue_primary.y/=sum; 00731 /* 00732 Decode 16^16 fixed point formatted gamma_scales. 00733 */ 00734 bmp_info.gamma_scale.x=(double) ReadBlobLSBLong(image)/0xffff; 00735 bmp_info.gamma_scale.y=(double) ReadBlobLSBLong(image)/0xffff; 00736 bmp_info.gamma_scale.z=(double) ReadBlobLSBLong(image)/0xffff; 00737 /* 00738 Compute a single gamma from the BMP 3-channel gamma. 00739 */ 00740 image->gamma=(bmp_info.gamma_scale.x+bmp_info.gamma_scale.y+ 00741 bmp_info.gamma_scale.z)/3.0; 00742 } 00743 if (bmp_info.size > 108) 00744 { 00745 unsigned long 00746 intent; 00747 00748 /* 00749 Read BMP Version 5 color management information. 00750 */ 00751 intent=ReadBlobLSBLong(image); 00752 switch ((int) intent) 00753 { 00754 case LCS_GM_BUSINESS: 00755 { 00756 image->rendering_intent=SaturationIntent; 00757 break; 00758 } 00759 case LCS_GM_GRAPHICS: 00760 { 00761 image->rendering_intent=RelativeIntent; 00762 break; 00763 } 00764 case LCS_GM_IMAGES: 00765 { 00766 image->rendering_intent=PerceptualIntent; 00767 break; 00768 } 00769 case LCS_GM_ABS_COLORIMETRIC: 00770 { 00771 image->rendering_intent=AbsoluteIntent; 00772 break; 00773 } 00774 } 00775 profile_data=ReadBlobLSBLong(image); 00776 profile_size=ReadBlobLSBLong(image); 00777 (void) ReadBlobLSBLong(image); /* Reserved byte */ 00778 } 00779 } 00780 if ((bmp_info.compression != BI_RGB) && 00781 ((MagickSizeType) bmp_info.file_size != GetBlobSize(image))) 00782 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError, 00783 "LengthAndFilesizeDoNotMatch",image->filename); 00784 if (bmp_info.width <= 0) 00785 ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize"); 00786 if (bmp_info.height == 0) 00787 ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize"); 00788 if ((bmp_info.height < 0) && (bmp_info.compression !=0)) 00789 ThrowReaderException(CorruptImageError,"CompressionNotValid"); 00790 if (bmp_info.planes != 1) 00791 ThrowReaderException(CorruptImageError,"StaticPlanesValueNotEqualToOne"); 00792 if ((bmp_info.bits_per_pixel != 1) && (bmp_info.bits_per_pixel != 4) && 00793 (bmp_info.bits_per_pixel != 8) && (bmp_info.bits_per_pixel != 16) && 00794 (bmp_info.bits_per_pixel != 24) && (bmp_info.bits_per_pixel != 32)) 00795 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel"); 00796 if (bmp_info.number_colors > (1UL << bmp_info.bits_per_pixel)) 00797 ThrowReaderException(CorruptImageError,"UnrecognizedNumberOfColors"); 00798 if (bmp_info.compression > 3) 00799 ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression"); 00800 if ((bmp_info.compression == 1) && (bmp_info.bits_per_pixel != 8)) 00801 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel"); 00802 if ((bmp_info.compression == 2) && (bmp_info.bits_per_pixel != 4)) 00803 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel"); 00804 if ((bmp_info.compression == 3) && (bmp_info.bits_per_pixel < 16)) 00805 ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel"); 00806 switch (bmp_info.compression) 00807 { 00808 case BI_RGB: 00809 case BI_RLE8: 00810 case BI_RLE4: 00811 case BI_BITFIELDS: 00812 break; 00813 case BI_JPEG: 00814 ThrowReaderException(CoderError,"JPEGCompressionNotSupported"); 00815 case BI_PNG: 00816 ThrowReaderException(CoderError,"PNGCompressionNotSupported"); 00817 default: 00818 ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression"); 00819 } 00820 image->columns=(unsigned long) bmp_info.width; 00821 image->rows=(unsigned long) AbsoluteValue(bmp_info.height); 00822 image->depth=8; 00823 image->matte=(MagickBooleanType) (bmp_info.alpha_mask != 0); 00824 if ((bmp_info.number_colors != 0) || (bmp_info.bits_per_pixel < 16)) 00825 { 00826 image->storage_class=PseudoClass; 00827 image->colors=bmp_info.number_colors; 00828 if (image->colors == 0) 00829 image->colors=1L << bmp_info.bits_per_pixel; 00830 } 00831 if (image->storage_class == PseudoClass) 00832 { 00833 unsigned char 00834 *bmp_colormap; 00835 00836 size_t 00837 packet_size; 00838 00839 /* 00840 Read BMP raster colormap. 00841 */ 00842 if (image->debug != MagickFalse) 00843 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00844 " Reading colormap of %ld colors",image->colors); 00845 if (AllocateImageColormap(image,image->colors) == MagickFalse) 00846 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 00847 bmp_colormap=(unsigned char *) 00848 AcquireMagickMemory((size_t) (4*image->colors)); 00849 if (bmp_colormap == (unsigned char *) NULL) 00850 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 00851 if ((bmp_info.size == 12) || (bmp_info.size == 64)) 00852 packet_size=3; 00853 else 00854 packet_size=4; 00855 (void) SeekBlob(image,start_position+14+bmp_info.size,SEEK_SET); 00856 (void) ReadBlob(image,packet_size*image->colors,bmp_colormap); 00857 p=bmp_colormap; 00858 for (i=0; i < (long) image->colors; i++) 00859 { 00860 image->colormap[i].blue=ScaleCharToQuantum(*p++); 00861 image->colormap[i].green=ScaleCharToQuantum(*p++); 00862 image->colormap[i].red=ScaleCharToQuantum(*p++); 00863 if (packet_size == 4) 00864 p++; 00865 } 00866 bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap); 00867 } 00868 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) 00869 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 00870 break; 00871 /* 00872 Read image data. 00873 */ 00874 (void) SeekBlob(image,start_position+bmp_info.offset_bits,SEEK_SET); 00875 if (bmp_info.compression == BI_RLE4) 00876 bmp_info.bits_per_pixel<<=1; 00877 bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32); 00878 length=(size_t) bytes_per_line*image->rows; 00879 pixels=(unsigned char *) AcquireMagickMemory((size_t) 00880 Max(bytes_per_line,image->columns+256)*image->rows*sizeof(*pixels)); 00881 if (pixels == (unsigned char *) NULL) 00882 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 00883 if ((bmp_info.compression == BI_RGB) || 00884 (bmp_info.compression == BI_BITFIELDS)) 00885 { 00886 if (image->debug != MagickFalse) 00887 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 00888 " Reading pixels (%ld bytes)",(long) length); 00889 (void) ReadBlob(image,length,pixels); 00890 } 00891 else 00892 { 00893 /* 00894 Convert run-length encoded raster pixels. 00895 */ 00896 status=DecodeImage(image,bmp_info.compression,pixels); 00897 if (status == MagickFalse) 00898 ThrowReaderException(CorruptImageError, 00899 "UnableToRunlengthDecodeImage"); 00900 } 00901 /* 00902 Initialize image structure. 00903 */ 00904 image->x_resolution=(double) bmp_info.x_pixels/100.0; 00905 image->y_resolution=(double) bmp_info.y_pixels/100.0; 00906 /* 00907 Convert BMP raster image to pixel packets. 00908 */ 00909 if (bmp_info.compression == BI_RGB) 00910 { 00911 bmp_info.alpha_mask=0; 00912 bmp_info.red_mask=0x00ff0000UL; 00913 bmp_info.green_mask=0x0000ff00UL; 00914 bmp_info.blue_mask=0x000000ffUL; 00915 if (bmp_info.bits_per_pixel == 16) 00916 { 00917 /* 00918 RGB555. 00919 */ 00920 bmp_info.red_mask=0x00007c00UL; 00921 bmp_info.green_mask=0x000003e0UL; 00922 bmp_info.blue_mask=0x0000001fUL; 00923 } 00924 } 00925 if ((bmp_info.bits_per_pixel == 16) || (bmp_info.bits_per_pixel == 32)) 00926 { 00927 register unsigned long 00928 sample; 00929 00930 /* 00931 Get shift and quantum bits info from bitfield masks. 00932 */ 00933 (void) ResetMagickMemory(&shift,0,sizeof(shift)); 00934 (void) ResetMagickMemory(&quantum_bits,0,sizeof(quantum_bits)); 00935 if (bmp_info.red_mask != 0) 00936 while (((bmp_info.red_mask << shift.red) & 0x80000000UL) == 0) 00937 shift.red++; 00938 if (bmp_info.green_mask != 0) 00939 while (((bmp_info.green_mask << shift.green) & 0x80000000UL) == 0) 00940 shift.green++; 00941 if (bmp_info.blue_mask != 0) 00942 while (((bmp_info.blue_mask << shift.blue) & 0x80000000UL) == 0) 00943 shift.blue++; 00944 if (bmp_info.alpha_mask != 0) 00945 while (((bmp_info.alpha_mask << shift.opacity) & 0x80000000UL) == 0) 00946 shift.opacity++; 00947 sample=shift.red; 00948 while (((bmp_info.red_mask << sample) & 0x80000000UL) != 0) 00949 sample++; 00950 quantum_bits.red=(Quantum) (sample-shift.red); 00951 sample=shift.green; 00952 while (((bmp_info.green_mask << sample) & 0x80000000UL) != 0) 00953 sample++; 00954 quantum_bits.green=(Quantum) (sample-shift.green); 00955 sample=shift.blue; 00956 while (((bmp_info.blue_mask << sample) & 0x80000000UL) != 0) 00957 sample++; 00958 quantum_bits.blue=(Quantum) (sample-shift.blue); 00959 sample=shift.opacity; 00960 while (((bmp_info.alpha_mask << sample) & 0x80000000UL) != 0) 00961 sample++; 00962 quantum_bits.opacity=(Quantum) (sample-shift.opacity); 00963 } 00964 switch (bmp_info.bits_per_pixel) 00965 { 00966 case 1: 00967 { 00968 /* 00969 Convert bitmap scanline. 00970 */ 00971 for (y=(long) image->rows-1; y >= 0; y--) 00972 { 00973 p=pixels+(image->rows-y-1)*bytes_per_line; 00974 q=SetImagePixels(image,0,y,image->columns,1); 00975 if (q == (PixelPacket *) NULL) 00976 break; 00977 indexes=GetIndexes(image); 00978 for (x=0; x < ((long) image->columns-7); x+=8) 00979 { 00980 for (bit=0; bit < 8; bit++) 00981 { 00982 index=(IndexPacket) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00); 00983 indexes[x+bit]=index; 00984 *q++=image->colormap[index]; 00985 } 00986 p++; 00987 } 00988 if ((image->columns % 8) != 0) 00989 { 00990 for (bit=0; bit < (image->columns % 8); bit++) 00991 { 00992 index=(IndexPacket) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00); 00993 indexes[x+bit]=index; 00994 *q++=image->colormap[index]; 00995 } 00996 p++; 00997 } 00998 if (SyncImagePixels(image) == MagickFalse) 00999 break; 01000 if (image->previous == (Image *) NULL) 01001 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 01002 (QuantumTick(y,image->rows) != MagickFalse)) 01003 { 01004 status=image->progress_monitor(LoadImageTag,y,image->rows, 01005 image->client_data); 01006 if (status == MagickFalse) 01007 break; 01008 } 01009 } 01010 break; 01011 } 01012 case 4: 01013 { 01014 /* 01015 Convert PseudoColor scanline. 01016 */ 01017 for (y=(long) image->rows-1; y >= 0; y--) 01018 { 01019 p=pixels+(image->rows-y-1)*bytes_per_line; 01020 q=SetImagePixels(image,0,y,image->columns,1); 01021 if (q == (PixelPacket *) NULL) 01022 break; 01023 indexes=GetIndexes(image); 01024 for (x=0; x < ((long) image->columns-1); x+=2) 01025 { 01026 index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f); 01027 indexes[x]=index; 01028 *q++=image->colormap[index]; 01029 index=ConstrainColormapIndex(image,*p & 0x0f); 01030 indexes[x+1]=index; 01031 *q++=image->colormap[index]; 01032 p++; 01033 } 01034 if ((image->columns % 2) != 0) 01035 { 01036 index=ConstrainColormapIndex(image,(*p >> 4) & 0xf); 01037 indexes[x]=index; 01038 *q++=image->colormap[index]; 01039 p++; 01040 } 01041 if (SyncImagePixels(image) == MagickFalse) 01042 break; 01043 if (image->previous == (Image *) NULL) 01044 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 01045 (QuantumTick(y,image->rows) != MagickFalse)) 01046 { 01047 status=image->progress_monitor(LoadImageTag,y,image->rows, 01048 image->client_data); 01049 if (status == MagickFalse) 01050 break; 01051 } 01052 } 01053 break; 01054 } 01055 case 8: 01056 { 01057 /* 01058 Convert PseudoColor scanline. 01059 */ 01060 if ((bmp_info.compression == BI_RLE8) || 01061 (bmp_info.compression == BI_RLE4)) 01062 bytes_per_line=image->columns; 01063 for (y=(long) image->rows-1; y >= 0; y--) 01064 { 01065 p=pixels+(image->rows-y-1)*bytes_per_line; 01066 q=SetImagePixels(image,0,y,image->columns,1); 01067 if (q == (PixelPacket *) NULL) 01068 break; 01069 indexes=GetIndexes(image); 01070 for (x = (long)image->columns; x != 0; --x) 01071 { 01072 index=ConstrainColormapIndex(image,*p); 01073 *indexes++=index; 01074 *q=image->colormap[index]; 01075 p++; 01076 q++; 01077 } 01078 if (SyncImagePixels(image) == MagickFalse) 01079 break; 01080 if (image->previous == (Image *) NULL) 01081 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 01082 (QuantumTick(image->rows-y-1,image->rows) != MagickFalse)) 01083 { 01084 status=image->progress_monitor(LoadImageTag,(MagickOffsetType) 01085 image->rows-y-1,image->rows,image->client_data); 01086 if (status == MagickFalse) 01087 break; 01088 } 01089 } 01090 break; 01091 } 01092 case 16: 01093 { 01094 unsigned long 01095 pixel; 01096 01097 /* 01098 Convert bitfield encoded 16-bit PseudoColor scanline. 01099 */ 01100 if (bmp_info.compression != BI_RGB && 01101 bmp_info.compression != BI_BITFIELDS) 01102 ThrowReaderException(CorruptImageError, 01103 "UnrecognizedImageCompression"); 01104 bytes_per_line=2*(image->columns+image->columns%2); 01105 image->storage_class=DirectClass; 01106 for (y=(long) image->rows-1; y >= 0; y--) 01107 { 01108 p=pixels+(image->rows-y-1)*bytes_per_line; 01109 q=SetImagePixels(image,0,y,image->columns,1); 01110 if (q == (PixelPacket *) NULL) 01111 break; 01112 for (x=0; x < (long) image->columns; x++) 01113 { 01114 pixel=(unsigned long) (*p++); 01115 pixel|=(*p++) << 8; 01116 red=((pixel & bmp_info.red_mask) << shift.red) >> 16; 01117 if (quantum_bits.red == 5) 01118 red|=((red & 0xe000) >> 5); 01119 if (quantum_bits.red <= 8) 01120 red|=((red & 0xff00) >> 8); 01121 green=((pixel & bmp_info.green_mask) << shift.green) >> 16; 01122 if (quantum_bits.green == 5) 01123 green|=((green & 0xe000) >> 5); 01124 if (quantum_bits.green == 6) 01125 green|=((green & 0xc000) >> 6); 01126 if (quantum_bits.green <= 8) 01127 green|=((green & 0xff00) >> 8); 01128 blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16; 01129 if (quantum_bits.blue == 5) 01130 blue|=((blue & 0xe000) >> 5); 01131 if (quantum_bits.blue <= 8) 01132 blue|=((blue & 0xff00) >> 8); 01133 q->red=ScaleShortToQuantum(red); 01134 q->green=ScaleShortToQuantum(green); 01135 q->blue=ScaleShortToQuantum(blue); 01136 if (image->matte != MagickFalse) 01137 { 01138 opacity=((pixel & bmp_info.alpha_mask) << shift.opacity) >> 16; 01139 if (quantum_bits.opacity <= 8) 01140 q->opacity|=((q->opacity & 0xff00) >> 8); 01141 q->opacity=ScaleShortToQuantum(opacity); 01142 } 01143 q++; 01144 } 01145 if (SyncImagePixels(image) == MagickFalse) 01146 break; 01147 if (image->previous == (Image *) NULL) 01148 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 01149 (QuantumTick(image->rows-y-1,image->rows) != MagickFalse)) 01150 { 01151 status=image->progress_monitor(LoadImageTag,(MagickOffsetType) 01152 image->rows-y-1,image->rows,image->client_data); 01153 if (status == MagickFalse) 01154 break; 01155 } 01156 } 01157 break; 01158 } 01159 case 24: 01160 { 01161 /* 01162 Convert DirectColor scanline. 01163 */ 01164 bytes_per_line=4*((image->columns*24+31)/32); 01165 for (y=(long) image->rows-1; y >= 0; y--) 01166 { 01167 p=pixels+(image->rows-y-1)*bytes_per_line; 01168 q=SetImagePixels(image,0,y,image->columns,1); 01169 if (q == (PixelPacket *) NULL) 01170 break; 01171 for (x=0; x < (long) image->columns; x++) 01172 { 01173 q->blue=ScaleCharToQuantum(*p++); 01174 q->green=ScaleCharToQuantum(*p++); 01175 q->red=ScaleCharToQuantum(*p++); 01176 q++; 01177 } 01178 if (SyncImagePixels(image) == MagickFalse) 01179 break; 01180 if (image->previous == (Image *) NULL) 01181 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 01182 (QuantumTick(image->rows-y-1,image->rows) != MagickFalse)) 01183 { 01184 status=image->progress_monitor(LoadImageTag,(MagickOffsetType) 01185 image->rows-y-1,image->rows,image->client_data); 01186 if (status == MagickFalse) 01187 break; 01188 } 01189 } 01190 break; 01191 } 01192 case 32: 01193 { 01194 /* 01195 Convert bitfield encoded DirectColor scanline. 01196 */ 01197 if ((bmp_info.compression != BI_RGB) && 01198 (bmp_info.compression != BI_BITFIELDS)) 01199 ThrowReaderException(CorruptImageError, 01200 "UnrecognizedImageCompression"); 01201 bytes_per_line=4*(image->columns); 01202 for (y=(long) image->rows-1; y >= 0; y--) 01203 { 01204 unsigned long 01205 pixel; 01206 01207 p=pixels+(image->rows-y-1)*bytes_per_line; 01208 q=SetImagePixels(image,0,y,image->columns,1); 01209 if (q == (PixelPacket *) NULL) 01210 break; 01211 for (x=0; x < (long) image->columns; x++) 01212 { 01213 pixel=(unsigned long) (*p++); 01214 pixel|=(*p++ << 8); 01215 pixel|=(*p++ << 16); 01216 pixel|=(*p++ << 24); 01217 red=((pixel & bmp_info.red_mask) << shift.red) >> 16; 01218 if (quantum_bits.red == 8) 01219 red|=(red >> 8); 01220 green=((pixel & bmp_info.green_mask) << shift.green) >> 16; 01221 if (quantum_bits.green == 8) 01222 green|=(green >> 8); 01223 blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16; 01224 if (quantum_bits.blue == 8) 01225 blue|=(blue >> 8); 01226 if (image->matte != MagickFalse) 01227 { 01228 opacity=((pixel & bmp_info.alpha_mask) << shift.opacity) >> 16; 01229 if (quantum_bits.opacity == 8) 01230 opacity|=(opacity >> 8); 01231 q->opacity=ScaleShortToQuantum(opacity); 01232 } 01233 q->red=ScaleShortToQuantum(red); 01234 q->green=ScaleShortToQuantum(green); 01235 q->blue=ScaleShortToQuantum(blue); 01236 q++; 01237 } 01238 if (SyncImagePixels(image) == MagickFalse) 01239 break; 01240 if (image->previous == (Image *) NULL) 01241 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 01242 (QuantumTick(image->rows-y-1,image->rows) != MagickFalse)) 01243 { 01244 status=image->progress_monitor(LoadImageTag,(MagickOffsetType) 01245 image->rows-y-1,image->rows,image->client_data); 01246 if (status == MagickFalse) 01247 break; 01248 } 01249 } 01250 break; 01251 } 01252 default: 01253 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 01254 } 01255 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 01256 if (EOFBlob(image) != MagickFalse) 01257 { 01258 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 01259 image->filename); 01260 break; 01261 } 01262 if (bmp_info.height < 0) 01263 { 01264 Image 01265 *flipped_image; 01266 01267 /* 01268 Correct image orientation. 01269 */ 01270 flipped_image=FlipImage(image,exception); 01271 if (flipped_image == (Image *) NULL) 01272 { 01273 DestroyImageList(image); 01274 return((Image *) NULL); 01275 } 01276 image=DestroyImage(image); 01277 image=flipped_image; 01278 } 01279 /* 01280 Proceed to next image. 01281 */ 01282 if (image_info->number_scenes != 0) 01283 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 01284 break; 01285 *magick='\0'; 01286 if (bmp_info.ba_offset != 0) 01287 (void) SeekBlob(image,(MagickOffsetType) bmp_info.ba_offset,SEEK_SET); 01288 (void) ReadBlob(image,2,magick); 01289 if (IsBMP(magick,2) != MagickFalse) 01290 { 01291 /* 01292 Acquire next image structure. 01293 */ 01294 AllocateNextImage(image_info,image); 01295 if (image->next == (Image *) NULL) 01296 { 01297 DestroyImageList(image); 01298 return((Image *) NULL); 01299 } 01300 image=SyncNextImageInList(image); 01301 if (image->progress_monitor != (MagickProgressMonitor) NULL) 01302 { 01303 status=image->progress_monitor(LoadImagesTag,TellBlob(image), 01304 GetBlobSize(image),image->client_data); 01305 if (status == MagickFalse) 01306 break; 01307 } 01308 } 01309 } while (IsBMP(magick,2) != MagickFalse); 01310 CloseBlob(image); 01311 return(GetFirstImageInList(image)); 01312 } 01313 01314 /* 01315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01316 % % 01317 % % 01318 % % 01319 % R e g i s t e r B M P I m a g e % 01320 % % 01321 % % 01322 % % 01323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01324 % 01325 % RegisterBMPImage() adds attributes for the BMP image format to 01326 % the list of supported formats. The attributes include the image format 01327 % tag, a method to read and/or write the format, whether the format 01328 % supports the saving of more than one frame to the same file or blob, 01329 % whether the format supports native in-memory I/O, and a brief 01330 % description of the format. 01331 % 01332 % The format of the RegisterBMPImage method is: 01333 % 01334 % RegisterBMPImage(void) 01335 % 01336 */ 01337 ModuleExport void RegisterBMPImage(void) 01338 { 01339 MagickInfo 01340 *entry; 01341 01342 entry=SetMagickInfo("BMP"); 01343 entry->decoder=(DecoderHandler *) ReadBMPImage; 01344 entry->encoder=(EncoderHandler *) WriteBMPImage; 01345 entry->magick=(MagickHandler *) IsBMP; 01346 entry->description=AcquireString("Microsoft Windows bitmap image"); 01347 entry->module=AcquireString("BMP"); 01348 entry->adjoin=MagickFalse; 01349 entry->seekable_stream=MagickTrue; 01350 (void) RegisterMagickInfo(entry); 01351 entry=SetMagickInfo("BMP2"); 01352 entry->encoder=(EncoderHandler *) WriteBMPImage; 01353 entry->magick=(MagickHandler *) IsBMP; 01354 entry->description=AcquireString("Microsoft Windows bitmap image v2"); 01355 entry->module=AcquireString("BMP"); 01356 entry->adjoin=MagickFalse; 01357 entry->seekable_stream=MagickTrue; 01358 (void) RegisterMagickInfo(entry); 01359 entry=SetMagickInfo("BMP3"); 01360 entry->encoder=(EncoderHandler *) WriteBMPImage; 01361 entry->magick=(MagickHandler *) IsBMP; 01362 entry->description=AcquireString("Microsoft Windows bitmap image v3"); 01363 entry->module=AcquireString("BMP"); 01364 entry->adjoin=MagickFalse; 01365 entry->seekable_stream=MagickTrue; 01366 (void) RegisterMagickInfo(entry); 01367 } 01368 01369 /* 01370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01371 % % 01372 % % 01373 % % 01374 % U n r e g i s t e r B M P I m a g e % 01375 % % 01376 % % 01377 % % 01378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01379 % 01380 % UnregisterBMPImage() removes format registrations made by the 01381 % BMP module from the list of supported formats. 01382 % 01383 % The format of the UnregisterBMPImage method is: 01384 % 01385 % UnregisterBMPImage(void) 01386 % 01387 */ 01388 ModuleExport void UnregisterBMPImage(void) 01389 { 01390 (void) UnregisterMagickInfo("BMP"); 01391 (void) UnregisterMagickInfo("BMP2"); 01392 (void) UnregisterMagickInfo("BMP3"); 01393 } 01394 01395 /* 01396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01397 % % 01398 % % 01399 % % 01400 % W r i t e B M P I m a g e % 01401 % % 01402 % % 01403 % % 01404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01405 % 01406 % WriteBMPImage() writes an image in Microsoft Windows bitmap encoded 01407 % image format, version 3 for Windows or (if the image has a matte channel) 01408 % version 4. 01409 % 01410 % The format of the WriteBMPImage method is: 01411 % 01412 % MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image) 01413 % 01414 % A description of each parameter follows. 01415 % 01416 % o image_info: The image info. 01417 % 01418 % o image: The image. 01419 % 01420 % 01421 */ 01422 static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image) 01423 { 01424 BMPInfo 01425 bmp_info; 01426 01427 long 01428 y; 01429 01430 MagickBooleanType 01431 have_color_info, 01432 status; 01433 01434 MagickOffsetType 01435 scene; 01436 01437 register const PixelPacket 01438 *p; 01439 01440 register IndexPacket 01441 *indexes; 01442 01443 register long 01444 i, 01445 x; 01446 01447 register unsigned char 01448 *q; 01449 01450 StringInfo 01451 *profile; 01452 01453 unsigned char 01454 *bmp_data, 01455 *pixels; 01456 01457 unsigned long 01458 bytes_per_line, 01459 type; 01460 01461 /* 01462 Open output image file. 01463 */ 01464 assert(image_info != (const ImageInfo *) NULL); 01465 assert(image_info->signature == MagickSignature); 01466 assert(image != (Image *) NULL); 01467 assert(image->signature == MagickSignature); 01468 if (image->debug != MagickFalse) 01469 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 01470 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); 01471 if (status == MagickFalse) 01472 return(status); 01473 type=4; 01474 if (LocaleCompare(image_info->magick,"BMP2") == 0) 01475 type=2; 01476 else 01477 if (LocaleCompare(image_info->magick,"BMP3") == 0) 01478 type=3; 01479 scene=0; 01480 do 01481 { 01482 /* 01483 Initialize BMP raster file header. 01484 */ 01485 (void) SetImageColorspace(image,RGBColorspace); 01486 (void) ResetMagickMemory(&bmp_info,0,sizeof(bmp_info)); 01487 bmp_info.file_size=14+12; 01488 if (type > 2) 01489 bmp_info.file_size+=28; 01490 bmp_info.offset_bits=bmp_info.file_size; 01491 bmp_info.compression=BI_RGB; 01492 if ((image->storage_class == PseudoClass) && (image->colors > 256)) 01493 image->storage_class=DirectClass; 01494 if (image->storage_class != DirectClass) 01495 { 01496 /* 01497 Colormapped BMP raster. 01498 */ 01499 bmp_info.bits_per_pixel=8; 01500 if (image->colors <= 2) 01501 bmp_info.bits_per_pixel=1; 01502 else 01503 if (image->colors <= 16) 01504 bmp_info.bits_per_pixel=4; 01505 else 01506 if (image->colors <= 256) 01507 bmp_info.bits_per_pixel=8; 01508 if (image->compression == RLECompression) 01509 bmp_info.bits_per_pixel=8; 01510 bmp_info.number_colors=1 << bmp_info.bits_per_pixel; 01511 if (image->matte != MagickFalse) 01512 image->storage_class=DirectClass; 01513 else 01514 if (bmp_info.number_colors < image->colors) 01515 image->storage_class=DirectClass; 01516 else 01517 { 01518 bmp_info.file_size+=3*(1 << bmp_info.bits_per_pixel); 01519 bmp_info.offset_bits+=3*(1 << bmp_info.bits_per_pixel); 01520 if (type > 2) 01521 { 01522 bmp_info.file_size+=(1 << bmp_info.bits_per_pixel); 01523 bmp_info.offset_bits+=(1 << bmp_info.bits_per_pixel); 01524 } 01525 } 01526 } 01527 if (image->storage_class == DirectClass) 01528 { 01529 /* 01530 Full color BMP raster. 01531 */ 01532 bmp_info.number_colors=0; 01533 bmp_info.bits_per_pixel=(unsigned short) 01534 ((type > 3) && (image->matte != MagickFalse) ? 32 : 24); 01535 bmp_info.compression=(MagickBooleanType) 01536 ((type > 3) && (image->matte != MagickFalse) ? BI_BITFIELDS : BI_RGB); 01537 } 01538 bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32); 01539 bmp_info.ba_offset=0; 01540 profile=GetImageProfile(image,"icc"); 01541 have_color_info=(MagickBooleanType) 01542 (((image->rendering_intent != UndefinedIntent) || 01543 (profile != (StringInfo *) NULL) || (image->gamma != 0.0))); 01544 if (type == 2) 01545 bmp_info.size=12; 01546 else 01547 if ((type == 3) || ((image->matte == MagickFalse) && 01548 (have_color_info == MagickFalse))) 01549 { 01550 type=3; 01551 bmp_info.size=40; 01552 } 01553 else 01554 { 01555 int 01556 extra_size; 01557 01558 bmp_info.size=108; 01559 extra_size=68; 01560 if ((image->rendering_intent != UndefinedIntent) || 01561 (profile != (StringInfo *) NULL)) 01562 { 01563 bmp_info.size=124; 01564 extra_size+=16; 01565 } 01566 bmp_info.file_size+=extra_size; 01567 bmp_info.offset_bits+=extra_size; 01568 } 01569 bmp_info.width=(long) image->columns; 01570 bmp_info.height=(long) image->rows; 01571 bmp_info.planes=1; 01572 bmp_info.image_size=bytes_per_line*image->rows; 01573 bmp_info.file_size+=bmp_info.image_size; 01574 bmp_info.x_pixels=75*39; 01575 bmp_info.y_pixels=75*39; 01576 switch (image->units) 01577 { 01578 case UndefinedResolution: 01579 case PixelsPerInchResolution: 01580 { 01581 bmp_info.x_pixels=(unsigned long) (100.0*image->x_resolution/2.54); 01582 bmp_info.y_pixels=(unsigned long) (100.0*image->y_resolution/2.54); 01583 break; 01584 } 01585 case PixelsPerCentimeterResolution: 01586 { 01587 bmp_info.x_pixels=(unsigned long) (100.0*image->x_resolution); 01588 bmp_info.y_pixels=(unsigned long) (100.0*image->y_resolution); 01589 break; 01590 } 01591 } 01592 bmp_info.colors_important=bmp_info.number_colors; 01593 /* 01594 Convert MIFF to BMP raster pixels. 01595 */ 01596 pixels=(unsigned char *) AcquireMagickMemory((size_t) bmp_info.image_size); 01597 if (pixels == (unsigned char *) NULL) 01598 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 01599 (void) ResetMagickMemory(pixels,0,(size_t) bmp_info.image_size); 01600 switch (bmp_info.bits_per_pixel) 01601 { 01602 case 1: 01603 { 01604 unsigned long 01605 bit, 01606 byte; 01607 01608 /* 01609 Convert PseudoClass image to a BMP monochrome image. 01610 */ 01611 for (y=0; y < (long) image->rows; y++) 01612 { 01613 p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); 01614 if (p == (const PixelPacket *) NULL) 01615 break; 01616 indexes=GetIndexes(image); 01617 q=pixels+(image->rows-y-1)*bytes_per_line; 01618 bit=0; 01619 byte=0; 01620 for (x=0; x < (long) image->columns; x++) 01621 { 01622 byte<<=1; 01623 byte|=indexes[x] != 0 ? 0x01 : 0x00; 01624 bit++; 01625 if (bit == 8) 01626 { 01627 *q++=(unsigned char) byte; 01628 bit=0; 01629 byte=0; 01630 } 01631 } 01632 if (bit != 0) 01633 { 01634 *q++=(unsigned char) (byte << (8-bit)); 01635 x++; 01636 } 01637 for (x=(long) (image->columns+7)/8; x < (long) bytes_per_line; x++) 01638 *q++=0x00; 01639 if (image->previous == (Image *) NULL) 01640 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 01641 (QuantumTick(y,image->rows) != MagickFalse)) 01642 { 01643 status=image->progress_monitor(SaveImageTag,y,image->rows, 01644 image->client_data); 01645 if (status == MagickFalse) 01646 break; 01647 } 01648 } 01649 break; 01650 } 01651 case 4: 01652 { 01653 unsigned long 01654 nibble, 01655 byte; 01656 01657 /* 01658 Convert PseudoClass image to a BMP monochrome image. 01659 */ 01660 for (y=0; y < (long) image->rows; y++) 01661 { 01662 p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); 01663 if (p == (const PixelPacket *) NULL) 01664 break; 01665 indexes=GetIndexes(image); 01666 q=pixels+(image->rows-y-1)*bytes_per_line; 01667 nibble=0; 01668 byte=0; 01669 for (x=0; x < (long) image->columns; x++) 01670 { 01671 byte<<=4; 01672 byte|=(indexes[x] & 0x0f); 01673 nibble++; 01674 if (nibble == 2) 01675 { 01676 *q++=(unsigned char) byte; 01677 nibble=0; 01678 byte=0; 01679 } 01680 } 01681 if (nibble != 0) 01682 { 01683 *q++=(unsigned char) (byte << 4); 01684 x++; 01685 } 01686 for (x=(long) (image->columns+1)/2; x < (long) bytes_per_line; x++) 01687 *q++=0x00; 01688 if (image->previous == (Image *) NULL) 01689 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 01690 (QuantumTick(y,image->rows) != MagickFalse)) 01691 { 01692 status=image->progress_monitor(SaveImageTag,y,image->rows, 01693 image->client_data); 01694 if (status == MagickFalse) 01695 break; 01696 } 01697 } 01698 break; 01699 } 01700 case 8: 01701 { 01702 /* 01703 Convert PseudoClass packet to BMP pixel. 01704 */ 01705 for (y=0; y < (long) image->rows; y++) 01706 { 01707 p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); 01708 if (p == (const PixelPacket *) NULL) 01709 break; 01710 indexes=GetIndexes(image); 01711 q=pixels+(image->rows-y-1)*bytes_per_line; 01712 for (x=0; x < (long) image->columns; x++) 01713 *q++=(unsigned char) indexes[x]; 01714 for ( ; x < (long) bytes_per_line; x++) 01715 *q++=0x00; 01716 if (image->previous == (Image *) NULL) 01717 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 01718 (QuantumTick(y,image->rows) != MagickFalse)) 01719 { 01720 status=image->progress_monitor(SaveImageTag,y,image->rows, 01721 image->client_data); 01722 if (status == MagickFalse) 01723 break; 01724 } 01725 } 01726 break; 01727 } 01728 case 24: 01729 case 32: 01730 { 01731 /* 01732 Convert DirectClass packet to BMP BGR888 or BGRA8888 pixel. 01733 */ 01734 for (y=0; y < (long) image->rows; y++) 01735 { 01736 p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); 01737 if (p == (const PixelPacket *) NULL) 01738 break; 01739 q=pixels+(image->rows-y-1)*bytes_per_line; 01740 for (x=0; x < (long) image->columns; x++) 01741 { 01742 *q++=ScaleQuantumToChar(p->blue); 01743 *q++=ScaleQuantumToChar(p->green); 01744 *q++=ScaleQuantumToChar(p->red); 01745 if (bmp_info.bits_per_pixel == 32) 01746 *q++=ScaleQuantumToChar(p->opacity); 01747 p++; 01748 } 01749 if (bmp_info.bits_per_pixel == 24) 01750 for (x=3L*(long) image->columns; x < (long) bytes_per_line; x++) 01751 *q++=0x00; 01752 if (image->previous == (Image *) NULL) 01753 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 01754 (QuantumTick(y,image->rows) != MagickFalse)) 01755 { 01756 status=image->progress_monitor(SaveImageTag,y,image->rows, 01757 image->client_data); 01758 if (status == MagickFalse) 01759 break; 01760 } 01761 } 01762 break; 01763 } 01764 } 01765 if ((type > 2) && (bmp_info.bits_per_pixel == 8)) 01766 if (image->compression != NoCompression) 01767 { 01768 size_t 01769 length; 01770 01771 /* 01772 Convert run-length encoded raster pixels. 01773 */ 01774 length=(size_t) (2*(bytes_per_line+2)*(image->rows+2)+2); 01775 bmp_data=(unsigned char *) AcquireMagickMemory(length+bytes_per_line); 01776 if (bmp_data == (unsigned char *) NULL) 01777 { 01778 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 01779 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 01780 } 01781 bmp_info.file_size-=bmp_info.image_size; 01782 bmp_info.image_size=(unsigned long) 01783 EncodeImage(image,bytes_per_line,pixels,bmp_data); 01784 bmp_info.file_size+=bmp_info.image_size; 01785 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 01786 pixels=bmp_data; 01787 bmp_info.compression=BI_RLE8; 01788 } 01789 /* 01790 Write BMP for Windows, all versions, 14-byte header. 01791 */ 01792 if (image->debug != MagickFalse) 01793 { 01794 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01795 " Writing BMP version %ld datastream",type); 01796 if (image->storage_class == DirectClass) 01797 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01798 " Storage class=DirectClass"); 01799 else 01800 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01801 " Storage class=PseudoClass"); 01802 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01803 " Image depth=%lu",image->depth); 01804 if (image->matte != MagickFalse) 01805 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01806 " Matte=True"); 01807 else 01808 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01809 " Matte=MagickFalse"); 01810 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01811 " BMP bits_per_pixel=%d",bmp_info.bits_per_pixel); 01812 switch ((int) bmp_info.compression) 01813 { 01814 case BI_RGB: 01815 { 01816 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01817 " Compression=BI_RGB"); 01818 break; 01819 } 01820 case BI_RLE8: 01821 { 01822 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01823 " Compression=BI_RLE8"); 01824 break; 01825 } 01826 case BI_BITFIELDS: 01827 { 01828 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01829 " Compression=BI_BITFIELDS"); 01830 break; 01831 } 01832 default: 01833 { 01834 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01835 " Compression=UNKNOWN (%lu)",bmp_info.compression); 01836 break; 01837 } 01838 } 01839 if (bmp_info.number_colors == 0) 01840 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01841 " Number_colors=unspecified"); 01842 else 01843 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01844 " Number_colors=%lu",bmp_info.number_colors); 01845 } 01846 (void) WriteBlob(image,2,(unsigned char *) "BM"); 01847 (void) WriteBlobLSBLong(image,bmp_info.file_size); 01848 (void) WriteBlobLSBLong(image,bmp_info.ba_offset); /* always 0 */ 01849 (void) WriteBlobLSBLong(image,bmp_info.offset_bits); 01850 if (type == 2) 01851 { 01852 /* 01853 Write 12-byte version 2 bitmap header. 01854 */ 01855 (void) WriteBlobLSBLong(image,bmp_info.size); 01856 (void) WriteBlobLSBShort(image,(unsigned short) bmp_info.width); 01857 (void) WriteBlobLSBShort(image,(unsigned short) bmp_info.height); 01858 (void) WriteBlobLSBShort(image,bmp_info.planes); 01859 (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel); 01860 } 01861 else 01862 { 01863 /* 01864 Write 40-byte version 3+ bitmap header. 01865 */ 01866 (void) WriteBlobLSBLong(image,bmp_info.size); 01867 (void) WriteBlobLSBLong(image,(unsigned long) bmp_info.width); 01868 (void) WriteBlobLSBLong(image,(unsigned long) bmp_info.height); 01869 (void) WriteBlobLSBShort(image,bmp_info.planes); 01870 (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel); 01871 (void) WriteBlobLSBLong(image,bmp_info.compression); 01872 (void) WriteBlobLSBLong(image,bmp_info.image_size); 01873 (void) WriteBlobLSBLong(image,bmp_info.x_pixels); 01874 (void) WriteBlobLSBLong(image,bmp_info.y_pixels); 01875 (void) WriteBlobLSBLong(image,bmp_info.number_colors); 01876 (void) WriteBlobLSBLong(image,bmp_info.colors_important); 01877 } 01878 if ((type > 3) && ((image->matte != MagickFalse) || 01879 (have_color_info != MagickFalse))) 01880 { 01881 /* 01882 Write the rest of the 108-byte BMP Version 4 header. 01883 */ 01884 (void) WriteBlobLSBLong(image,0x00ff0000UL); /* Red mask */ 01885 (void) WriteBlobLSBLong(image,0x0000ff00UL); /* Green mask */ 01886 (void) WriteBlobLSBLong(image,0x000000ffUL); /* Blue mask */ 01887 (void) WriteBlobLSBLong(image,0xff000000UL); /* Alpha mask */ 01888 (void) WriteBlobLSBLong(image,0x00000001UL); /* CSType==Calib. RGB */ 01889 (void) WriteBlobLSBLong(image,(unsigned long) 01890 image->chromaticity.red_primary.x*0x3ffffff); 01891 (void) WriteBlobLSBLong(image,(unsigned long) 01892 image->chromaticity.red_primary.y*0x3ffffff); 01893 (void) WriteBlobLSBLong(image,(unsigned long) 01894 (1.000f-(image->chromaticity.red_primary.x+ 01895 image->chromaticity.red_primary.y)*0x3ffffff)); 01896 (void) WriteBlobLSBLong(image,(unsigned long) 01897 image->chromaticity.green_primary.x*0x3ffffff); 01898 (void) WriteBlobLSBLong(image,(unsigned long) 01899 image->chromaticity.green_primary.y*0x3ffffff); 01900 (void) WriteBlobLSBLong(image,(unsigned long) 01901 (1.000f-(image->chromaticity.green_primary.x+ 01902 image->chromaticity.green_primary.y)*0x3ffffff)); 01903 (void) WriteBlobLSBLong(image,(unsigned long) 01904 image->chromaticity.blue_primary.x*0x3ffffff); 01905 (void) WriteBlobLSBLong(image,(unsigned long) 01906 image->chromaticity.blue_primary.y*0x3ffffff); 01907 (void) WriteBlobLSBLong(image,(unsigned long) 01908 (1.000f-(image->chromaticity.blue_primary.x+ 01909 image->chromaticity.blue_primary.y)*0x3ffffff)); 01910 (void) WriteBlobLSBLong(image,(unsigned long) 01911 bmp_info.gamma_scale.x*0xffff); 01912 (void) WriteBlobLSBLong(image,(unsigned long) 01913 bmp_info.gamma_scale.y*0xffff); 01914 (void) WriteBlobLSBLong(image,(unsigned long) 01915 bmp_info.gamma_scale.z*0xffff); 01916 if ((image->rendering_intent != UndefinedIntent) || 01917 (profile != (StringInfo *) NULL)) 01918 { 01919 long 01920 intent; 01921 01922 switch ((int) image->rendering_intent) 01923 { 01924 case SaturationIntent: 01925 { 01926 intent=LCS_GM_BUSINESS; 01927 break; 01928 } 01929 case RelativeIntent: 01930 { 01931 intent=LCS_GM_GRAPHICS; 01932 break; 01933 } 01934 case PerceptualIntent: 01935 { 01936 intent=LCS_GM_IMAGES; 01937 break; 01938 } 01939 case AbsoluteIntent: 01940 { 01941 intent=LCS_GM_ABS_COLORIMETRIC; 01942 break; 01943 } 01944 default: 01945 { 01946 intent=0; 01947 break; 01948 } 01949 } 01950 (void) WriteBlobLSBLong(image,(unsigned long) intent); 01951 (void) WriteBlobLSBLong(image,0x00); /* dummy profile data */ 01952 (void) WriteBlobLSBLong(image,0x00); /* dummy profile length */ 01953 (void) WriteBlobLSBLong(image,0x00); /* reserved */ 01954 } 01955 } 01956 if (image->storage_class == PseudoClass) 01957 { 01958 unsigned char 01959 *bmp_colormap; 01960 01961 /* 01962 Dump colormap to file. 01963 */ 01964 if (image->debug != MagickFalse) 01965 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01966 " Colormap: %ld entries",image->colors); 01967 bmp_colormap=(unsigned char *) 01968 AcquireMagickMemory((size_t) (4*(1 << bmp_info.bits_per_pixel))); 01969 if (bmp_colormap == (unsigned char *) NULL) 01970 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 01971 q=bmp_colormap; 01972 for (i=0; i < (long) image->colors; i++) 01973 { 01974 *q++=ScaleQuantumToChar(image->colormap[i].blue); 01975 *q++=ScaleQuantumToChar(image->colormap[i].green); 01976 *q++=ScaleQuantumToChar(image->colormap[i].red); 01977 if (type > 2) 01978 *q++=(unsigned char) 0x0; 01979 } 01980 for ( ; i < (long) (1UL << bmp_info.bits_per_pixel); i++) 01981 { 01982 *q++=(unsigned char) 0x00; 01983 *q++=(unsigned char) 0x00; 01984 *q++=(unsigned char) 0x00; 01985 if (type > 2) 01986 *q++=(unsigned char) 0x00; 01987 } 01988 if (type <= 2) 01989 (void) WriteBlob(image,(size_t) (3*(1L << bmp_info.bits_per_pixel)), 01990 bmp_colormap); 01991 else 01992 (void) WriteBlob(image,(size_t) (4*(1L << bmp_info.bits_per_pixel)), 01993 bmp_colormap); 01994 bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap); 01995 } 01996 if (image->debug != MagickFalse) 01997 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 01998 " Pixels: %lu bytes",bmp_info.image_size); 01999 (void) WriteBlob(image,(size_t) bmp_info.image_size,pixels); 02000 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 02001 if (image->next == (Image *) NULL) 02002 break; 02003 image=SyncNextImageInList(image); 02004 if (image->progress_monitor != (MagickProgressMonitor) NULL) 02005 { 02006 status=image->progress_monitor(SaveImagesTag,scene, 02007 GetImageListLength(image),image->client_data); 02008 if (status == MagickFalse) 02009 break; 02010 } 02011 scene++; 02012 } while (image_info->adjoin != MagickFalse); 02013 CloseBlob(image); 02014 return(MagickTrue); 02015 }

Generated on Mon Oct 25 13:40:35 2004 for ImageMagick by doxygen 1.3.7
ImageMagick Copyright © 2004, ImageMagick Studio LLC