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->