From cd8dc2cbf03ccb62c03ba445b0a81053ab42eef3 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Thu, 12 May 2022 23:51:40 -0400 Subject: [PATCH] blades-engine load bmp directly --- projects/blades-engine/source/Bmp.c | 2484 ----------------- projects/blades-engine/source/Bmp.c.hx.ktxt2 | 229 -- projects/blades-engine/source/Bmp.hx | 103 + .../source/IsometricMapState.kiss | 2 +- 4 files changed, 104 insertions(+), 2714 deletions(-) delete mode 100644 projects/blades-engine/source/Bmp.c delete mode 100644 projects/blades-engine/source/Bmp.c.hx.ktxt2 diff --git a/projects/blades-engine/source/Bmp.c b/projects/blades-engine/source/Bmp.c deleted file mode 100644 index 4b1397ed..00000000 --- a/projects/blades-engine/source/Bmp.c +++ /dev/null @@ -1,2484 +0,0 @@ -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% BBBB M M PPPP % -% B B MM MM P P % -% BBBB M M M PPPP % -% B B M M P % -% BBBB M M P % -% % -% % -% Read/Write Microsoft Windows Bitmap Image Format % -% % -% Software Design % -% Cristy % -% Glenn Randers-Pehrson % -% December 2001 % -% % -% % -% Copyright @ 2001 ImageMagick Studio LLC, a non-profit organization % -% dedicated to making software imaging solutions freely available. % -% % -% You may not use this file except in compliance with the License. You may % -% obtain a copy of the License at % -% % -% https://imagemagick.org/script/license.php % -% % -% Unless required by applicable law or agreed to in writing, software % -% distributed under the License is distributed on an "AS IS" BASIS, % -% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % -% See the License for the specific language governing permissions and % -% limitations under the License. % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% -*/ - -/* - Include declarations. -*/ -#include "MagickCore/studio.h" -#include "MagickCore/blob.h" -#include "MagickCore/blob-private.h" -#include "MagickCore/cache.h" -#include "MagickCore/colormap-private.h" -#include "MagickCore/color-private.h" -#include "MagickCore/colormap.h" -#include "MagickCore/colorspace.h" -#include "MagickCore/colorspace-private.h" -#include "MagickCore/exception.h" -#include "MagickCore/exception-private.h" -#include "MagickCore/image.h" -#include "MagickCore/image-private.h" -#include "MagickCore/list.h" -#include "MagickCore/log.h" -#include "MagickCore/magick.h" -#include "MagickCore/memory_.h" -#include "MagickCore/monitor.h" -#include "MagickCore/monitor-private.h" -#include "MagickCore/option.h" -#include "MagickCore/pixel-accessor.h" -#include "MagickCore/profile.h" -#include "MagickCore/quantum-private.h" -#include "MagickCore/static.h" -#include "MagickCore/string_.h" -#include "MagickCore/module.h" -#include "MagickCore/transform.h" - -/* - Macro definitions (from Windows wingdi.h). -*/ -#undef BI_JPEG -#define BI_JPEG 4 -#undef BI_PNG -#define BI_PNG 5 -#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__) -#undef BI_RGB -#define BI_RGB 0 -#undef BI_RLE8 -#define BI_RLE8 1 -#undef BI_RLE4 -#define BI_RLE4 2 -#undef BI_BITFIELDS -#define BI_BITFIELDS 3 - -#undef LCS_CALIBRATED_RBG -#define LCS_CALIBRATED_RBG 0 -#undef LCS_sRGB -#define LCS_sRGB 1 -#undef LCS_WINDOWS_COLOR_SPACE -#define LCS_WINDOWS_COLOR_SPACE 2 -#undef PROFILE_LINKED -#define PROFILE_LINKED 3 -#undef PROFILE_EMBEDDED -#define PROFILE_EMBEDDED 4 - -#undef LCS_GM_BUSINESS -#define LCS_GM_BUSINESS 1 /* Saturation */ -#undef LCS_GM_GRAPHICS -#define LCS_GM_GRAPHICS 2 /* Relative */ -#undef LCS_GM_IMAGES -#define LCS_GM_IMAGES 4 /* Perceptual */ -#undef LCS_GM_ABS_COLORIMETRIC -#define LCS_GM_ABS_COLORIMETRIC 8 /* Absolute */ -#endif - -/* - Enumerated declaractions. -*/ -typedef enum -{ - UndefinedSubtype, - RGB555, - RGB565, - ARGB4444, - ARGB1555 -} BMPSubtype; - -/* - Typedef declarations. -*/ -typedef struct _BMPInfo -{ - unsigned int - file_size, - ba_offset, - offset_bits, - size; - - ssize_t - width, - height; - - unsigned short - planes, - bits_per_pixel; - - unsigned int - compression, - image_size, - x_pixels, - y_pixels, - number_colors, - red_mask, - green_mask, - blue_mask, - alpha_mask, - colors_important; - - long - colorspace; - - PrimaryInfo - red_primary, - green_primary, - blue_primary, - gamma_scale; -} BMPInfo; - -/* - Forward declarations. -*/ -static MagickBooleanType - WriteBMPImage(const ImageInfo *,Image *,ExceptionInfo *); - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% D e c o d e I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% DecodeImage unpacks the packed image pixels into runlength-encoded -% pixel packets. -% -% The format of the DecodeImage method is: -% -% MagickBooleanType DecodeImage(Image *image,const size_t compression, -% unsigned char *pixels,const size_t number_pixels) -% -% A description of each parameter follows: -% -% o image: the address of a structure of type Image. -% -% o compression: Zero means uncompressed. A value of 1 means the -% compressed pixels are runlength encoded for a 256-color bitmap. -% A value of 2 means a 16-color bitmap. A value of 3 means bitfields -% encoding. -% -% o pixels: The address of a byte (8 bits) array of pixel data created by -% the decoding process. -% -% o number_pixels: The number of pixels. -% -*/ -static MagickBooleanType DecodeImage(Image *image,const size_t compression, - unsigned char *pixels,const size_t number_pixels) -{ - int - byte, - count; - - ssize_t - i, - x; - - unsigned char - *p, - *q; - - ssize_t - y; - - assert(image != (Image *) NULL); - assert(image->signature == MagickCoreSignature); - assert(pixels != (unsigned char *) NULL); - if (IsEventLogging() != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - (void) memset(pixels,0,number_pixels*sizeof(*pixels)); - byte=0; - x=0; - p=pixels; - q=pixels+number_pixels; - for (y=0; y < (ssize_t) image->rows; ) - { - MagickBooleanType - status; - - if ((p < pixels) || (p > q)) - break; - count=ReadBlobByte(image); - if (count == EOF) - break; - if (count > 0) - { - /* - Encoded mode. - */ - count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p)); - byte=ReadBlobByte(image); - if (byte == EOF) - break; - if (compression == BI_RLE8) - { - for (i=0; i < (ssize_t) count; i++) - *p++=(unsigned char) byte; - } - else - { - for (i=0; i < (ssize_t) count; i++) - *p++=(unsigned char) - ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f)); - } - x+=count; - } - else - { - /* - Escape mode. - */ - count=ReadBlobByte(image); - if (count == EOF) - break; - if (count == 0x01) - return(MagickTrue); - switch (count) - { - case 0x00: - { - /* - End of line. - */ - x=0; - y++; - p=pixels+y*image->columns; - break; - } - case 0x02: - { - /* - Delta mode. - */ - x+=ReadBlobByte(image); - y+=ReadBlobByte(image); - p=pixels+y*image->columns+x; - break; - } - default: - { - /* - Absolute mode. - */ - count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p)); - if (compression == BI_RLE8) - for (i=0; i < (ssize_t) count; i++) - { - byte=ReadBlobByte(image); - if (byte == EOF) - break; - *p++=(unsigned char) byte; - } - else - for (i=0; i < (ssize_t) count; i++) - { - if ((i & 0x01) == 0) - { - byte=ReadBlobByte(image); - if (byte == EOF) - break; - } - *p++=(unsigned char) - ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f)); - } - x+=count; - /* - Read pad byte. - */ - if (compression == BI_RLE8) - { - if ((count & 0x01) != 0) - if (ReadBlobByte(image) == EOF) - break; - } - else - if (((count & 0x03) == 1) || ((count & 0x03) == 2)) - if (ReadBlobByte(image) == EOF) - break; - break; - } - } - } - status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, - image->rows); - if (status == MagickFalse) - break; - } - (void) ReadBlobByte(image); /* end of line */ - (void) ReadBlobByte(image); - return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% E n c o d e I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% EncodeImage compresses pixels using a runlength encoded format. -% -% The format of the EncodeImage method is: -% -% static MagickBooleanType EncodeImage(Image *image, -% const size_t bytes_per_line,const unsigned char *pixels, -% unsigned char *compressed_pixels) -% -% A description of each parameter follows: -% -% o image: The image. -% -% o bytes_per_line: the number of bytes in a scanline of compressed pixels -% -% o pixels: The address of a byte (8 bits) array of pixel data created by -% the compression process. -% -% o compressed_pixels: The address of a byte (8 bits) array of compressed -% pixel data. -% -*/ -static size_t EncodeImage(Image *image,const size_t bytes_per_line, - const unsigned char *pixels,unsigned char *compressed_pixels) -{ - MagickBooleanType - status; - - const unsigned char - *p; - - ssize_t - i, - x; - - unsigned char - *q; - - ssize_t - y; - - /* - Runlength encode pixels. - */ - assert(image != (Image *) NULL); - assert(image->signature == MagickCoreSignature); - assert(pixels != (const unsigned char *) NULL); - assert(compressed_pixels != (unsigned char *) NULL); - if (IsEventLogging() != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - p=pixels; - q=compressed_pixels; - i=0; - for (y=0; y < (ssize_t) image->rows; y++) - { - for (x=0; x < (ssize_t) bytes_per_line; x+=i) - { - /* - Determine runlength. - */ - for (i=1; ((x+i) < (ssize_t) bytes_per_line); i++) - if ((i == 255) || (*(p+i) != *p)) - break; - *q++=(unsigned char) i; - *q++=(*p); - p+=i; - } - /* - End of line. - */ - *q++=(unsigned char) 0x00; - *q++=(unsigned char) 0x00; - status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, - image->rows); - if (status == MagickFalse) - break; - } - /* - End of bitmap. - */ - *q++=(unsigned char) 0x00; - *q++=(unsigned char) 0x01; - return((size_t) (q-compressed_pixels)); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% I s B M P % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% IsBMP() returns MagickTrue if the image format type, identified by the -% magick string, is BMP. -% -% The format of the IsBMP method is: -% -% MagickBooleanType IsBMP(const unsigned char *magick,const size_t length) -% -% A description of each parameter follows: -% -% o magick: compare image format pattern against these bytes. -% -% o length: Specifies the length of the magick string. -% -*/ -static MagickBooleanType IsBMP(const unsigned char *magick,const size_t length) -{ - if (length < 2) - return(MagickFalse); - if ((LocaleNCompare((char *) magick,"BA",2) == 0) || - (LocaleNCompare((char *) magick,"BM",2) == 0) || - (LocaleNCompare((char *) magick,"IC",2) == 0) || - (LocaleNCompare((char *) magick,"PI",2) == 0) || - (LocaleNCompare((char *) magick,"CI",2) == 0) || - (LocaleNCompare((char *) magick,"CP",2) == 0)) - return(MagickTrue); - return(MagickFalse); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% R e a d B M P I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% ReadBMPImage() reads a Microsoft Windows bitmap image file, Version -% 2, 3 (for Windows or NT), or 4, and returns it. It allocates the memory -% necessary for the new Image structure and returns a pointer to the new -% image. -% -% The format of the ReadBMPImage method is: -% -% image=ReadBMPImage(image_info) -% -% A description of each parameter follows: -% -% o image_info: the image info. -% -% o exception: return any errors or warnings in this structure. -% -*/ - -static Image *ReadBMPImage(const ImageInfo *image_info,ExceptionInfo *exception) -{ - BMPInfo - bmp_info; - - Image - *image; - - MagickBooleanType - status; - - MagickOffsetType - offset, - profile_data, - profile_size, - start_position; - - MagickSizeType - blob_size; - - MemoryInfo - *pixel_info; - - Quantum - index; - - Quantum - *q; - - ssize_t - i, - x; - - unsigned char - *p; - - size_t - bit, - bytes_per_line, - length; - - ssize_t - count, - y; - - unsigned char - magick[12], - *pixels; - - unsigned int - blue, - green, - offset_bits, - red; - - /* - Open image file. - */ - assert(image_info != (const ImageInfo *) NULL); - assert(image_info->signature == MagickCoreSignature); - if (IsEventLogging() != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", - image_info->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - image=AcquireImage(image_info,exception); - status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); - if (status == MagickFalse) - { - image=DestroyImageList(image); - return((Image *) NULL); - } - /* - Determine if this a BMP file. - */ - (void) memset(&bmp_info,0,sizeof(bmp_info)); - bmp_info.ba_offset=0; - start_position=0; - offset_bits=0; - count=ReadBlob(image,2,magick); - if (count != 2) - ThrowReaderException(CorruptImageError,"ImproperImageHeader"); - blob_size=GetBlobSize(image); - do - { - PixelInfo - quantum_bits; - - PixelPacket - shift; - - /* - Verify BMP identifier. - */ - start_position=TellBlob(image)-2; - bmp_info.ba_offset=0; - while (LocaleNCompare((char *) magick,"BA",2) == 0) - { - bmp_info.file_size=ReadBlobLSBLong(image); - bmp_info.ba_offset=ReadBlobLSBLong(image); - bmp_info.offset_bits=ReadBlobLSBLong(image); - count=ReadBlob(image,2,magick); - if (count != 2) - break; - } - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule()," Magick: %c%c", - magick[0],magick[1]); - if ((count != 2) || ((LocaleNCompare((char *) magick,"BM",2) != 0) && - (LocaleNCompare((char *) magick,"CI",2) != 0))) - ThrowReaderException(CorruptImageError,"ImproperImageHeader"); - bmp_info.file_size=ReadBlobLSBLong(image); - (void) ReadBlobLSBLong(image); - bmp_info.offset_bits=ReadBlobLSBLong(image); - bmp_info.size=ReadBlobLSBLong(image); - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " BMP header size: %u",bmp_info.size); - if (bmp_info.size > 124) - ThrowReaderException(CorruptImageError,"ImproperImageHeader"); - profile_data=0; - profile_size=0; - if (bmp_info.size == 12) - { - /* - OS/2 BMP image file. - */ - (void) CopyMagickString(image->magick,"BMP2",MagickPathExtent); - bmp_info.width=(ssize_t) ((short) ReadBlobLSBShort(image)); - bmp_info.height=(ssize_t) ((short) ReadBlobLSBShort(image)); - bmp_info.planes=ReadBlobLSBShort(image); - bmp_info.bits_per_pixel=ReadBlobLSBShort(image); - bmp_info.x_pixels=0; - bmp_info.y_pixels=0; - bmp_info.number_colors=0; - bmp_info.compression=BI_RGB; - bmp_info.image_size=0; - bmp_info.alpha_mask=0; - if (image->debug != MagickFalse) - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Format: OS/2 Bitmap"); - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Geometry: %.20gx%.20g",(double) bmp_info.width,(double) - bmp_info.height); - } - } - else - { - /* - Microsoft Windows BMP image file. - */ - bmp_info.width=(ssize_t) ReadBlobLSBSignedLong(image); - bmp_info.height=(ssize_t) ReadBlobLSBSignedLong(image); - bmp_info.planes=ReadBlobLSBShort(image); - bmp_info.bits_per_pixel=ReadBlobLSBShort(image); - bmp_info.compression=ReadBlobLSBLong(image); - if (bmp_info.size > 16) - { - bmp_info.image_size=ReadBlobLSBLong(image); - bmp_info.x_pixels=ReadBlobLSBLong(image); - bmp_info.y_pixels=ReadBlobLSBLong(image); - bmp_info.number_colors=ReadBlobLSBLong(image); - if ((MagickSizeType) bmp_info.number_colors > blob_size) - ThrowReaderException(CorruptImageError, - "InsufficientImageDataInFile"); - bmp_info.colors_important=ReadBlobLSBLong(image); - } - if (image->debug != MagickFalse) - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Format: MS Windows bitmap"); - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Geometry: %.20gx%.20g",(double) bmp_info.width,(double) - bmp_info.height); - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Bits per pixel: %.20g",(double) bmp_info.bits_per_pixel); - switch (bmp_info.compression) - { - case BI_RGB: - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Compression: BI_RGB"); - break; - } - case BI_RLE4: - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Compression: BI_RLE4"); - break; - } - case BI_RLE8: - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Compression: BI_RLE8"); - break; - } - case BI_BITFIELDS: - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Compression: BI_BITFIELDS"); - break; - } - case BI_PNG: - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Compression: BI_PNG"); - break; - } - case BI_JPEG: - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Compression: BI_JPEG"); - break; - } - default: - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Compression: UNKNOWN (%u)",bmp_info.compression); - } - } - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Number of colors: %u",bmp_info.number_colors); - } - if ((bmp_info.size > 40) || (bmp_info.compression == BI_BITFIELDS)) - { - bmp_info.red_mask=ReadBlobLSBLong(image); - bmp_info.green_mask=ReadBlobLSBLong(image); - bmp_info.blue_mask=ReadBlobLSBLong(image); - } - if (bmp_info.size > 40) - { - double - gamma; - - /* - Read color management information. - */ - bmp_info.alpha_mask=ReadBlobLSBLong(image); - bmp_info.colorspace=ReadBlobLSBSignedLong(image); - /* - Decode 2^30 fixed point formatted CIE primaries. - */ -# define BMP_DENOM ((double) 0x40000000) - bmp_info.red_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM; - bmp_info.red_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM; - bmp_info.red_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM; - bmp_info.green_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM; - bmp_info.green_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM; - bmp_info.green_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM; - bmp_info.blue_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM; - bmp_info.blue_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM; - bmp_info.blue_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM; - - gamma=bmp_info.red_primary.x+bmp_info.red_primary.y+ - bmp_info.red_primary.z; - gamma=PerceptibleReciprocal(gamma); - bmp_info.red_primary.x*=gamma; - bmp_info.red_primary.y*=gamma; - image->chromaticity.red_primary.x=bmp_info.red_primary.x; - image->chromaticity.red_primary.y=bmp_info.red_primary.y; - - gamma=bmp_info.green_primary.x+bmp_info.green_primary.y+ - bmp_info.green_primary.z; - gamma=PerceptibleReciprocal(gamma); - bmp_info.green_primary.x*=gamma; - bmp_info.green_primary.y*=gamma; - image->chromaticity.green_primary.x=bmp_info.green_primary.x; - image->chromaticity.green_primary.y=bmp_info.green_primary.y; - - gamma=bmp_info.blue_primary.x+bmp_info.blue_primary.y+ - bmp_info.blue_primary.z; - gamma=PerceptibleReciprocal(gamma); - bmp_info.blue_primary.x*=gamma; - bmp_info.blue_primary.y*=gamma; - image->chromaticity.blue_primary.x=bmp_info.blue_primary.x; - image->chromaticity.blue_primary.y=bmp_info.blue_primary.y; - - /* - Decode 16^16 fixed point formatted gamma_scales. - */ - bmp_info.gamma_scale.x=(double) ReadBlobLSBLong(image)/0x10000; - bmp_info.gamma_scale.y=(double) ReadBlobLSBLong(image)/0x10000; - bmp_info.gamma_scale.z=(double) ReadBlobLSBLong(image)/0x10000; - /* - Compute a single gamma from the BMP 3-channel gamma. - */ - image->gamma=(bmp_info.gamma_scale.x+bmp_info.gamma_scale.y+ - bmp_info.gamma_scale.z)/3.0; - } - else - (void) CopyMagickString(image->magick,"BMP3",MagickPathExtent); - - if (bmp_info.size > 108) - { - size_t - intent; - - /* - Read BMP Version 5 color management information. - */ - intent=ReadBlobLSBLong(image); - switch ((int) intent) - { - case LCS_GM_BUSINESS: - { - image->rendering_intent=SaturationIntent; - break; - } - case LCS_GM_GRAPHICS: - { - image->rendering_intent=RelativeIntent; - break; - } - case LCS_GM_IMAGES: - { - image->rendering_intent=PerceptualIntent; - break; - } - case LCS_GM_ABS_COLORIMETRIC: - { - image->rendering_intent=AbsoluteIntent; - break; - } - } - profile_data=(MagickOffsetType)ReadBlobLSBLong(image); - profile_size=(MagickOffsetType)ReadBlobLSBLong(image); - (void) ReadBlobLSBLong(image); /* Reserved byte */ - } - } - if ((MagickSizeType) bmp_info.file_size != blob_size) - { - const char - *option; - - option=GetImageOption(image_info,"bmp:ignore-filesize"); - if (IsStringTrue(option) == MagickFalse) - (void) ThrowMagickException(exception,GetMagickModule(), - CorruptImageError,"LengthAndFilesizeDoNotMatch","`%s'", - image->filename); - } - if (bmp_info.width <= 0) - ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize"); - if (bmp_info.height == 0) - ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize"); - if (bmp_info.planes != 1) - ThrowReaderException(CorruptImageError,"StaticPlanesValueNotEqualToOne"); - if ((bmp_info.bits_per_pixel != 1) && (bmp_info.bits_per_pixel != 4) && - (bmp_info.bits_per_pixel != 8) && (bmp_info.bits_per_pixel != 16) && - (bmp_info.bits_per_pixel != 24) && (bmp_info.bits_per_pixel != 32)) - ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel"); - if (bmp_info.bits_per_pixel < 16 && - bmp_info.number_colors > (1U << bmp_info.bits_per_pixel)) - ThrowReaderException(CorruptImageError,"UnrecognizedNumberOfColors"); - if ((bmp_info.compression == BI_RLE8) && (bmp_info.bits_per_pixel != 8)) - ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel"); - if ((bmp_info.compression == BI_RLE4) && (bmp_info.bits_per_pixel != 4)) - ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel"); - if ((bmp_info.compression == BI_BITFIELDS) && (bmp_info.bits_per_pixel < 16)) - ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel"); - switch (bmp_info.compression) - { - case BI_RGB: - image->compression=NoCompression; - break; - case BI_RLE8: - case BI_RLE4: - image->compression=RLECompression; - break; - case BI_BITFIELDS: - break; - case BI_JPEG: - ThrowReaderException(CoderError,"JPEGCompressNotSupported"); - case BI_PNG: - ThrowReaderException(CoderError,"PNGCompressNotSupported"); - default: - ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression"); - } - image->columns=(size_t) MagickAbsoluteValue(bmp_info.width); - image->rows=(size_t) MagickAbsoluteValue(bmp_info.height); - image->depth=bmp_info.bits_per_pixel <= 8 ? bmp_info.bits_per_pixel : 8; - image->alpha_trait=((bmp_info.alpha_mask != 0) && - (bmp_info.compression == BI_BITFIELDS)) ? BlendPixelTrait : - UndefinedPixelTrait; - if (bmp_info.bits_per_pixel < 16) - { - size_t - one; - - image->storage_class=PseudoClass; - image->colors=bmp_info.number_colors; - one=1; - if (image->colors == 0) - image->colors=one << bmp_info.bits_per_pixel; - } - image->resolution.x=(double) bmp_info.x_pixels/100.0; - image->resolution.y=(double) bmp_info.y_pixels/100.0; - image->units=PixelsPerCentimeterResolution; - if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) - if (image->scene >= (image_info->scene+image_info->number_scenes-1)) - break; - status=SetImageExtent(image,image->columns,image->rows,exception); - if (status == MagickFalse) - return(DestroyImageList(image)); - if (image->storage_class == PseudoClass) - { - unsigned char - *bmp_colormap; - - size_t - packet_size; - - /* - Read BMP raster colormap. - */ - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Reading colormap of %.20g colors",(double) image->colors); - if (AcquireImageColormap(image,image->colors,exception) == MagickFalse) - ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); - bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t) - image->colors,4*sizeof(*bmp_colormap)); - if (bmp_colormap == (unsigned char *) NULL) - ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); - if ((bmp_info.size == 12) || (bmp_info.size == 64)) - packet_size=3; - else - packet_size=4; - offset=SeekBlob(image,start_position+14+bmp_info.size,SEEK_SET); - if (offset < 0) - { - bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap); - ThrowReaderException(CorruptImageError,"ImproperImageHeader"); - } - count=ReadBlob(image,packet_size*image->colors,bmp_colormap); - if (count != (ssize_t) (packet_size*image->colors)) - { - bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap); - ThrowReaderException(CorruptImageError, - "InsufficientImageDataInFile"); - } - p=bmp_colormap; - for (i=0; i < (ssize_t) image->colors; i++) - { - image->colormap[i].blue=(MagickRealType) ScaleCharToQuantum(*p++); - image->colormap[i].green=(MagickRealType) ScaleCharToQuantum(*p++); - image->colormap[i].red=(MagickRealType) ScaleCharToQuantum(*p++); - if (packet_size == 4) - p++; - } - bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap); - } - /* - Read image data. - */ - if (bmp_info.offset_bits == offset_bits) - ThrowReaderException(CorruptImageError,"ImproperImageHeader"); - offset_bits=bmp_info.offset_bits; - offset=SeekBlob(image,start_position+bmp_info.offset_bits,SEEK_SET); - if (offset < 0) - ThrowReaderException(CorruptImageError,"ImproperImageHeader"); - if (bmp_info.compression == BI_RLE4) - bmp_info.bits_per_pixel<<=1; - bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32); - length=(size_t) bytes_per_line*image->rows; - if ((MagickSizeType) (length/256) > blob_size) - ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); - if ((bmp_info.compression == BI_RGB) || - (bmp_info.compression == BI_BITFIELDS)) - { - pixel_info=AcquireVirtualMemory(image->rows, - MagickMax(bytes_per_line,image->columns+256UL)*sizeof(*pixels)); - if (pixel_info == (MemoryInfo *) NULL) - ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); - pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Reading pixels (%.20g bytes)",(double) length); - count=ReadBlob(image,length,pixels); - if (count != (ssize_t) length) - { - pixel_info=RelinquishVirtualMemory(pixel_info); - ThrowReaderException(CorruptImageError, - "InsufficientImageDataInFile"); - } - } - else - { - /* - Convert run-length encoded raster pixels. - */ - pixel_info=AcquireVirtualMemory(image->rows, - MagickMax(bytes_per_line,image->columns+256UL)*sizeof(*pixels)); - if (pixel_info == (MemoryInfo *) NULL) - ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); - pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); - status=DecodeImage(image,bmp_info.compression,pixels, - image->columns*image->rows); - if (status == MagickFalse) - { - pixel_info=RelinquishVirtualMemory(pixel_info); - ThrowReaderException(CorruptImageError, - "UnableToRunlengthDecodeImage"); - } - } - /* - Convert BMP raster image to pixel packets. - */ - if (bmp_info.compression == BI_RGB) - { - /* - We should ignore the alpha value in BMP3 files but there have been - reports about 32 bit files with alpha. We do a quick check to see if - the alpha channel contains a value that is not zero (default value). - If we find a non zero value we asume the program that wrote the file - wants to use the alpha channel. - */ - if ((image->alpha_trait == UndefinedPixelTrait) && - (bmp_info.size == 40) && (bmp_info.bits_per_pixel == 32)) - { - bytes_per_line=4*(image->columns); - for (y=(ssize_t) image->rows-1; y >= 0; y--) - { - p=pixels+(image->rows-y-1)*bytes_per_line; - for (x=0; x < (ssize_t) image->columns; x++) - { - if (*(p+3) != 0) - { - image->alpha_trait=BlendPixelTrait; - y=-1; - break; - } - p+=4; - } - } - } - bmp_info.alpha_mask=image->alpha_trait != UndefinedPixelTrait ? - 0xff000000U : 0U; - bmp_info.red_mask=0x00ff0000U; - bmp_info.green_mask=0x0000ff00U; - bmp_info.blue_mask=0x000000ffU; - if (bmp_info.bits_per_pixel == 16) - { - /* - RGB555. - */ - bmp_info.red_mask=0x00007c00U; - bmp_info.green_mask=0x000003e0U; - bmp_info.blue_mask=0x0000001fU; - } - } - (void) memset(&shift,0,sizeof(shift)); - (void) memset(&quantum_bits,0,sizeof(quantum_bits)); - if ((bmp_info.bits_per_pixel == 16) || (bmp_info.bits_per_pixel == 32)) - { - unsigned int - sample; - - /* - Get shift and quantum bits info from bitfield masks. - */ - if (bmp_info.red_mask != 0) - while (((bmp_info.red_mask << shift.red) & 0x80000000UL) == 0) - { - shift.red++; - if (shift.red >= 32U) - break; - } - if (bmp_info.green_mask != 0) - while (((bmp_info.green_mask << shift.green) & 0x80000000UL) == 0) - { - shift.green++; - if (shift.green >= 32U) - break; - } - if (bmp_info.blue_mask != 0) - while (((bmp_info.blue_mask << shift.blue) & 0x80000000UL) == 0) - { - shift.blue++; - if (shift.blue >= 32U) - break; - } - if (bmp_info.alpha_mask != 0) - while (((bmp_info.alpha_mask << shift.alpha) & 0x80000000UL) == 0) - { - shift.alpha++; - if (shift.alpha >= 32U) - break; - } - sample=shift.red; - while (((bmp_info.red_mask << sample) & 0x80000000UL) != 0) - { - sample++; - if (sample >= 32U) - break; - } - quantum_bits.red=(MagickRealType) (sample-shift.red); - sample=shift.green; - while (((bmp_info.green_mask << sample) & 0x80000000UL) != 0) - { - sample++; - if (sample >= 32U) - break; - } - quantum_bits.green=(MagickRealType) (sample-shift.green); - sample=shift.blue; - while (((bmp_info.blue_mask << sample) & 0x80000000UL) != 0) - { - sample++; - if (sample >= 32U) - break; - } - quantum_bits.blue=(MagickRealType) (sample-shift.blue); - sample=shift.alpha; - while (((bmp_info.alpha_mask << sample) & 0x80000000UL) != 0) - { - sample++; - if (sample >= 32U) - break; - } - quantum_bits.alpha=(MagickRealType) (sample-shift.alpha); - } - switch (bmp_info.bits_per_pixel) - { - case 1: - { - /* - Convert bitmap scanline. - */ - for (y=(ssize_t) image->rows-1; y >= 0; y--) - { - p=pixels+(image->rows-y-1)*bytes_per_line; - q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); - if (q == (Quantum *) NULL) - break; - for (x=0; x < ((ssize_t) image->columns-7); x+=8) - { - for (bit=0; bit < 8; bit++) - { - index=(Quantum) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00); - SetPixelIndex(image,index,q); - q+=GetPixelChannels(image); - } - p++; - } - if ((image->columns % 8) != 0) - { - for (bit=0; bit < (image->columns % 8); bit++) - { - index=(Quantum) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00); - SetPixelIndex(image,index,q); - q+=GetPixelChannels(image); - } - p++; - } - if (SyncAuthenticPixels(image,exception) == MagickFalse) - break; - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) - (image->rows-y),image->rows); - if (status == MagickFalse) - break; - } - } - (void) SyncImage(image,exception); - break; - } - case 4: - { - /* - Convert PseudoColor scanline. - */ - for (y=(ssize_t) image->rows-1; y >= 0; y--) - { - p=pixels+(image->rows-y-1)*bytes_per_line; - q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); - if (q == (Quantum *) NULL) - break; - for (x=0; x < ((ssize_t) image->columns-1); x+=2) - { - ValidateColormapValue(image,(ssize_t) ((*p >> 4) & 0x0f),&index, - exception); - SetPixelIndex(image,index,q); - q+=GetPixelChannels(image); - ValidateColormapValue(image,(ssize_t) (*p & 0x0f),&index,exception); - SetPixelIndex(image,index,q); - q+=GetPixelChannels(image); - p++; - } - if ((image->columns % 2) != 0) - { - ValidateColormapValue(image,(ssize_t) ((*p >> 4) & 0xf),&index, - exception); - SetPixelIndex(image,index,q); - q+=GetPixelChannels(image); - p++; - x++; - } - if (x < (ssize_t) image->columns) - break; - if (SyncAuthenticPixels(image,exception) == MagickFalse) - break; - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) - (image->rows-y),image->rows); - if (status == MagickFalse) - break; - } - } - (void) SyncImage(image,exception); - break; - } - case 8: - { - /* - Convert PseudoColor scanline. - */ - if ((bmp_info.compression == BI_RLE8) || - (bmp_info.compression == BI_RLE4)) - bytes_per_line=image->columns; - for (y=(ssize_t) image->rows-1; y >= 0; y--) - { - p=pixels+(image->rows-y-1)*bytes_per_line; - q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); - if (q == (Quantum *) NULL) - break; - for (x=(ssize_t) image->columns; x != 0; --x) - { - ValidateColormapValue(image,(ssize_t) *p++,&index,exception); - SetPixelIndex(image,index,q); - q+=GetPixelChannels(image); - } - if (SyncAuthenticPixels(image,exception) == MagickFalse) - break; - offset=(MagickOffsetType) (image->rows-y-1); - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) - (image->rows-y),image->rows); - if (status == MagickFalse) - break; - } - } - (void) SyncImage(image,exception); - break; - } - case 16: - { - unsigned int - alpha, - pixel; - - /* - Convert bitfield encoded 16-bit PseudoColor scanline. - */ - if ((bmp_info.compression != BI_RGB) && - (bmp_info.compression != BI_BITFIELDS)) - { - pixel_info=RelinquishVirtualMemory(pixel_info); - ThrowReaderException(CorruptImageError, - "UnrecognizedImageCompression"); - } - bytes_per_line=2*(image->columns+image->columns % 2); - image->storage_class=DirectClass; - for (y=(ssize_t) image->rows-1; y >= 0; y--) - { - p=pixels+(image->rows-y-1)*bytes_per_line; - q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); - if (q == (Quantum *) NULL) - break; - for (x=0; x < (ssize_t) image->columns; x++) - { - pixel=(unsigned int) (*p++); - pixel|=(*p++) << 8; - red=((pixel & bmp_info.red_mask) << shift.red) >> 16; - if (quantum_bits.red == 5) - red|=((red & 0xe000) >> 5); - if (quantum_bits.red <= 8) - red|=((red & 0xff00) >> 8); - green=((pixel & bmp_info.green_mask) << shift.green) >> 16; - if (quantum_bits.green == 5) - green|=((green & 0xe000) >> 5); - if (quantum_bits.green == 6) - green|=((green & 0xc000) >> 6); - if (quantum_bits.green <= 8) - green|=((green & 0xff00) >> 8); - blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16; - if (quantum_bits.blue == 5) - blue|=((blue & 0xe000) >> 5); - if (quantum_bits.blue <= 8) - blue|=((blue & 0xff00) >> 8); - SetPixelRed(image,ScaleShortToQuantum((unsigned short) red),q); - SetPixelGreen(image,ScaleShortToQuantum((unsigned short) green),q); - SetPixelBlue(image,ScaleShortToQuantum((unsigned short) blue),q); - SetPixelAlpha(image,OpaqueAlpha,q); - if (image->alpha_trait != UndefinedPixelTrait) - { - alpha=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16; - if (quantum_bits.alpha <= 8) - alpha|=((alpha & 0xff00) >> 8); - SetPixelAlpha(image,ScaleShortToQuantum( - (unsigned short) alpha),q); - } - q+=GetPixelChannels(image); - } - if (SyncAuthenticPixels(image,exception) == MagickFalse) - break; - offset=(MagickOffsetType) (image->rows-y-1); - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) - (image->rows-y),image->rows); - if (status == MagickFalse) - break; - } - } - break; - } - case 24: - { - /* - Convert DirectColor scanline. - */ - bytes_per_line=4*((image->columns*24+31)/32); - for (y=(ssize_t) image->rows-1; y >= 0; y--) - { - p=pixels+(image->rows-y-1)*bytes_per_line; - q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); - if (q == (Quantum *) NULL) - break; - for (x=0; x < (ssize_t) image->columns; x++) - { - SetPixelBlue(image,ScaleCharToQuantum(*p++),q); - SetPixelGreen(image,ScaleCharToQuantum(*p++),q); - SetPixelRed(image,ScaleCharToQuantum(*p++),q); - SetPixelAlpha(image,OpaqueAlpha,q); - q+=GetPixelChannels(image); - } - if (SyncAuthenticPixels(image,exception) == MagickFalse) - break; - offset=(MagickOffsetType) (image->rows-y-1); - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) - (image->rows-y),image->rows); - if (status == MagickFalse) - break; - } - } - break; - } - case 32: - { - /* - Convert bitfield encoded DirectColor scanline. - */ - if ((bmp_info.compression != BI_RGB) && - (bmp_info.compression != BI_BITFIELDS)) - { - pixel_info=RelinquishVirtualMemory(pixel_info); - ThrowReaderException(CorruptImageError, - "UnrecognizedImageCompression"); - } - bytes_per_line=4*(image->columns); - for (y=(ssize_t) image->rows-1; y >= 0; y--) - { - unsigned int - alpha, - pixel; - - p=pixels+(image->rows-y-1)*bytes_per_line; - q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); - if (q == (Quantum *) NULL) - break; - for (x=0; x < (ssize_t) image->columns; x++) - { - pixel=(unsigned int) (*p++); - pixel|=((unsigned int) *p++ << 8); - pixel|=((unsigned int) *p++ << 16); - pixel|=((unsigned int) *p++ << 24); - red=((pixel & bmp_info.red_mask) << shift.red) >> 16; - if (quantum_bits.red == 8) - red|=(red >> 8); - green=((pixel & bmp_info.green_mask) << shift.green) >> 16; - if (quantum_bits.green == 8) - green|=(green >> 8); - blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16; - if (quantum_bits.blue == 8) - blue|=(blue >> 8); - SetPixelRed(image,ScaleShortToQuantum((unsigned short) red),q); - SetPixelGreen(image,ScaleShortToQuantum((unsigned short) green),q); - SetPixelBlue(image,ScaleShortToQuantum((unsigned short) blue),q); - SetPixelAlpha(image,OpaqueAlpha,q); - if (image->alpha_trait != UndefinedPixelTrait) - { - alpha=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16; - if (quantum_bits.alpha == 8) - alpha|=(alpha >> 8); - SetPixelAlpha(image,ScaleShortToQuantum( - (unsigned short) alpha),q); - } - q+=GetPixelChannels(image); - } - if (SyncAuthenticPixels(image,exception) == MagickFalse) - break; - offset=(MagickOffsetType) (image->rows-y-1); - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) - (image->rows-y),image->rows); - if (status == MagickFalse) - break; - } - } - break; - } - default: - { - pixel_info=RelinquishVirtualMemory(pixel_info); - ThrowReaderException(CorruptImageError,"ImproperImageHeader"); - } - } - pixel_info=RelinquishVirtualMemory(pixel_info); - if (y > 0) - break; - if (EOFBlob(image) != MagickFalse) - { - ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", - image->filename); - break; - } - if (bmp_info.height < 0) - { - Image - *flipped_image; - - /* - Correct image orientation. - */ - flipped_image=FlipImage(image,exception); - if (flipped_image != (Image *) NULL) - { - DuplicateBlob(flipped_image,image); - ReplaceImageInList(&image, flipped_image); - image=flipped_image; - } - } - /* - Read embeded ICC profile - */ - if ((bmp_info.colorspace == 0x4D424544L) && (profile_data > 0) && - (profile_size > 0)) - { - StringInfo - *profile; - - unsigned char - *datum; - - offset=start_position+14+profile_data; - if ((offset < TellBlob(image)) || - (SeekBlob(image,offset,SEEK_SET) != offset) || - (blob_size < (MagickSizeType) (offset+profile_size))) - ThrowReaderException(CorruptImageError,"ImproperImageHeader"); - profile=AcquireStringInfo((size_t) profile_size); - if (profile == (StringInfo *) NULL) - ThrowReaderException(CorruptImageError,"MemoryAllocationFailed"); - datum=GetStringInfoDatum(profile); - if (ReadBlob(image,(size_t) profile_size,datum) == (ssize_t) profile_size) - { - MagickOffsetType - profile_size_orig; - - /* - Trimming padded bytes. - */ - profile_size_orig=(MagickOffsetType) datum[0] << 24; - profile_size_orig|=(MagickOffsetType) datum[1] << 16; - profile_size_orig|=(MagickOffsetType) datum[2] << 8; - profile_size_orig|=(MagickOffsetType) datum[3]; - if (profile_size_orig < profile_size) - SetStringInfoLength(profile,(size_t) profile_size_orig); - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - "Profile: ICC, %u bytes",(unsigned int) profile_size_orig); - (void) SetImageProfile(image,"icc",profile,exception); - } - profile=DestroyStringInfo(profile); - } - /* - Proceed to next image. - */ - if (image_info->number_scenes != 0) - if (image->scene >= (image_info->scene+image_info->number_scenes-1)) - break; - offset=(MagickOffsetType) bmp_info.ba_offset; - if (offset != 0) - if ((offset < TellBlob(image)) || - (SeekBlob(image,offset,SEEK_SET) != offset)) - ThrowReaderException(CorruptImageError,"ImproperImageHeader"); - *magick='\0'; - count=ReadBlob(image,2,magick); - if ((count == 2) && (IsBMP(magick,2) != MagickFalse)) - { - /* - Acquire next image structure. - */ - AcquireNextImage(image_info,image,exception); - if (GetNextImageInList(image) == (Image *) NULL) - { - status=MagickFalse; - break; - } - image=SyncNextImageInList(image); - status=SetImageProgress(image,LoadImagesTag,TellBlob(image),blob_size); - if (status == MagickFalse) - break; - } - } while (IsBMP(magick,2) != MagickFalse); - (void) CloseBlob(image); - if (status == MagickFalse) - return(DestroyImageList(image)); - return(GetFirstImageInList(image)); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% R e g i s t e r B M P I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% RegisterBMPImage() adds attributes for the BMP image format to -% the list of supported formats. The attributes include the image format -% tag, a method to read and/or write the format, whether the format -% supports the saving of more than one frame to the same file or blob, -% whether the format supports native in-memory I/O, and a brief -% description of the format. -% -% The format of the RegisterBMPImage method is: -% -% size_t RegisterBMPImage(void) -% -*/ -ModuleExport size_t RegisterBMPImage(void) -{ - MagickInfo - *entry; - - entry=AcquireMagickInfo("BMP","BMP","Microsoft Windows bitmap image"); - entry->decoder=(DecodeImageHandler *) ReadBMPImage; - entry->encoder=(EncodeImageHandler *) WriteBMPImage; - entry->magick=(IsImageFormatHandler *) IsBMP; - entry->flags^=CoderAdjoinFlag; - entry->flags|=CoderDecoderSeekableStreamFlag; - entry->mime_type=ConstantString("image/bmp"); - (void) RegisterMagickInfo(entry); - entry=AcquireMagickInfo("BMP","BMP2","Microsoft Windows bitmap image (V2)"); - entry->decoder=(DecodeImageHandler *) ReadBMPImage; - entry->encoder=(EncodeImageHandler *) WriteBMPImage; - entry->magick=(IsImageFormatHandler *) IsBMP; - entry->flags^=CoderAdjoinFlag; - entry->flags|=CoderDecoderSeekableStreamFlag; - entry->mime_type=ConstantString("image/bmp"); - (void) RegisterMagickInfo(entry); - entry=AcquireMagickInfo("BMP","BMP3","Microsoft Windows bitmap image (V3)"); - entry->decoder=(DecodeImageHandler *) ReadBMPImage; - entry->encoder=(EncodeImageHandler *) WriteBMPImage; - entry->magick=(IsImageFormatHandler *) IsBMP; - entry->flags^=CoderAdjoinFlag; - entry->flags|=CoderDecoderSeekableStreamFlag; - entry->mime_type=ConstantString("image/bmp"); - (void) RegisterMagickInfo(entry); - return(MagickImageCoderSignature); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% U n r e g i s t e r B M P I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% UnregisterBMPImage() removes format registrations made by the -% BMP module from the list of supported formats. -% -% The format of the UnregisterBMPImage method is: -% -% UnregisterBMPImage(void) -% -*/ -ModuleExport void UnregisterBMPImage(void) -{ - (void) UnregisterMagickInfo("BMP"); - (void) UnregisterMagickInfo("BMP2"); - (void) UnregisterMagickInfo("BMP3"); -} - -/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% W r i t e B M P I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% WriteBMPImage() writes an image in Microsoft Windows bitmap encoded -% image format, version 3 for Windows or (if the image has a matte channel) -% version 4. -% -% The format of the WriteBMPImage method is: -% -% MagickBooleanType WriteBMPImage(const ImageInfo *image_info, -% Image *image,ExceptionInfo *exception) -% -% A description of each parameter follows. -% -% o image_info: the image info. -% -% o image: The image. -% -% o exception: return any errors or warnings in this structure. -% -*/ -static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image, - ExceptionInfo *exception) -{ - BMPInfo - bmp_info; - - BMPSubtype - bmp_subtype; - - const char - *option; - - const StringInfo - *profile; - - MagickBooleanType - have_color_info, - status; - - MagickOffsetType - scene; - - MemoryInfo - *pixel_info; - - const Quantum - *p; - - ssize_t - i, - x; - - unsigned char - *q; - - size_t - bytes_per_line, - imageListLength, - type; - - ssize_t - y; - - unsigned char - *bmp_data, - *pixels; - - MagickOffsetType - profile_data, - profile_size, - profile_size_pad; - - /* - Open output image file. - */ - assert(image_info != (const ImageInfo *) NULL); - assert(image_info->signature == MagickCoreSignature); - assert(image != (Image *) NULL); - assert(image->signature == MagickCoreSignature); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - if (IsEventLogging() != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); - if (status == MagickFalse) - return(status); - if (((image->columns << 3) != (size_t) ((int) (image->columns << 3))) || - ((image->rows << 3) != (size_t) ((int) (image->rows << 3)))) - ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); - type=4; - if (LocaleCompare(image_info->magick,"BMP2") == 0) - type=2; - else - if (LocaleCompare(image_info->magick,"BMP3") == 0) - type=3; - option=GetImageOption(image_info,"bmp:format"); - if (option != (char *) NULL) - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Format=%s",option); - if (LocaleCompare(option,"bmp2") == 0) - type=2; - if (LocaleCompare(option,"bmp3") == 0) - type=3; - if (LocaleCompare(option,"bmp4") == 0) - type=4; - } - scene=0; - imageListLength=GetImageListLength(image); - do - { - /* - Initialize BMP raster file header. - */ - if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse) - (void) TransformImageColorspace(image,sRGBColorspace,exception); - (void) memset(&bmp_info,0,sizeof(bmp_info)); - bmp_info.file_size=14+12; - if (type > 2) - bmp_info.file_size+=28; - bmp_info.offset_bits=bmp_info.file_size; - bmp_info.compression=BI_RGB; - bmp_info.red_mask=0x00ff0000U; - bmp_info.green_mask=0x0000ff00U; - bmp_info.blue_mask=0x000000ffU; - bmp_info.alpha_mask=0xff000000U; - bmp_subtype=UndefinedSubtype; - if ((image->storage_class == PseudoClass) && (image->colors > 256)) - (void) SetImageStorageClass(image,DirectClass,exception); - if (image->storage_class != DirectClass) - { - /* - Colormapped BMP raster. - */ - bmp_info.bits_per_pixel=8; - if (image->colors <= 2) - bmp_info.bits_per_pixel=1; - else - if (image->colors <= 16) - bmp_info.bits_per_pixel=4; - else - if (image->colors <= 256) - bmp_info.bits_per_pixel=8; - if (image_info->compression == RLECompression) - bmp_info.bits_per_pixel=8; - bmp_info.number_colors=1U << bmp_info.bits_per_pixel; - if (image->alpha_trait != UndefinedPixelTrait) - (void) SetImageStorageClass(image,DirectClass,exception); - else - if ((size_t) bmp_info.number_colors < image->colors) - (void) SetImageStorageClass(image,DirectClass,exception); - else - { - bmp_info.file_size+=3*(1UL << bmp_info.bits_per_pixel); - bmp_info.offset_bits+=3*(1UL << bmp_info.bits_per_pixel); - if (type > 2) - { - bmp_info.file_size+=(1UL << bmp_info.bits_per_pixel); - bmp_info.offset_bits+=(1UL << bmp_info.bits_per_pixel); - } - } - } - if (image->storage_class == DirectClass) - { - /* - Full color BMP raster. - */ - bmp_info.number_colors=0; - option=GetImageOption(image_info,"bmp:subtype"); - if (option != (const char *) NULL) - { - if (image->alpha_trait != UndefinedPixelTrait) - { - if (LocaleNCompare(option,"ARGB4444",8) == 0) - { - bmp_subtype=ARGB4444; - bmp_info.red_mask=0x00000f00U; - bmp_info.green_mask=0x000000f0U; - bmp_info.blue_mask=0x0000000fU; - bmp_info.alpha_mask=0x0000f000U; - } - else if (LocaleNCompare(option,"ARGB1555",8) == 0) - { - bmp_subtype=ARGB1555; - bmp_info.red_mask=0x00007c00U; - bmp_info.green_mask=0x000003e0U; - bmp_info.blue_mask=0x0000001fU; - bmp_info.alpha_mask=0x00008000U; - } - } - else - { - if (LocaleNCompare(option,"RGB555",6) == 0) - { - bmp_subtype=RGB555; - bmp_info.red_mask=0x00007c00U; - bmp_info.green_mask=0x000003e0U; - bmp_info.blue_mask=0x0000001fU; - bmp_info.alpha_mask=0U; - } - else if (LocaleNCompare(option,"RGB565",6) == 0) - { - bmp_subtype=RGB565; - bmp_info.red_mask=0x0000f800U; - bmp_info.green_mask=0x000007e0U; - bmp_info.blue_mask=0x0000001fU; - bmp_info.alpha_mask=0U; - } - } - } - if (bmp_subtype != UndefinedSubtype) - { - bmp_info.bits_per_pixel=16; - bmp_info.compression=BI_BITFIELDS; - } - else - { - bmp_info.bits_per_pixel=(unsigned short) ((type > 3) && - (image->alpha_trait != UndefinedPixelTrait) ? 32 : 24); - bmp_info.compression=(unsigned int) ((type > 3) && - (image->alpha_trait != UndefinedPixelTrait) ? BI_BITFIELDS : BI_RGB); - if ((type == 3) && (image->alpha_trait != UndefinedPixelTrait)) - { - option=GetImageOption(image_info,"bmp3:alpha"); - if (IsStringTrue(option)) - bmp_info.bits_per_pixel=32; - } - } - } - bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32); - bmp_info.ba_offset=0; - profile=GetImageProfile(image,"icc"); - have_color_info=(image->rendering_intent != UndefinedIntent) || - (profile != (StringInfo *) NULL) || (image->gamma != 0.0) ? MagickTrue : - MagickFalse; - if (type == 2) - bmp_info.size=12; - else - if ((type == 3) || ((image->alpha_trait == UndefinedPixelTrait) && - (have_color_info == MagickFalse))) - { - type=3; - bmp_info.size=40; - } - else - { - int - extra_size; - - bmp_info.size=108; - extra_size=68; - if ((image->rendering_intent != UndefinedIntent) || - (profile != (StringInfo *) NULL)) - { - bmp_info.size=124; - extra_size+=16; - } - bmp_info.file_size+=extra_size; - bmp_info.offset_bits+=extra_size; - } - if (((ssize_t) image->columns != (ssize_t) ((signed int) image->columns)) || - ((ssize_t) image->rows != (ssize_t) ((signed int) image->rows))) - ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); - bmp_info.width=(ssize_t) image->columns; - bmp_info.height=(ssize_t) image->rows; - bmp_info.planes=1; - bmp_info.image_size=(unsigned int) (bytes_per_line*image->rows); - bmp_info.file_size+=bmp_info.image_size; - bmp_info.x_pixels=75*39; - bmp_info.y_pixels=75*39; - switch (image->units) - { - case UndefinedResolution: - case PixelsPerInchResolution: - { - bmp_info.x_pixels=(unsigned int) (100.0*image->resolution.x/2.54); - bmp_info.y_pixels=(unsigned int) (100.0*image->resolution.y/2.54); - break; - } - case PixelsPerCentimeterResolution: - { - bmp_info.x_pixels=(unsigned int) (100.0*image->resolution.x); - bmp_info.y_pixels=(unsigned int) (100.0*image->resolution.y); - break; - } - } - bmp_info.colors_important=bmp_info.number_colors; - /* - Convert MIFF to BMP raster pixels. - */ - pixel_info=AcquireVirtualMemory(image->rows,MagickMax(bytes_per_line, - image->columns+256UL)*sizeof(*pixels)); - if (pixel_info == (MemoryInfo *) NULL) - ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); - pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); - (void) memset(pixels,0,(size_t) bmp_info.image_size); - switch (bmp_info.bits_per_pixel) - { - case 1: - { - size_t - bit, - byte; - - /* - Convert PseudoClass image to a BMP monochrome image. - */ - for (y=0; y < (ssize_t) image->rows; y++) - { - ssize_t - offset; - - p=GetVirtualPixels(image,0,y,image->columns,1,exception); - if (p == (const Quantum *) NULL) - break; - q=pixels+(image->rows-y-1)*bytes_per_line; - bit=0; - byte=0; - for (x=0; x < (ssize_t) image->columns; x++) - { - byte<<=1; - byte|=GetPixelIndex(image,p) != 0 ? 0x01 : 0x00; - bit++; - if (bit == 8) - { - *q++=(unsigned char) byte; - bit=0; - byte=0; - } - p+=GetPixelChannels(image); - } - if (bit != 0) - { - *q++=(unsigned char) (byte << (8-bit)); - x++; - } - offset=(ssize_t) (image->columns+7)/8; - for (x=offset; x < (ssize_t) bytes_per_line; x++) - *q++=0x00; - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, - image->rows); - if (status == MagickFalse) - break; - } - } - break; - } - case 4: - { - unsigned int - byte, - nibble; - - ssize_t - offset; - - /* - Convert PseudoClass image to a BMP monochrome image. - */ - for (y=0; y < (ssize_t) image->rows; y++) - { - p=GetVirtualPixels(image,0,y,image->columns,1,exception); - if (p == (const Quantum *) NULL) - break; - q=pixels+(image->rows-y-1)*bytes_per_line; - nibble=0; - byte=0; - for (x=0; x < (ssize_t) image->columns; x++) - { - byte<<=4; - byte|=((unsigned int) GetPixelIndex(image,p) & 0x0f); - nibble++; - if (nibble == 2) - { - *q++=(unsigned char) byte; - nibble=0; - byte=0; - } - p+=GetPixelChannels(image); - } - if (nibble != 0) - { - *q++=(unsigned char) (byte << 4); - x++; - } - offset=(ssize_t) (image->columns+1)/2; - for (x=offset; x < (ssize_t) bytes_per_line; x++) - *q++=0x00; - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, - image->rows); - if (status == MagickFalse) - break; - } - } - break; - } - case 8: - { - /* - Convert PseudoClass packet to BMP pixel. - */ - for (y=0; y < (ssize_t) image->rows; y++) - { - p=GetVirtualPixels(image,0,y,image->columns,1,exception); - if (p == (const Quantum *) NULL) - break; - q=pixels+(image->rows-y-1)*bytes_per_line; - for (x=0; x < (ssize_t) image->columns; x++) - { - *q++=(unsigned char) ((ssize_t) GetPixelIndex(image,p)); - p+=GetPixelChannels(image); - } - for ( ; x < (ssize_t) bytes_per_line; x++) - *q++=0x00; - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, - image->rows); - if (status == MagickFalse) - break; - } - } - break; - } - case 16: - { - /* - Convert DirectClass packet to BMP BGR888. - */ - for (y=0; y < (ssize_t) image->rows; y++) - { - p=GetVirtualPixels(image,0,y,image->columns,1,exception); - if (p == (const Quantum *) NULL) - break; - q=pixels+(image->rows-y-1)*bytes_per_line; - for (x=0; x < (ssize_t) image->columns; x++) - { - unsigned short - pixel; - - pixel=0; - if (bmp_subtype == ARGB4444) - { - pixel=(unsigned short) (ScaleQuantumToAny( - GetPixelAlpha(image,p),15) << 12); - pixel|=(unsigned short) (ScaleQuantumToAny( - GetPixelRed(image,p),15) << 8); - pixel|=(unsigned short) (ScaleQuantumToAny( - GetPixelGreen(image,p),15) << 4); - pixel|=(unsigned short) (ScaleQuantumToAny( - GetPixelBlue(image,p),15)); - } - else if (bmp_subtype == RGB565) - { - pixel=(unsigned short) (ScaleQuantumToAny( - GetPixelRed(image,p),31) << 11); - pixel|=(unsigned short) (ScaleQuantumToAny( - GetPixelGreen(image,p),63) << 5); - pixel|=(unsigned short) (ScaleQuantumToAny( - GetPixelBlue(image,p),31)); - } - else - { - if (bmp_subtype == ARGB1555) - pixel=(unsigned short) (ScaleQuantumToAny( - GetPixelAlpha(image,p),1) << 15); - pixel|=(unsigned short) (ScaleQuantumToAny( - GetPixelRed(image,p),31) << 10); - pixel|=(unsigned short) (ScaleQuantumToAny( - GetPixelGreen(image,p),31) << 5); - pixel|=(unsigned short) (ScaleQuantumToAny( - GetPixelBlue(image,p),31)); - } - *((unsigned short *) q)=pixel; - q+=2; - p+=GetPixelChannels(image); - } - for (x=2L*(ssize_t) image->columns; x < (ssize_t) bytes_per_line; x++) - *q++=0x00; - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, - image->rows); - if (status == MagickFalse) - break; - } - } - break; - } - case 24: - { - /* - Convert DirectClass packet to BMP BGR888. - */ - for (y=0; y < (ssize_t) image->rows; y++) - { - p=GetVirtualPixels(image,0,y,image->columns,1,exception); - if (p == (const Quantum *) NULL) - break; - q=pixels+(image->rows-y-1)*bytes_per_line; - for (x=0; x < (ssize_t) image->columns; x++) - { - *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); - *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); - *q++=ScaleQuantumToChar(GetPixelRed(image,p)); - p+=GetPixelChannels(image); - } - for (x=3L*(ssize_t) image->columns; x < (ssize_t) bytes_per_line; x++) - *q++=0x00; - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, - image->rows); - if (status == MagickFalse) - break; - } - } - break; - } - case 32: - { - /* - Convert DirectClass packet to ARGB8888 pixel. - */ - for (y=0; y < (ssize_t) image->rows; y++) - { - p=GetVirtualPixels(image,0,y,image->columns,1,exception); - if (p == (const Quantum *) NULL) - break; - q=pixels+(image->rows-y-1)*bytes_per_line; - for (x=0; x < (ssize_t) image->columns; x++) - { - *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); - *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); - *q++=ScaleQuantumToChar(GetPixelRed(image,p)); - *q++=ScaleQuantumToChar(GetPixelAlpha(image,p)); - p+=GetPixelChannels(image); - } - if (image->previous == (Image *) NULL) - { - status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, - image->rows); - if (status == MagickFalse) - break; - } - } - break; - } - } - if ((type > 2) && (bmp_info.bits_per_pixel == 8)) - if (image_info->compression != NoCompression) - { - MemoryInfo - *rle_info; - - /* - Convert run-length encoded raster pixels. - */ - rle_info=AcquireVirtualMemory((size_t) (2*(bytes_per_line+2)+2), - (image->rows+2)*sizeof(*pixels)); - if (rle_info == (MemoryInfo *) NULL) - { - pixel_info=RelinquishVirtualMemory(pixel_info); - ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); - } - bmp_data=(unsigned char *) GetVirtualMemoryBlob(rle_info); - bmp_info.file_size-=bmp_info.image_size; - bmp_info.image_size=(unsigned int) EncodeImage(image,bytes_per_line, - pixels,bmp_data); - bmp_info.file_size+=bmp_info.image_size; - pixel_info=RelinquishVirtualMemory(pixel_info); - pixel_info=rle_info; - pixels=bmp_data; - bmp_info.compression=BI_RLE8; - } - /* - Write BMP for Windows, all versions, 14-byte header. - */ - if (image->debug != MagickFalse) - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Writing BMP version %.20g datastream",(double) type); - if (image->storage_class == DirectClass) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Storage class=DirectClass"); - else - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Storage class=PseudoClass"); - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Image depth=%.20g",(double) image->depth); - if (image->alpha_trait != UndefinedPixelTrait) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Matte=True"); - else - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Matte=MagickFalse"); - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " BMP bits_per_pixel=%.20g",(double) bmp_info.bits_per_pixel); - switch ((int) bmp_info.compression) - { - case BI_RGB: - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Compression=BI_RGB"); - break; - } - case BI_RLE8: - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Compression=BI_RLE8"); - break; - } - case BI_BITFIELDS: - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Compression=BI_BITFIELDS"); - break; - } - default: - { - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Compression=UNKNOWN (%u)",bmp_info.compression); - break; - } - } - if (bmp_info.number_colors == 0) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Number_colors=unspecified"); - else - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Number_colors=%u",bmp_info.number_colors); - } - profile_data=0; - profile_size=0; - profile_size_pad=0; - if (profile != (StringInfo *) NULL) - { - profile_data=(MagickOffsetType) bmp_info.file_size-14; /* from head of BMP info header */ - profile_size=(MagickOffsetType) GetStringInfoLength(profile); - if ((profile_size % 4) > 0) - profile_size_pad=4-(profile_size%4); - bmp_info.file_size+=profile_size+profile_size_pad; - } - (void) WriteBlob(image,2,(unsigned char *) "BM"); - (void) WriteBlobLSBLong(image,bmp_info.file_size); - (void) WriteBlobLSBLong(image,bmp_info.ba_offset); /* always 0 */ - (void) WriteBlobLSBLong(image,bmp_info.offset_bits); - if (type == 2) - { - /* - Write 12-byte version 2 bitmap header. - */ - (void) WriteBlobLSBLong(image,bmp_info.size); - (void) WriteBlobLSBSignedShort(image,(signed short) bmp_info.width); - (void) WriteBlobLSBSignedShort(image,(signed short) bmp_info.height); - (void) WriteBlobLSBShort(image,bmp_info.planes); - (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel); - } - else - { - /* - Write 40-byte version 3+ bitmap header. - */ - (void) WriteBlobLSBLong(image,bmp_info.size); - (void) WriteBlobLSBSignedLong(image,(signed int) bmp_info.width); - (void) WriteBlobLSBSignedLong(image,(signed int) bmp_info.height); - (void) WriteBlobLSBShort(image,bmp_info.planes); - (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel); - (void) WriteBlobLSBLong(image,bmp_info.compression); - (void) WriteBlobLSBLong(image,bmp_info.image_size); - (void) WriteBlobLSBLong(image,bmp_info.x_pixels); - (void) WriteBlobLSBLong(image,bmp_info.y_pixels); - (void) WriteBlobLSBLong(image,bmp_info.number_colors); - (void) WriteBlobLSBLong(image,bmp_info.colors_important); - } - if ((type > 3) && ((image->alpha_trait != UndefinedPixelTrait) || - (have_color_info != MagickFalse))) - { - /* - Write the rest of the 108-byte BMP Version 4 header. - */ - (void) WriteBlobLSBLong(image,bmp_info.red_mask); - (void) WriteBlobLSBLong(image,bmp_info.green_mask); - (void) WriteBlobLSBLong(image,bmp_info.blue_mask); - (void) WriteBlobLSBLong(image,bmp_info.alpha_mask); - if (profile != (StringInfo *) NULL) - (void) WriteBlobLSBLong(image,0x4D424544U); /* PROFILE_EMBEDDED */ - else - (void) WriteBlobLSBLong(image,0x73524742U); /* sRGB */ - - // bounds check, assign .0 if invalid value - if (isgreater(image->chromaticity.red_primary.x, 1.0) || - !isgreater(image->chromaticity.red_primary.x, 0.0)) - image->chromaticity.red_primary.x = 0.0; - if (isgreater(image->chromaticity.red_primary.y, 1.0) || - !isgreater(image->chromaticity.red_primary.y, 0.0)) - image->chromaticity.red_primary.y = 0.0; - if (isgreater(image->chromaticity.green_primary.x, 1.0) || - !isgreater(image->chromaticity.green_primary.x, 0.0)) - image->chromaticity.green_primary.x = 0.0; - if (isgreater(image->chromaticity.green_primary.y, 1.0) || - !isgreater(image->chromaticity.green_primary.y, 0.0)) - image->chromaticity.green_primary.y = 0.0; - if (isgreater(image->chromaticity.blue_primary.x, 1.0) || - !isgreater(image->chromaticity.blue_primary.x, 0.0)) - image->chromaticity.blue_primary.x = 0.0; - if (isgreater(image->chromaticity.blue_primary.y, 1.0) || - !isgreater(image->chromaticity.blue_primary.y, 0.0)) - image->chromaticity.blue_primary.y = 0.0; - if (isgreater(bmp_info.gamma_scale.x, 1.0) || - !isgreater(bmp_info.gamma_scale.x, 0.0)) - bmp_info.gamma_scale.x = 0.0; - if (isgreater(bmp_info.gamma_scale.y, 1.0) || - !isgreater(bmp_info.gamma_scale.y, 0.0)) - bmp_info.gamma_scale.y = 0.0; - if (isgreater(bmp_info.gamma_scale.z, 1.0) || - !isgreater(bmp_info.gamma_scale.z, 0.0)) - bmp_info.gamma_scale.z = 0.0; - - (void) WriteBlobLSBLong(image,(unsigned int) - (image->chromaticity.red_primary.x*0x40000000)); - (void) WriteBlobLSBLong(image,(unsigned int) - (image->chromaticity.red_primary.y*0x40000000)); - (void) WriteBlobLSBLong(image,(unsigned int) - ((1.000f-(image->chromaticity.red_primary.x+ - image->chromaticity.red_primary.y))*0x40000000)); - (void) WriteBlobLSBLong(image,(unsigned int) - (image->chromaticity.green_primary.x*0x40000000)); - (void) WriteBlobLSBLong(image,(unsigned int) - (image->chromaticity.green_primary.y*0x40000000)); - (void) WriteBlobLSBLong(image,(unsigned int) - ((1.000f-(image->chromaticity.green_primary.x+ - image->chromaticity.green_primary.y))*0x40000000)); - (void) WriteBlobLSBLong(image,(unsigned int) - (image->chromaticity.blue_primary.x*0x40000000)); - (void) WriteBlobLSBLong(image,(unsigned int) - (image->chromaticity.blue_primary.y*0x40000000)); - (void) WriteBlobLSBLong(image,(unsigned int) - ((1.000f-(image->chromaticity.blue_primary.x+ - image->chromaticity.blue_primary.y))*0x40000000)); - (void) WriteBlobLSBLong(image,(unsigned int) - (bmp_info.gamma_scale.x*0x10000)); - (void) WriteBlobLSBLong(image,(unsigned int) - (bmp_info.gamma_scale.y*0x10000)); - (void) WriteBlobLSBLong(image,(unsigned int) - (bmp_info.gamma_scale.z*0x10000)); - if ((image->rendering_intent != UndefinedIntent) || - (profile != (StringInfo *) NULL)) - { - ssize_t - intent; - - switch ((int) image->rendering_intent) - { - case SaturationIntent: - { - intent=LCS_GM_BUSINESS; - break; - } - case RelativeIntent: - { - intent=LCS_GM_GRAPHICS; - break; - } - case PerceptualIntent: - { - intent=LCS_GM_IMAGES; - break; - } - case AbsoluteIntent: - { - intent=LCS_GM_ABS_COLORIMETRIC; - break; - } - default: - { - intent=0; - break; - } - } - (void) WriteBlobLSBLong(image,(unsigned int) intent); - (void) WriteBlobLSBLong(image,(unsigned int) profile_data); - (void) WriteBlobLSBLong(image,(unsigned int) - (profile_size+profile_size_pad)); - (void) WriteBlobLSBLong(image,0x00); /* reserved */ - } - } - if (image->storage_class == PseudoClass) - { - unsigned char - *bmp_colormap; - - /* - Dump colormap to file. - */ - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Colormap: %.20g entries",(double) image->colors); - bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t) (1UL << - bmp_info.bits_per_pixel),4*sizeof(*bmp_colormap)); - if (bmp_colormap == (unsigned char *) NULL) - { - pixel_info=RelinquishVirtualMemory(pixel_info); - ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); - } - q=bmp_colormap; - for (i=0; i < (ssize_t) MagickMin((ssize_t) image->colors,(ssize_t) bmp_info.number_colors); i++) - { - *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue)); - *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green)); - *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red)); - if (type > 2) - *q++=(unsigned char) 0x0; - } - for ( ; i < (ssize_t) (1UL << bmp_info.bits_per_pixel); i++) - { - *q++=(unsigned char) 0x00; - *q++=(unsigned char) 0x00; - *q++=(unsigned char) 0x00; - if (type > 2) - *q++=(unsigned char) 0x00; - } - if (type <= 2) - (void) WriteBlob(image,(size_t) (3*(1L << bmp_info.bits_per_pixel)), - bmp_colormap); - else - (void) WriteBlob(image,(size_t) (4*(1L << bmp_info.bits_per_pixel)), - bmp_colormap); - bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap); - } - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Pixels: %u bytes",bmp_info.image_size); - (void) WriteBlob(image,(size_t) bmp_info.image_size,pixels); - if (profile != (StringInfo *) NULL) - { - if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule(), - " Profile: %g bytes",(double) profile_size+profile_size_pad); - (void) WriteBlob(image,(size_t) profile_size,GetStringInfoDatum(profile)); - if (profile_size_pad > 0) /* padding for 4 bytes multiple */ - (void) WriteBlob(image,(size_t) profile_size_pad,"\0\0\0"); - } - pixel_info=RelinquishVirtualMemory(pixel_info); - if (GetNextImageInList(image) == (Image *) NULL) - break; - image=SyncNextImageInList(image); - status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength); - if (status == MagickFalse) - break; - } while (image_info->adjoin != MagickFalse); - (void) CloseBlob(image); - return(MagickTrue); -} diff --git a/projects/blades-engine/source/Bmp.c.hx.ktxt2 b/projects/blades-engine/source/Bmp.c.hx.ktxt2 deleted file mode 100644 index 322b2ba4..00000000 --- a/projects/blades-engine/source/Bmp.c.hx.ktxt2 +++ /dev/null @@ -1,229 +0,0 @@ -|||/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% BBBB M M PPPP % -% B B MM MM P P % -% BBBB M M M PPPP % -% B B M M P % -% BBBB M M P % -% % -% % -% Read/Write Microsoft Windows Bitmap Image Format % -% % -% Software Design % -% Cristy % -% Glenn Randers-Pehrson % -% December 2001 % -% % -% % -% Copyright @ 2001 ImageMagick Studio LLC, a non-profit organization % -% dedicated to making software imaging solutions freely available. % -% % -% You may not use this file except in compliance with the License. You may % -% obtain a copy of the License at % -% % -% https://imagemagick.org/script/license.php % -% % -% Unless required by applicable law or agreed to in writing, software % -% distributed under the License is distributed on an "AS IS" BASIS, % -% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % -% See the License for the specific language governing permissions and % -% limitations under the License. % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% -*/ - ↵|>|||||||/* - Include declarations. -*/ -#include "MagickCore/studio.h" -#include "MagickCore/blob.h" -#include "MagickCore/blob-private.h" -#include "MagickCore/cache.h" -#include "MagickCore/colormap-private.h" -#include "MagickCore/color-private.h" -#include "MagickCore/colormap.h" -#include "MagickCore/colorspace.h" -#include "MagickCore/colorspace-private.h" -#include "MagickCore/exception.h" -#include "MagickCore/exception-private.h" -#include "MagickCore/image.h" -#include "MagickCore/image-private.h" -#include "MagickCore/list.h" -#include "MagickCore/log.h" -#include "MagickCore/magick.h" -#include "MagickCore/memory_.h" -#include "MagickCore/monitor.h" -#include "MagickCore/monitor-private.h" -#include "MagickCore/option.h" -#include "MagickCore/pixel-accessor.h" -#include "MagickCore/profile.h" -#include "MagickCore/quantum-private.h" -#include "MagickCore/static.h" -#include "MagickCore/string_.h" -#include "MagickCore/module.h" -#include "MagickCore/transform.h" - ↵|>|||||||/* - Macro definitions (from Windows wingdi.h). -*/ -#undef BI_JPEG -#define BI_JPEG 4 -#undef BI_PNG -#define BI_PNG 5 -#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__) -#undef BI_RGB -#define BI_RGB 0 -#undef BI_RLE8 -#define BI_RLE8 1 -#undef BI_RLE4 -#define BI_RLE4 2 -#undef BI_BITFIELDS -#define BI_BITFIELDS 3 - -#undef LCS_CALIBRATED_RBG -#define LCS_CALIBRATED_RBG 0 -#undef LCS_sRGB -#define LCS_sRGB 1 -#undef LCS_WINDOWS_COLOR_SPACE -#define LCS_WINDOWS_COLOR_SPACE 2 -#undef PROFILE_LINKED -#define PROFILE_LINKED 3 -#undef PROFILE_EMBEDDED -#define PROFILE_EMBEDDED 4 - -#undef LCS_GM_BUSINESS -#define LCS_GM_BUSINESS 1 /* Saturation */ -#undef LCS_GM_GRAPHICS -#define LCS_GM_GRAPHICS 2 /* Relative */ -#undef LCS_GM_IMAGES -#define LCS_GM_IMAGES 4 /* Perceptual */ -#undef LCS_GM_ABS_COLORIMETRIC -#define LCS_GM_ABS_COLORIMETRIC 8 /* Absolute */ -#endif - ↵|>|||||||/* - Enumerated declaractions. -*/ -typedef enum -{ - UndefinedSubtype, - RGB555, - RGB565, - ARGB4444, - ARGB1555 -} BMPSubtype;¶|>|||||||/* - Typedef declarations. -*/ -typedef struct _BMPInfo -{↵|>||||||| unsigned int - file_size,↵|>||||||| ba_offset,↵|>||||||| offset_bits,↵|>||||||| size;¶|>||||||| ssize_t - width,↵|>||||||| height;¶|>||||||| unsigned short - planes,↵|>||||||| bits_per_pixel;¶|>||||||| unsigned int - compression,↵|>||||||| image_size,↵|>||||||| x_pixels,↵|>||||||| y_pixels,↵|>||||||| number_colors,↵|>||||||| red_mask,↵|>||||||| green_mask,↵|>||||||| blue_mask,↵|>||||||| alpha_mask,↵|>||||||| colors_important;¶|>||||||| long - colorspace;¶|>||||||| PrimaryInfo - red_primary,↵|>||||||| green_primary,↵|>||||||| blue_primary,↵|>||||||| gamma_scale;↵|>|||||||} BMPInfo; - ↵|>|||||||/* - Forward declarations. -*/ -static MagickBooleanType - WriteBMPImage(const ImageInfo *,Image *,ExceptionInfo *); - ↵|>|||||||/* -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% % -% % -% D e c o d e I m a g e % -% % -% % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% DecodeImage unpacks the packed image pixels into runlength-encoded -% pixel packets. -% -% The format of the DecodeImage method is: -% -% MagickBooleanType DecodeImage(Image *image,const size_t compression, -% unsigned char *pixels,const size_t number_pixels) -% -% A description of each parameter follows: -% -% o image: the address of a structure of type Image. -% -% o compression: Zero means uncompressed. A value of 1 means the -% compressed pixels are runlength encoded for a 256-color bitmap. -% A value of 2 means a 16-color bitmap. A value of 3 means bitfields -% encoding. -% -% o pixels: The address of a byte (8 bits) array of pixel data created by -% the decoding process. -% -% o number_pixels: The number of pixels. -% -*/↵|>|||||||static MagickBooleanType DecodeImage(Image *image,const size_t compression, - unsigned char *pixels,const size_t number_pixels) -{↵|>||||||| int - byte,↵|>||||||| count;¶|>||||||| ssize_t - i,↵|>||||||| x;¶|>||||||| unsigned char - *p,↵|>||||||| *q;¶|>||||||| ssize_t - y;¶|>||||||| assert(image != (Image *) NULL); - assert(image->signature == MagickCoreSignature); - assert(pixels != (unsigned char *) NULL);↵|>||||||| if (IsEventLogging() != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);↵|>||||||| (void) memset(pixels,0,number_pixels*sizeof(*pixels));↵|>||||||| byte=0;↵|>||||||| x=0;↵|>||||||| p=pixels;↵|>||||||| q=pixels+number_pixels;↵|>||||||| for (y=0; y < (ssize_t) image->rows; ) - {↵|>||||||| MagickBooleanType - status;¶|>||||||| if ((p < pixels) || (p > q))↵|>||||||| break;↵|>||||||| count=ReadBlobByte(image);↵|>||||||| if (count == EOF)↵|>||||||| break;↵|>||||||| if (count > 0)↵|>||||||| {↵|>||||||| /*↵|>||||||| Encoded mode.↵|>||||||| */↵|>||||||| count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p));↵|>||||||| byte=ReadBlobByte(image);↵|>||||||| if (byte == EOF)↵|>||||||| break;↵|>||||||| if (compression == BI_RLE8)↵|>||||||| {↵|>||||||| for (i=0; i < (ssize_t) count; i++)↵|>||||||| *p++=(unsigned char) byte;↵|>||||||| }↵|>||||||| else↵|>||||||| {↵|>||||||| for (i=0; i < (ssize_t) count; i++)↵|>||||||| *p++=(unsigned char)↵|>||||||| ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));↵|>||||||| }↵|>||||||| x+=count;↵|>||||||| }↵|>||||||| else↵|>||||||| {↵|>||||||| /*↵|>||||||| Escape mode.↵|>||||||| */↵|>||||||| count=ReadBlobByte(image);↵|>||||||| if (count == EOF)↵|>||||||| break;↵|>||||||| if (count == 0x01)↵|>||||||| return(MagickTrue);↵|>||||||| switch (count)↵|>||||||| {↵|>||||||| case 0x00:↵|>||||||| {↵|>||||||| /*↵|>||||||| End of line.↵|>||||||| */↵|>||||||| x=0;↵|>||||||| y++;↵|>||||||| p=pixels+y*image->columns;↵|>||||||| break;↵|>||||||| }↵|>||||||| case 0x02:↵|>||||||| {↵|>||||||| /*↵|>||||||| Delta mode.↵|>||||||| */↵|>||||||| x+=ReadBlobByte(image);↵|>||||||| y+=ReadBlobByte(image);↵|>||||||| p=pixels+y*image->columns+x;↵|>||||||| break;↵|>||||||| }↵|>||||||| default:↵|>||||||| {↵|>||||||| /*↵|>||||||| Absolute mode.↵|>||||||| */↵|>||||||| count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p));↵|>||||||| if (compression == BI_RLE8)↵|>||||||| for (i=0; i < (ssize_t) count; i++)↵|>||||||| {↵|>||||||| byte=ReadBlobByte(image);↵|>||||||| if (byte == EOF)↵|>||||||| break;↵|>||||||| *p++=(unsigned char) byte;↵|>||||||| }↵|>||||||| else↵|>||||||| for (i=0; i < (ssize_t) count; i++)↵|>||||||| {↵|>||||||| if ((i & 0x01) == 0)↵|>||||||| {↵|>||||||| byte=ReadBlobByte(image);↵|>||||||| if (byte == EOF)↵|>||||||| break;↵|>||||||| }↵|>||||||| *p++=(unsigned char)↵|>||||||| ((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));↵|>||||||| }↵|>||||||| x+=count;↵|>||||||| /*↵|>||||||| Read pad byte.↵|>||||||| */↵|>||||||| if (compression == BI_RLE8)↵|>||||||| {↵|>||||||| if ((count & 0x01) != 0)↵|>||||||| if (ReadBlobByte(image) == EOF)↵|>||||||| break;↵|>||||||| }↵|>||||||| else↵|>||||||| if (((count & 0x03) == 1) || ((count & 0x03) == 2))↵|>||||||| if (ReadBlobByte(image) == EOF)↵|>||||||| break;↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| }↵|>||||||| status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,↵|>||||||| image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| (void) ReadBlobByte(image); /* end of line */↵|>||||||| (void) ReadBlobByte(image);↵|>||||||| return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);↵|>|||||||}↵|>||||||| ↵|>|||||||/*↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% E n c o d e I m a g e %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||%↵|>|||||||% EncodeImage compresses pixels using a runlength encoded format.↵|>|||||||%↵|>|||||||% The format of the EncodeImage method is:↵|>|||||||%↵|>|||||||% static MagickBooleanType EncodeImage(Image *image,↵|>|||||||% const size_t bytes_per_line,const unsigned char *pixels,↵|>|||||||% unsigned char *compressed_pixels)↵|>|||||||%↵|>|||||||% A description of each parameter follows:↵|>|||||||%↵|>|||||||% o image: The image.↵|>|||||||%↵|>|||||||% o bytes_per_line: the number of bytes in a scanline of compressed pixels↵|>|||||||%↵|>|||||||% o pixels: The address of a byte (8 bits) array of pixel data created by↵|>|||||||% the compression process.↵|>|||||||%↵|>|||||||% o compressed_pixels: The address of a byte (8 bits) array of compressed↵|>|||||||% pixel data.↵|>|||||||%↵|>|||||||*/↵|>|||||||static size_t EncodeImage(Image *image,const size_t bytes_per_line,↵|>||||||| const unsigned char *pixels,unsigned char *compressed_pixels)↵|>|||||||{↵|>||||||| MagickBooleanType↵|>||||||| status;↵|>|||||||↵|>||||||| const unsigned char↵|>||||||| *p;↵|>|||||||↵|>||||||| ssize_t↵|>||||||| i,↵|>||||||| x;↵|>|||||||↵|>||||||| unsigned char↵|>||||||| *q;↵|>|||||||↵|>||||||| ssize_t↵|>||||||| y;↵|>|||||||↵|>||||||| /*↵|>||||||| Runlength encode pixels.↵|>||||||| */↵|>||||||| assert(image != (Image *) NULL);↵|>||||||| assert(image->signature == MagickCoreSignature);↵|>||||||| assert(pixels != (const unsigned char *) NULL);↵|>||||||| assert(compressed_pixels != (unsigned char *) NULL);↵|>||||||| if (IsEventLogging() != MagickFalse)↵|>||||||| (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);↵|>||||||| p=pixels;↵|>||||||| q=compressed_pixels;↵|>||||||| i=0;↵|>||||||| for (y=0; y < (ssize_t) image->rows; y++)↵|>||||||| {↵|>||||||| for (x=0; x < (ssize_t) bytes_per_line; x+=i)↵|>||||||| {↵|>||||||| /*↵|>||||||| Determine runlength.↵|>||||||| */↵|>||||||| for (i=1; ((x+i) < (ssize_t) bytes_per_line); i++)↵|>||||||| if ((i == 255) || (*(p+i) != *p))↵|>||||||| break;↵|>||||||| *q++=(unsigned char) i;↵|>||||||| *q++=(*p);↵|>||||||| p+=i;↵|>||||||| }↵|>||||||| /*↵|>||||||| End of line.↵|>||||||| */↵|>||||||| *q++=(unsigned char) 0x00;↵|>||||||| *q++=(unsigned char) 0x00;↵|>||||||| status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,↵|>||||||| image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| /*↵|>||||||| End of bitmap.↵|>||||||| */↵|>||||||| *q++=(unsigned char) 0x00;↵|>||||||| *q++=(unsigned char) 0x01;↵|>||||||| return((size_t) (q-compressed_pixels));↵|>|||||||}↵|>||||||| ↵|>|||||||/*↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% I s B M P %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||%↵|>|||||||% IsBMP() returns MagickTrue if the image format type, identified by the↵|>|||||||% magick string, is BMP.↵|>|||||||%↵|>|||||||% The format of the IsBMP method is:↵|>|||||||%↵|>|||||||% MagickBooleanType IsBMP(const unsigned char *magick,const size_t length)↵|>|||||||%↵|>|||||||% A description of each parameter follows:↵|>|||||||%↵|>|||||||% o magick: compare image format pattern against these bytes.↵|>|||||||%↵|>|||||||% o length: Specifies the length of the magick string.↵|>|||||||%↵|>|||||||*/↵|>|||||||static MagickBooleanType IsBMP(const unsigned char *magick,const size_t length)↵|>|||||||{↵|>||||||| if (length < 2)↵|>||||||| return(MagickFalse);↵|>||||||| if ((LocaleNCompare((char *) magick,"BA",2) == 0) ||↵|>||||||| (LocaleNCompare((char *) magick,"BM",2) == 0) ||↵|>||||||| (LocaleNCompare((char *) magick,"IC",2) == 0) ||↵|>||||||| (LocaleNCompare((char *) magick,"PI",2) == 0) ||↵|>||||||| (LocaleNCompare((char *) magick,"CI",2) == 0) ||↵|>||||||| (LocaleNCompare((char *) magick,"CP",2) == 0))↵|>||||||| return(MagickTrue);↵|>||||||| return(MagickFalse);↵|>|||||||}↵|>||||||| ↵|>|||||||/*↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% R e a d B M P I m a g e %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||%↵|>|||||||% ReadBMPImage() reads a Microsoft Windows bitmap image file, Version -% 2, 3 (for Windows or NT), or 4, and returns it. It allocates the memory -% necessary for the new Image structure and returns a pointer to the new -% image. -% -% The format of the ReadBMPImage method is: -% -% image=ReadBMPImage(image_info) -% -% A description of each parameter follows: -% -% o image_info: the image info. -% -% o exception: return any errors or warnings in this structure. -% -*/¶|>|||||||static Image *ReadBMPImage(const ImageInfo *image_info,ExceptionInfo *exception) -{↵|>||||||| BMPInfo - bmp_info;¶|>||||||| Image - *image;¶|>||||||| MagickBooleanType - status;¶|>||||||| MagickOffsetType - offset,↵|>||||||| profile_data,↵|>||||||| profile_size,↵|>||||||| start_position;¶|>||||||| MagickSizeType - blob_size;¶|>||||||| MemoryInfo - *pixel_info;¶|>||||||| Quantum - index;¶|>||||||| Quantum - *q;¶|>||||||| ssize_t - i,↵|>||||||| x;¶|>||||||| unsigned char - *p;¶|>||||||| size_t - bit,↵|>||||||| bytes_per_line,↵|>||||||| length;¶|>||||||| ssize_t - count,↵|>||||||| y;¶|>||||||| unsigned char - magick[12],↵|>||||||| *pixels;¶|>||||||| unsigned int - blue,↵|>||||||| green,↵|>||||||| offset_bits,↵|>||||||| red;¶|>||||||| /* - Open image file. - */↵|>||||||| assert(image_info != (const ImageInfo *) NULL); - assert(image_info->signature == MagickCoreSignature);↵|>||||||| if (IsEventLogging() != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", - image_info->filename);↵|>||||||| assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature);↵|>||||||| image=AcquireImage(image_info,exception);↵|>||||||| status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);↵|>||||||| if (status == MagickFalse) - { - image=DestroyImageList(image); - return((Image *) NULL); - }↵|>||||||| /* - Determine if this a BMP file. - */↵|>||||||| (void) memset(&bmp_info,0,sizeof(bmp_info));↵|>||||||| bmp_info.ba_offset=0;↵|>||||||| start_position=0;↵|>||||||| offset_bits=0;↵|>||||||| count=ReadBlob(image,2,magick);↵|>||||||| if (count != 2) - ThrowReaderException(CorruptImageError,"ImproperImageHeader");↵|>||||||| blob_size=GetBlobSize(image);↵|>||||||| do - {↵|>||||||| PixelInfo - quantum_bits;¶|>||||||| PixelPacket - shift;¶|>||||||| /* - Verify BMP identifier. - */↵|>||||||| start_position=TellBlob(image)-2;↵|>||||||| bmp_info.ba_offset=0;↵|>||||||| while (LocaleNCompare((char *) magick,"BA",2) == 0) - {↵|>||||||| bmp_info.file_size=ReadBlobLSBLong(image);↵|>||||||| bmp_info.ba_offset=ReadBlobLSBLong(image);↵|>||||||| bmp_info.offset_bits=ReadBlobLSBLong(image);↵|>||||||| count=ReadBlob(image,2,magick);↵|>||||||| if (count != 2) - break;↵|>||||||| }↵|>||||||| if (image->debug != MagickFalse) - (void) LogMagickEvent(CoderEvent,GetMagickModule()," Magick: %c%c", - magick[0],magick[1]);↵|>||||||| if ((count != 2) || ((LocaleNCompare((char *) magick,"BM",2) != 0) && - (LocaleNCompare((char *) magick,"CI",2) != 0)))↵|>||||||| ThrowReaderException(CorruptImageError,"ImproperImageHeader");↵|>||||||| bmp_info.file_size=ReadBlobLSBLong(image);↵|>||||||| (void) ReadBlobLSBLong(image);↵|>||||||| bmp_info.offset_bits=ReadBlobLSBLong(image);↵|>||||||| bmp_info.size=ReadBlobLSBLong(image);↵|>||||||| if (image->debug != MagickFalse)↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " BMP header size: %u",bmp_info.size);↵|>||||||| if (bmp_info.size > 124)↵|>||||||| ThrowReaderException(CorruptImageError,"ImproperImageHeader");↵|>||||||| profile_data=0;↵|>||||||| profile_size=0;↵|>||||||| if (bmp_info.size == 12)↵|>||||||| {↵|>||||||| /*↵|>||||||| OS/2 BMP image file.↵|>||||||| */↵|>||||||| (void) CopyMagickString(image->magick,"BMP2",MagickPathExtent);↵|>||||||| bmp_info.width=(ssize_t) ((short) ReadBlobLSBShort(image));↵|>||||||| bmp_info.height=(ssize_t) ((short) ReadBlobLSBShort(image));↵|>||||||| bmp_info.planes=ReadBlobLSBShort(image);↵|>||||||| bmp_info.bits_per_pixel=ReadBlobLSBShort(image);↵|>||||||| bmp_info.x_pixels=0;↵|>||||||| bmp_info.y_pixels=0;↵|>||||||| bmp_info.number_colors=0;↵|>||||||| bmp_info.compression=BI_RGB;↵|>||||||| bmp_info.image_size=0;↵|>||||||| bmp_info.alpha_mask=0;↵|>||||||| if (image->debug != MagickFalse)↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Format: OS/2 Bitmap");↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Geometry: %.20gx%.20g",(double) bmp_info.width,(double)↵|>||||||| bmp_info.height);↵|>||||||| }↵|>||||||| }↵|>||||||| else↵|>||||||| {↵|>||||||| /*↵|>||||||| Microsoft Windows BMP image file.↵|>||||||| */↵|>||||||| bmp_info.width=(ssize_t) ReadBlobLSBSignedLong(image);↵|>||||||| bmp_info.height=(ssize_t) ReadBlobLSBSignedLong(image);↵|>||||||| bmp_info.planes=ReadBlobLSBShort(image);↵|>||||||| bmp_info.bits_per_pixel=ReadBlobLSBShort(image);↵|>||||||| bmp_info.compression=ReadBlobLSBLong(image);↵|>||||||| if (bmp_info.size > 16)↵|>||||||| {↵|>||||||| bmp_info.image_size=ReadBlobLSBLong(image);↵|>||||||| bmp_info.x_pixels=ReadBlobLSBLong(image);↵|>||||||| bmp_info.y_pixels=ReadBlobLSBLong(image);↵|>||||||| bmp_info.number_colors=ReadBlobLSBLong(image);↵|>||||||| if ((MagickSizeType) bmp_info.number_colors > blob_size)↵|>||||||| ThrowReaderException(CorruptImageError,↵|>||||||| "InsufficientImageDataInFile");↵|>||||||| bmp_info.colors_important=ReadBlobLSBLong(image);↵|>||||||| }↵|>||||||| if (image->debug != MagickFalse)↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Format: MS Windows bitmap");↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Geometry: %.20gx%.20g",(double) bmp_info.width,(double)↵|>||||||| bmp_info.height);↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Bits per pixel: %.20g",(double) bmp_info.bits_per_pixel);↵|>||||||| switch (bmp_info.compression)↵|>||||||| {↵|>||||||| case BI_RGB:↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Compression: BI_RGB");↵|>||||||| break;↵|>||||||| }↵|>||||||| case BI_RLE4:↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Compression: BI_RLE4");↵|>||||||| break;↵|>||||||| }↵|>||||||| case BI_RLE8:↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Compression: BI_RLE8");↵|>||||||| break;↵|>||||||| }↵|>||||||| case BI_BITFIELDS:↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Compression: BI_BITFIELDS");↵|>||||||| break;↵|>||||||| }↵|>||||||| case BI_PNG:↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Compression: BI_PNG");↵|>||||||| break;↵|>||||||| }↵|>||||||| case BI_JPEG:↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Compression: BI_JPEG");↵|>||||||| break;↵|>||||||| }↵|>||||||| default:↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Compression: UNKNOWN (%u)",bmp_info.compression);↵|>||||||| }↵|>||||||| }↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Number of colors: %u",bmp_info.number_colors);↵|>||||||| }↵|>||||||| if ((bmp_info.size > 40) || (bmp_info.compression == BI_BITFIELDS))↵|>||||||| {↵|>||||||| bmp_info.red_mask=ReadBlobLSBLong(image);↵|>||||||| bmp_info.green_mask=ReadBlobLSBLong(image);↵|>||||||| bmp_info.blue_mask=ReadBlobLSBLong(image);↵|>||||||| }↵|>||||||| if (bmp_info.size > 40)↵|>||||||| {↵|>||||||| double↵|>||||||| gamma;↵|>|||||||↵|>||||||| /*↵|>||||||| Read color management information.↵|>||||||| */↵|>||||||| bmp_info.alpha_mask=ReadBlobLSBLong(image);↵|>||||||| bmp_info.colorspace=ReadBlobLSBSignedLong(image);↵|>||||||| /*↵|>||||||| Decode 2^30 fixed point formatted CIE primaries.↵|>||||||| */↵|>|||||||# define BMP_DENOM ((double) 0x40000000)↵|>||||||| bmp_info.red_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;↵|>||||||| bmp_info.red_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;↵|>||||||| bmp_info.red_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;↵|>||||||| bmp_info.green_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;↵|>||||||| bmp_info.green_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;↵|>||||||| bmp_info.green_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;↵|>||||||| bmp_info.blue_primary.x=(double) ReadBlobLSBLong(image)/BMP_DENOM;↵|>||||||| bmp_info.blue_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;↵|>||||||| bmp_info.blue_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;↵|>|||||||↵|>||||||| gamma=bmp_info.red_primary.x+bmp_info.red_primary.y+↵|>||||||| bmp_info.red_primary.z;↵|>||||||| gamma=PerceptibleReciprocal(gamma);↵|>||||||| bmp_info.red_primary.x*=gamma;↵|>||||||| bmp_info.red_primary.y*=gamma;↵|>||||||| image->chromaticity.red_primary.x=bmp_info.red_primary.x;↵|>||||||| image->chromaticity.red_primary.y=bmp_info.red_primary.y;↵|>|||||||↵|>||||||| gamma=bmp_info.green_primary.x+bmp_info.green_primary.y+↵|>||||||| bmp_info.green_primary.z;↵|>||||||| gamma=PerceptibleReciprocal(gamma);↵|>||||||| bmp_info.green_primary.x*=gamma;↵|>||||||| bmp_info.green_primary.y*=gamma;↵|>||||||| image->chromaticity.green_primary.x=bmp_info.green_primary.x;↵|>||||||| image->chromaticity.green_primary.y=bmp_info.green_primary.y;↵|>|||||||↵|>||||||| gamma=bmp_info.blue_primary.x+bmp_info.blue_primary.y+↵|>||||||| bmp_info.blue_primary.z;↵|>||||||| gamma=PerceptibleReciprocal(gamma);↵|>||||||| bmp_info.blue_primary.x*=gamma;↵|>||||||| bmp_info.blue_primary.y*=gamma;↵|>||||||| image->chromaticity.blue_primary.x=bmp_info.blue_primary.x;↵|>||||||| image->chromaticity.blue_primary.y=bmp_info.blue_primary.y;↵|>|||||||↵|>||||||| /*↵|>||||||| Decode 16^16 fixed point formatted gamma_scales.↵|>||||||| */↵|>||||||| bmp_info.gamma_scale.x=(double) ReadBlobLSBLong(image)/0x10000;↵|>||||||| bmp_info.gamma_scale.y=(double) ReadBlobLSBLong(image)/0x10000;↵|>||||||| bmp_info.gamma_scale.z=(double) ReadBlobLSBLong(image)/0x10000;↵|>||||||| /*↵|>||||||| Compute a single gamma from the BMP 3-channel gamma.↵|>||||||| */↵|>||||||| image->gamma=(bmp_info.gamma_scale.x+bmp_info.gamma_scale.y+↵|>||||||| bmp_info.gamma_scale.z)/3.0;↵|>||||||| }↵|>||||||| else↵|>||||||| (void) CopyMagickString(image->magick,"BMP3",MagickPathExtent);↵|>|||||||↵|>||||||| if (bmp_info.size > 108)↵|>||||||| {↵|>||||||| size_t↵|>||||||| intent;↵|>|||||||↵|>||||||| /*↵|>||||||| Read BMP Version 5 color management information.↵|>||||||| */↵|>||||||| intent=ReadBlobLSBLong(image);↵|>||||||| switch ((int) intent)↵|>||||||| {↵|>||||||| case LCS_GM_BUSINESS:↵|>||||||| {↵|>||||||| image->rendering_intent=SaturationIntent;↵|>||||||| break;↵|>||||||| }↵|>||||||| case LCS_GM_GRAPHICS:↵|>||||||| {↵|>||||||| image->rendering_intent=RelativeIntent;↵|>||||||| break;↵|>||||||| }↵|>||||||| case LCS_GM_IMAGES:↵|>||||||| {↵|>||||||| image->rendering_intent=PerceptualIntent;↵|>||||||| break;↵|>||||||| }↵|>||||||| case LCS_GM_ABS_COLORIMETRIC:↵|>||||||| {↵|>||||||| image->rendering_intent=AbsoluteIntent;↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| profile_data=(MagickOffsetType)ReadBlobLSBLong(image);↵|>||||||| profile_size=(MagickOffsetType)ReadBlobLSBLong(image);↵|>||||||| (void) ReadBlobLSBLong(image); /* Reserved byte */↵|>||||||| }↵|>||||||| }↵|>||||||| if ((MagickSizeType) bmp_info.file_size != blob_size)↵|>||||||| {↵|>||||||| const char↵|>||||||| *option;↵|>|||||||↵|>||||||| option=GetImageOption(image_info,"bmp:ignore-filesize");↵|>||||||| if (IsStringTrue(option) == MagickFalse)↵|>||||||| (void) ThrowMagickException(exception,GetMagickModule(),↵|>||||||| CorruptImageError,"LengthAndFilesizeDoNotMatch","`%s'",↵|>||||||| image->filename);↵|>||||||| }↵|>||||||| if (bmp_info.width <= 0)↵|>||||||| ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");↵|>||||||| if (bmp_info.height == 0)↵|>||||||| ThrowReaderException(CorruptImageError,"NegativeOrZeroImageSize");↵|>||||||| if (bmp_info.planes != 1)↵|>||||||| ThrowReaderException(CorruptImageError,"StaticPlanesValueNotEqualToOne");↵|>||||||| if ((bmp_info.bits_per_pixel != 1) && (bmp_info.bits_per_pixel != 4) &&↵|>||||||| (bmp_info.bits_per_pixel != 8) && (bmp_info.bits_per_pixel != 16) &&↵|>||||||| (bmp_info.bits_per_pixel != 24) && (bmp_info.bits_per_pixel != 32))↵|>||||||| ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");↵|>||||||| if (bmp_info.bits_per_pixel < 16 &&↵|>||||||| bmp_info.number_colors > (1U << bmp_info.bits_per_pixel))↵|>||||||| ThrowReaderException(CorruptImageError,"UnrecognizedNumberOfColors");↵|>||||||| if ((bmp_info.compression == BI_RLE8) && (bmp_info.bits_per_pixel != 8))↵|>||||||| ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");↵|>||||||| if ((bmp_info.compression == BI_RLE4) && (bmp_info.bits_per_pixel != 4))↵|>||||||| ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");↵|>||||||| if ((bmp_info.compression == BI_BITFIELDS) && (bmp_info.bits_per_pixel < 16))↵|>||||||| ThrowReaderException(CorruptImageError,"UnsupportedBitsPerPixel");↵|>||||||| switch (bmp_info.compression)↵|>||||||| {↵|>||||||| case BI_RGB:↵|>||||||| image->compression=NoCompression;↵|>||||||| break;↵|>||||||| case BI_RLE8:↵|>||||||| case BI_RLE4:↵|>||||||| image->compression=RLECompression;↵|>||||||| break;↵|>||||||| case BI_BITFIELDS:↵|>||||||| break;↵|>||||||| case BI_JPEG:↵|>||||||| ThrowReaderException(CoderError,"JPEGCompressNotSupported");↵|>||||||| case BI_PNG:↵|>||||||| ThrowReaderException(CoderError,"PNGCompressNotSupported");↵|>||||||| default:↵|>||||||| ThrowReaderException(CorruptImageError,"UnrecognizedImageCompression");↵|>||||||| }↵|>||||||| image->columns=(size_t) MagickAbsoluteValue(bmp_info.width);↵|>||||||| image->rows=(size_t) MagickAbsoluteValue(bmp_info.height);↵|>||||||| image->depth=bmp_info.bits_per_pixel <= 8 ? bmp_info.bits_per_pixel : 8;↵|>||||||| image->alpha_trait=((bmp_info.alpha_mask != 0) &&↵|>||||||| (bmp_info.compression == BI_BITFIELDS)) ? BlendPixelTrait :↵|>||||||| UndefinedPixelTrait;↵|>||||||| if (bmp_info.bits_per_pixel < 16)↵|>||||||| {↵|>||||||| size_t↵|>||||||| one;↵|>|||||||↵|>||||||| image->storage_class=PseudoClass;↵|>||||||| image->colors=bmp_info.number_colors;↵|>||||||| one=1;↵|>||||||| if (image->colors == 0)↵|>||||||| image->colors=one << bmp_info.bits_per_pixel;↵|>||||||| }↵|>||||||| image->resolution.x=(double) bmp_info.x_pixels/100.0;↵|>||||||| image->resolution.y=(double) bmp_info.y_pixels/100.0;↵|>||||||| image->units=PixelsPerCentimeterResolution;↵|>||||||| if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))↵|>||||||| if (image->scene >= (image_info->scene+image_info->number_scenes-1))↵|>||||||| break;↵|>||||||| status=SetImageExtent(image,image->columns,image->rows,exception);↵|>||||||| if (status == MagickFalse)↵|>||||||| return(DestroyImageList(image));↵|>||||||| if (image->storage_class == PseudoClass)↵|>||||||| {↵|>||||||| unsigned char↵|>||||||| *bmp_colormap;↵|>|||||||↵|>||||||| size_t↵|>||||||| packet_size;↵|>|||||||↵|>||||||| /*↵|>||||||| Read BMP raster colormap.↵|>||||||| */↵|>||||||| if (image->debug != MagickFalse)↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Reading colormap of %.20g colors",(double) image->colors);↵|>||||||| if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)↵|>||||||| ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");↵|>||||||| bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t)↵|>||||||| image->colors,4*sizeof(*bmp_colormap));↵|>||||||| if (bmp_colormap == (unsigned char *) NULL)↵|>||||||| ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");↵|>||||||| if ((bmp_info.size == 12) || (bmp_info.size == 64))↵|>||||||| packet_size=3;↵|>||||||| else↵|>||||||| packet_size=4;↵|>||||||| offset=SeekBlob(image,start_position+14+bmp_info.size,SEEK_SET);↵|>||||||| if (offset < 0)↵|>||||||| {↵|>||||||| bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);↵|>||||||| ThrowReaderException(CorruptImageError,"ImproperImageHeader");↵|>||||||| }↵|>||||||| count=ReadBlob(image,packet_size*image->colors,bmp_colormap);↵|>||||||| if (count != (ssize_t) (packet_size*image->colors))↵|>||||||| {↵|>||||||| bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);↵|>||||||| ThrowReaderException(CorruptImageError,↵|>||||||| "InsufficientImageDataInFile");↵|>||||||| }↵|>||||||| p=bmp_colormap;↵|>||||||| for (i=0; i < (ssize_t) image->colors; i++)↵|>||||||| {↵|>||||||| image->colormap[i].blue=(MagickRealType) ScaleCharToQuantum(*p++);↵|>||||||| image->colormap[i].green=(MagickRealType) ScaleCharToQuantum(*p++);↵|>||||||| image->colormap[i].red=(MagickRealType) ScaleCharToQuantum(*p++);↵|>||||||| if (packet_size == 4)↵|>||||||| p++;↵|>||||||| }↵|>||||||| bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);↵|>||||||| }↵|>||||||| /*↵|>||||||| Read image data.↵|>||||||| */↵|>||||||| if (bmp_info.offset_bits == offset_bits)↵|>||||||| ThrowReaderException(CorruptImageError,"ImproperImageHeader");↵|>||||||| offset_bits=bmp_info.offset_bits;↵|>||||||| offset=SeekBlob(image,start_position+bmp_info.offset_bits,SEEK_SET);↵|>||||||| if (offset < 0)↵|>||||||| ThrowReaderException(CorruptImageError,"ImproperImageHeader");↵|>||||||| if (bmp_info.compression == BI_RLE4)↵|>||||||| bmp_info.bits_per_pixel<<=1;↵|>||||||| bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);↵|>||||||| length=(size_t) bytes_per_line*image->rows;↵|>||||||| if ((MagickSizeType) (length/256) > blob_size)↵|>||||||| ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");↵|>||||||| if ((bmp_info.compression == BI_RGB) ||↵|>||||||| (bmp_info.compression == BI_BITFIELDS))↵|>||||||| {↵|>||||||| pixel_info=AcquireVirtualMemory(image->rows,↵|>||||||| MagickMax(bytes_per_line,image->columns+256UL)*sizeof(*pixels));↵|>||||||| if (pixel_info == (MemoryInfo *) NULL)↵|>||||||| ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");↵|>||||||| pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);↵|>||||||| if (image->debug != MagickFalse)↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Reading pixels (%.20g bytes)",(double) length);↵|>||||||| count=ReadBlob(image,length,pixels);↵|>||||||| if (count != (ssize_t) length)↵|>||||||| {↵|>||||||| pixel_info=RelinquishVirtualMemory(pixel_info);↵|>||||||| ThrowReaderException(CorruptImageError,↵|>||||||| "InsufficientImageDataInFile");↵|>||||||| }↵|>||||||| }↵|>||||||| else↵|>||||||| {↵|>||||||| /*↵|>||||||| Convert run-length encoded raster pixels.↵|>||||||| */↵|>||||||| pixel_info=AcquireVirtualMemory(image->rows,↵|>||||||| MagickMax(bytes_per_line,image->columns+256UL)*sizeof(*pixels));↵|>||||||| if (pixel_info == (MemoryInfo *) NULL)↵|>||||||| ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");↵|>||||||| pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);↵|>||||||| status=DecodeImage(image,bmp_info.compression,pixels,↵|>||||||| image->columns*image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| {↵|>||||||| pixel_info=RelinquishVirtualMemory(pixel_info);↵|>||||||| ThrowReaderException(CorruptImageError,↵|>||||||| "UnableToRunlengthDecodeImage");↵|>||||||| }↵|>||||||| }↵|>||||||| /*↵|>||||||| Convert BMP raster image to pixel packets.↵|>||||||| */↵|>||||||| if (bmp_info.compression == BI_RGB)↵|>||||||| {↵|>||||||| /*↵|>||||||| We should ignore the alpha value in BMP3 files but there have been↵|>||||||| reports about 32 bit files with alpha. We do a quick check to see if↵|>||||||| the alpha channel contains a value that is not zero (default value).↵|>||||||| If we find a non zero value we asume the program that wrote the file↵|>||||||| wants to use the alpha channel.↵|>||||||| */↵|>||||||| if ((image->alpha_trait == UndefinedPixelTrait) &&↵|>||||||| (bmp_info.size == 40) && (bmp_info.bits_per_pixel == 32))↵|>||||||| {↵|>||||||| bytes_per_line=4*(image->columns);↵|>||||||| for (y=(ssize_t) image->rows-1; y >= 0; y--)↵|>||||||| {↵|>||||||| p=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| for (x=0; x < (ssize_t) image->columns; x++)↵|>||||||| {↵|>||||||| if (*(p+3) != 0)↵|>||||||| {↵|>||||||| image->alpha_trait=BlendPixelTrait;↵|>||||||| y=-1;↵|>||||||| break;↵|>||||||| }↵|>||||||| p+=4;↵|>||||||| }↵|>||||||| }↵|>||||||| }↵|>||||||| bmp_info.alpha_mask=image->alpha_trait != UndefinedPixelTrait ?↵|>||||||| 0xff000000U : 0U;↵|>||||||| bmp_info.red_mask=0x00ff0000U;↵|>||||||| bmp_info.green_mask=0x0000ff00U;↵|>||||||| bmp_info.blue_mask=0x000000ffU;↵|>||||||| if (bmp_info.bits_per_pixel == 16)↵|>||||||| {↵|>||||||| /*↵|>||||||| RGB555.↵|>||||||| */↵|>||||||| bmp_info.red_mask=0x00007c00U;↵|>||||||| bmp_info.green_mask=0x000003e0U;↵|>||||||| bmp_info.blue_mask=0x0000001fU;↵|>||||||| }↵|>||||||| }↵|>||||||| (void) memset(&shift,0,sizeof(shift));↵|>||||||| (void) memset(&quantum_bits,0,sizeof(quantum_bits));↵|>||||||| if ((bmp_info.bits_per_pixel == 16) || (bmp_info.bits_per_pixel == 32))↵|>||||||| {↵|>||||||| unsigned int↵|>||||||| sample;↵|>|||||||↵|>||||||| /*↵|>||||||| Get shift and quantum bits info from bitfield masks.↵|>||||||| */↵|>||||||| if (bmp_info.red_mask != 0)↵|>||||||| while (((bmp_info.red_mask << shift.red) & 0x80000000UL) == 0)↵|>||||||| {↵|>||||||| shift.red++;↵|>||||||| if (shift.red >= 32U)↵|>||||||| break;↵|>||||||| }↵|>||||||| if (bmp_info.green_mask != 0)↵|>||||||| while (((bmp_info.green_mask << shift.green) & 0x80000000UL) == 0)↵|>||||||| {↵|>||||||| shift.green++;↵|>||||||| if (shift.green >= 32U)↵|>||||||| break;↵|>||||||| }↵|>||||||| if (bmp_info.blue_mask != 0)↵|>||||||| while (((bmp_info.blue_mask << shift.blue) & 0x80000000UL) == 0)↵|>||||||| {↵|>||||||| shift.blue++;↵|>||||||| if (shift.blue >= 32U)↵|>||||||| break;↵|>||||||| }↵|>||||||| if (bmp_info.alpha_mask != 0)↵|>||||||| while (((bmp_info.alpha_mask << shift.alpha) & 0x80000000UL) == 0)↵|>||||||| {↵|>||||||| shift.alpha++;↵|>||||||| if (shift.alpha >= 32U)↵|>||||||| break;↵|>||||||| }↵|>||||||| sample=shift.red;↵|>||||||| while (((bmp_info.red_mask << sample) & 0x80000000UL) != 0)↵|>||||||| {↵|>||||||| sample++;↵|>||||||| if (sample >= 32U)↵|>||||||| break;↵|>||||||| }↵|>||||||| quantum_bits.red=(MagickRealType) (sample-shift.red);↵|>||||||| sample=shift.green;↵|>||||||| while (((bmp_info.green_mask << sample) & 0x80000000UL) != 0)↵|>||||||| {↵|>||||||| sample++;↵|>||||||| if (sample >= 32U)↵|>||||||| break;↵|>||||||| }↵|>||||||| quantum_bits.green=(MagickRealType) (sample-shift.green);↵|>||||||| sample=shift.blue;↵|>||||||| while (((bmp_info.blue_mask << sample) & 0x80000000UL) != 0)↵|>||||||| {↵|>||||||| sample++;↵|>||||||| if (sample >= 32U)↵|>||||||| break;↵|>||||||| }↵|>||||||| quantum_bits.blue=(MagickRealType) (sample-shift.blue);↵|>||||||| sample=shift.alpha;↵|>||||||| while (((bmp_info.alpha_mask << sample) & 0x80000000UL) != 0)↵|>||||||| {↵|>||||||| sample++;↵|>||||||| if (sample >= 32U)↵|>||||||| break;↵|>||||||| }↵|>||||||| quantum_bits.alpha=(MagickRealType) (sample-shift.alpha);↵|>||||||| }↵|>||||||| switch (bmp_info.bits_per_pixel)↵|>||||||| {↵|>||||||| case 1:↵|>||||||| {↵|>||||||| /*↵|>||||||| Convert bitmap scanline.↵|>||||||| */↵|>||||||| for (y=(ssize_t) image->rows-1; y >= 0; y--)↵|>||||||| {↵|>||||||| p=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (q == (Quantum *) NULL)↵|>||||||| break;↵|>||||||| for (x=0; x < ((ssize_t) image->columns-7); x+=8)↵|>||||||| {↵|>||||||| for (bit=0; bit < 8; bit++)↵|>||||||| {↵|>||||||| index=(Quantum) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00);↵|>||||||| SetPixelIndex(image,index,q);↵|>||||||| q+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| p++;↵|>||||||| }↵|>||||||| if ((image->columns % 8) != 0)↵|>||||||| {↵|>||||||| for (bit=0; bit < (image->columns % 8); bit++)↵|>||||||| {↵|>||||||| index=(Quantum) (((*p) & (0x80 >> bit)) != 0 ? 0x01 : 0x00);↵|>||||||| SetPixelIndex(image,index,q);↵|>||||||| q+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| p++;↵|>||||||| }↵|>||||||| if (SyncAuthenticPixels(image,exception) == MagickFalse)↵|>||||||| break;↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)↵|>||||||| (image->rows-y),image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| (void) SyncImage(image,exception);↵|>||||||| break;↵|>||||||| }↵|>||||||| case 4:↵|>||||||| {↵|>||||||| /*↵|>||||||| Convert PseudoColor scanline.↵|>||||||| */↵|>||||||| for (y=(ssize_t) image->rows-1; y >= 0; y--)↵|>||||||| {↵|>||||||| p=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (q == (Quantum *) NULL)↵|>||||||| break;↵|>||||||| for (x=0; x < ((ssize_t) image->columns-1); x+=2)↵|>||||||| {↵|>||||||| ValidateColormapValue(image,(ssize_t) ((*p >> 4) & 0x0f),&index,↵|>||||||| exception);↵|>||||||| SetPixelIndex(image,index,q);↵|>||||||| q+=GetPixelChannels(image);↵|>||||||| ValidateColormapValue(image,(ssize_t) (*p & 0x0f),&index,exception);↵|>||||||| SetPixelIndex(image,index,q);↵|>||||||| q+=GetPixelChannels(image);↵|>||||||| p++;↵|>||||||| }↵|>||||||| if ((image->columns % 2) != 0)↵|>||||||| {↵|>||||||| ValidateColormapValue(image,(ssize_t) ((*p >> 4) & 0xf),&index,↵|>||||||| exception);↵|>||||||| SetPixelIndex(image,index,q);↵|>||||||| q+=GetPixelChannels(image);↵|>||||||| p++;↵|>||||||| x++;↵|>||||||| }↵|>||||||| if (x < (ssize_t) image->columns)↵|>||||||| break;↵|>||||||| if (SyncAuthenticPixels(image,exception) == MagickFalse)↵|>||||||| break;↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)↵|>||||||| (image->rows-y),image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| (void) SyncImage(image,exception);↵|>||||||| break;↵|>||||||| }↵|>||||||| case 8:↵|>||||||| {↵|>||||||| /*↵|>||||||| Convert PseudoColor scanline.↵|>||||||| */↵|>||||||| if ((bmp_info.compression == BI_RLE8) ||↵|>||||||| (bmp_info.compression == BI_RLE4))↵|>||||||| bytes_per_line=image->columns;↵|>||||||| for (y=(ssize_t) image->rows-1; y >= 0; y--)↵|>||||||| {↵|>||||||| p=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (q == (Quantum *) NULL)↵|>||||||| break;↵|>||||||| for (x=(ssize_t) image->columns; x != 0; --x)↵|>||||||| {↵|>||||||| ValidateColormapValue(image,(ssize_t) *p++,&index,exception);↵|>||||||| SetPixelIndex(image,index,q);↵|>||||||| q+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| if (SyncAuthenticPixels(image,exception) == MagickFalse)↵|>||||||| break;↵|>||||||| offset=(MagickOffsetType) (image->rows-y-1);↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)↵|>||||||| (image->rows-y),image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| (void) SyncImage(image,exception);↵|>||||||| break;↵|>||||||| }↵|>||||||| case 16:↵|>||||||| {↵|>||||||| unsigned int↵|>||||||| alpha,↵|>||||||| pixel;↵|>|||||||↵|>||||||| /*↵|>||||||| Convert bitfield encoded 16-bit PseudoColor scanline.↵|>||||||| */↵|>||||||| if ((bmp_info.compression != BI_RGB) &&↵|>||||||| (bmp_info.compression != BI_BITFIELDS))↵|>||||||| {↵|>||||||| pixel_info=RelinquishVirtualMemory(pixel_info);↵|>||||||| ThrowReaderException(CorruptImageError,↵|>||||||| "UnrecognizedImageCompression");↵|>||||||| }↵|>||||||| bytes_per_line=2*(image->columns+image->columns % 2);↵|>||||||| image->storage_class=DirectClass;↵|>||||||| for (y=(ssize_t) image->rows-1; y >= 0; y--)↵|>||||||| {↵|>||||||| p=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (q == (Quantum *) NULL)↵|>||||||| break;↵|>||||||| for (x=0; x < (ssize_t) image->columns; x++)↵|>||||||| {↵|>||||||| pixel=(unsigned int) (*p++);↵|>||||||| pixel|=(*p++) << 8;↵|>||||||| red=((pixel & bmp_info.red_mask) << shift.red) >> 16;↵|>||||||| if (quantum_bits.red == 5)↵|>||||||| red|=((red & 0xe000) >> 5);↵|>||||||| if (quantum_bits.red <= 8)↵|>||||||| red|=((red & 0xff00) >> 8);↵|>||||||| green=((pixel & bmp_info.green_mask) << shift.green) >> 16;↵|>||||||| if (quantum_bits.green == 5)↵|>||||||| green|=((green & 0xe000) >> 5);↵|>||||||| if (quantum_bits.green == 6)↵|>||||||| green|=((green & 0xc000) >> 6);↵|>||||||| if (quantum_bits.green <= 8)↵|>||||||| green|=((green & 0xff00) >> 8);↵|>||||||| blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16;↵|>||||||| if (quantum_bits.blue == 5)↵|>||||||| blue|=((blue & 0xe000) >> 5);↵|>||||||| if (quantum_bits.blue <= 8)↵|>||||||| blue|=((blue & 0xff00) >> 8);↵|>||||||| SetPixelRed(image,ScaleShortToQuantum((unsigned short) red),q);↵|>||||||| SetPixelGreen(image,ScaleShortToQuantum((unsigned short) green),q);↵|>||||||| SetPixelBlue(image,ScaleShortToQuantum((unsigned short) blue),q);↵|>||||||| SetPixelAlpha(image,OpaqueAlpha,q);↵|>||||||| if (image->alpha_trait != UndefinedPixelTrait)↵|>||||||| {↵|>||||||| alpha=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16;↵|>||||||| if (quantum_bits.alpha <= 8)↵|>||||||| alpha|=((alpha & 0xff00) >> 8);↵|>||||||| SetPixelAlpha(image,ScaleShortToQuantum(↵|>||||||| (unsigned short) alpha),q);↵|>||||||| }↵|>||||||| q+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| if (SyncAuthenticPixels(image,exception) == MagickFalse)↵|>||||||| break;↵|>||||||| offset=(MagickOffsetType) (image->rows-y-1);↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)↵|>||||||| (image->rows-y),image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| break;↵|>||||||| }↵|>||||||| case 24:↵|>||||||| {↵|>||||||| /*↵|>||||||| Convert DirectColor scanline.↵|>||||||| */↵|>||||||| bytes_per_line=4*((image->columns*24+31)/32);↵|>||||||| for (y=(ssize_t) image->rows-1; y >= 0; y--)↵|>||||||| {↵|>||||||| p=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (q == (Quantum *) NULL)↵|>||||||| break;↵|>||||||| for (x=0; x < (ssize_t) image->columns; x++)↵|>||||||| {↵|>||||||| SetPixelBlue(image,ScaleCharToQuantum(*p++),q);↵|>||||||| SetPixelGreen(image,ScaleCharToQuantum(*p++),q);↵|>||||||| SetPixelRed(image,ScaleCharToQuantum(*p++),q);↵|>||||||| SetPixelAlpha(image,OpaqueAlpha,q);↵|>||||||| q+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| if (SyncAuthenticPixels(image,exception) == MagickFalse)↵|>||||||| break;↵|>||||||| offset=(MagickOffsetType) (image->rows-y-1);↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)↵|>||||||| (image->rows-y),image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| break;↵|>||||||| }↵|>||||||| case 32:↵|>||||||| {↵|>||||||| /*↵|>||||||| Convert bitfield encoded DirectColor scanline.↵|>||||||| */↵|>||||||| if ((bmp_info.compression != BI_RGB) &&↵|>||||||| (bmp_info.compression != BI_BITFIELDS))↵|>||||||| {↵|>||||||| pixel_info=RelinquishVirtualMemory(pixel_info);↵|>||||||| ThrowReaderException(CorruptImageError,↵|>||||||| "UnrecognizedImageCompression");↵|>||||||| }↵|>||||||| bytes_per_line=4*(image->columns);↵|>||||||| for (y=(ssize_t) image->rows-1; y >= 0; y--)↵|>||||||| {↵|>||||||| unsigned int↵|>||||||| alpha,↵|>||||||| pixel;↵|>|||||||↵|>||||||| p=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (q == (Quantum *) NULL)↵|>||||||| break;↵|>||||||| for (x=0; x < (ssize_t) image->columns; x++)↵|>||||||| {↵|>||||||| pixel=(unsigned int) (*p++);↵|>||||||| pixel|=((unsigned int) *p++ << 8);↵|>||||||| pixel|=((unsigned int) *p++ << 16);↵|>||||||| pixel|=((unsigned int) *p++ << 24);↵|>||||||| red=((pixel & bmp_info.red_mask) << shift.red) >> 16;↵|>||||||| if (quantum_bits.red == 8)↵|>||||||| red|=(red >> 8);↵|>||||||| green=((pixel & bmp_info.green_mask) << shift.green) >> 16;↵|>||||||| if (quantum_bits.green == 8)↵|>||||||| green|=(green >> 8);↵|>||||||| blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16;↵|>||||||| if (quantum_bits.blue == 8)↵|>||||||| blue|=(blue >> 8);↵|>||||||| SetPixelRed(image,ScaleShortToQuantum((unsigned short) red),q);↵|>||||||| SetPixelGreen(image,ScaleShortToQuantum((unsigned short) green),q);↵|>||||||| SetPixelBlue(image,ScaleShortToQuantum((unsigned short) blue),q);↵|>||||||| SetPixelAlpha(image,OpaqueAlpha,q);↵|>||||||| if (image->alpha_trait != UndefinedPixelTrait)↵|>||||||| {↵|>||||||| alpha=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16;↵|>||||||| if (quantum_bits.alpha == 8)↵|>||||||| alpha|=(alpha >> 8);↵|>||||||| SetPixelAlpha(image,ScaleShortToQuantum(↵|>||||||| (unsigned short) alpha),q);↵|>||||||| }↵|>||||||| q+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| if (SyncAuthenticPixels(image,exception) == MagickFalse)↵|>||||||| break;↵|>||||||| offset=(MagickOffsetType) (image->rows-y-1);↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)↵|>||||||| (image->rows-y),image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| break;↵|>||||||| }↵|>||||||| default:↵|>||||||| {↵|>||||||| pixel_info=RelinquishVirtualMemory(pixel_info);↵|>||||||| ThrowReaderException(CorruptImageError,"ImproperImageHeader");↵|>||||||| }↵|>||||||| }↵|>||||||| pixel_info=RelinquishVirtualMemory(pixel_info);↵|>||||||| if (y > 0)↵|>||||||| break;↵|>||||||| if (EOFBlob(image) != MagickFalse)↵|>||||||| {↵|>||||||| ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",↵|>||||||| image->filename);↵|>||||||| break;↵|>||||||| }↵|>||||||| if (bmp_info.height < 0)↵|>||||||| {↵|>||||||| Image↵|>||||||| *flipped_image;↵|>|||||||↵|>||||||| /*↵|>||||||| Correct image orientation.↵|>||||||| */↵|>||||||| flipped_image=FlipImage(image,exception);↵|>||||||| if (flipped_image != (Image *) NULL)↵|>||||||| {↵|>||||||| DuplicateBlob(flipped_image,image);↵|>||||||| ReplaceImageInList(&image, flipped_image);↵|>||||||| image=flipped_image;↵|>||||||| }↵|>||||||| }↵|>||||||| /*↵|>||||||| Read embeded ICC profile↵|>||||||| */↵|>||||||| if ((bmp_info.colorspace == 0x4D424544L) && (profile_data > 0) &&↵|>||||||| (profile_size > 0))↵|>||||||| {↵|>||||||| StringInfo↵|>||||||| *profile;↵|>|||||||↵|>||||||| unsigned char↵|>||||||| *datum;↵|>|||||||↵|>||||||| offset=start_position+14+profile_data;↵|>||||||| if ((offset < TellBlob(image)) ||↵|>||||||| (SeekBlob(image,offset,SEEK_SET) != offset) ||↵|>||||||| (blob_size < (MagickSizeType) (offset+profile_size)))↵|>||||||| ThrowReaderException(CorruptImageError,"ImproperImageHeader");↵|>||||||| profile=AcquireStringInfo((size_t) profile_size);↵|>||||||| if (profile == (StringInfo *) NULL)↵|>||||||| ThrowReaderException(CorruptImageError,"MemoryAllocationFailed");↵|>||||||| datum=GetStringInfoDatum(profile);↵|>||||||| if (ReadBlob(image,(size_t) profile_size,datum) == (ssize_t) profile_size)↵|>||||||| {↵|>||||||| MagickOffsetType↵|>||||||| profile_size_orig;↵|>|||||||↵|>||||||| /*↵|>||||||| Trimming padded bytes.↵|>||||||| */↵|>||||||| profile_size_orig=(MagickOffsetType) datum[0] << 24;↵|>||||||| profile_size_orig|=(MagickOffsetType) datum[1] << 16;↵|>||||||| profile_size_orig|=(MagickOffsetType) datum[2] << 8;↵|>||||||| profile_size_orig|=(MagickOffsetType) datum[3];↵|>||||||| if (profile_size_orig < profile_size)↵|>||||||| SetStringInfoLength(profile,(size_t) profile_size_orig);↵|>||||||| if (image->debug != MagickFalse)↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| "Profile: ICC, %u bytes",(unsigned int) profile_size_orig);↵|>||||||| (void) SetImageProfile(image,"icc",profile,exception);↵|>||||||| }↵|>||||||| profile=DestroyStringInfo(profile);↵|>||||||| }↵|>||||||| /*↵|>||||||| Proceed to next image.↵|>||||||| */↵|>||||||| if (image_info->number_scenes != 0)↵|>||||||| if (image->scene >= (image_info->scene+image_info->number_scenes-1))↵|>||||||| break;↵|>||||||| offset=(MagickOffsetType) bmp_info.ba_offset;↵|>||||||| if (offset != 0)↵|>||||||| if ((offset < TellBlob(image)) ||↵|>||||||| (SeekBlob(image,offset,SEEK_SET) != offset))↵|>||||||| ThrowReaderException(CorruptImageError,"ImproperImageHeader");↵|>||||||| *magick='\0';↵|>||||||| count=ReadBlob(image,2,magick);↵|>||||||| if ((count == 2) && (IsBMP(magick,2) != MagickFalse))↵|>||||||| {↵|>||||||| /*↵|>||||||| Acquire next image structure.↵|>||||||| */↵|>||||||| AcquireNextImage(image_info,image,exception);↵|>||||||| if (GetNextImageInList(image) == (Image *) NULL)↵|>||||||| {↵|>||||||| status=MagickFalse;↵|>||||||| break;↵|>||||||| }↵|>||||||| image=SyncNextImageInList(image);↵|>||||||| status=SetImageProgress(image,LoadImagesTag,TellBlob(image),blob_size);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| } while (IsBMP(magick,2) != MagickFalse);↵|>||||||| (void) CloseBlob(image);↵|>||||||| if (status == MagickFalse)↵|>||||||| return(DestroyImageList(image));↵|>||||||| return(GetFirstImageInList(image));↵|>|||||||}↵|>||||||| ↵|>|||||||/*↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% R e g i s t e r B M P I m a g e %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||%↵|>|||||||% RegisterBMPImage() adds attributes for the BMP image format to↵|>|||||||% the list of supported formats. The attributes include the image format↵|>|||||||% tag, a method to read and/or write the format, whether the format↵|>|||||||% supports the saving of more than one frame to the same file or blob,↵|>|||||||% whether the format supports native in-memory I/O, and a brief↵|>|||||||% description of the format.↵|>|||||||%↵|>|||||||% The format of the RegisterBMPImage method is:↵|>|||||||%↵|>|||||||% size_t RegisterBMPImage(void)↵|>|||||||%↵|>|||||||*/↵|>|||||||ModuleExport size_t RegisterBMPImage(void)↵|>|||||||{↵|>||||||| MagickInfo↵|>||||||| *entry;↵|>|||||||↵|>||||||| entry=AcquireMagickInfo("BMP","BMP","Microsoft Windows bitmap image");↵|>||||||| entry->decoder=(DecodeImageHandler *) ReadBMPImage;↵|>||||||| entry->encoder=(EncodeImageHandler *) WriteBMPImage;↵|>||||||| entry->magick=(IsImageFormatHandler *) IsBMP;↵|>||||||| entry->flags^=CoderAdjoinFlag;↵|>||||||| entry->flags|=CoderDecoderSeekableStreamFlag;↵|>||||||| entry->mime_type=ConstantString("image/bmp");↵|>||||||| (void) RegisterMagickInfo(entry);↵|>||||||| entry=AcquireMagickInfo("BMP","BMP2","Microsoft Windows bitmap image (V2)");↵|>||||||| entry->decoder=(DecodeImageHandler *) ReadBMPImage;↵|>||||||| entry->encoder=(EncodeImageHandler *) WriteBMPImage;↵|>||||||| entry->magick=(IsImageFormatHandler *) IsBMP;↵|>||||||| entry->flags^=CoderAdjoinFlag;↵|>||||||| entry->flags|=CoderDecoderSeekableStreamFlag;↵|>||||||| entry->mime_type=ConstantString("image/bmp");↵|>||||||| (void) RegisterMagickInfo(entry);↵|>||||||| entry=AcquireMagickInfo("BMP","BMP3","Microsoft Windows bitmap image (V3)");↵|>||||||| entry->decoder=(DecodeImageHandler *) ReadBMPImage;↵|>||||||| entry->encoder=(EncodeImageHandler *) WriteBMPImage;↵|>||||||| entry->magick=(IsImageFormatHandler *) IsBMP;↵|>||||||| entry->flags^=CoderAdjoinFlag;↵|>||||||| entry->flags|=CoderDecoderSeekableStreamFlag;↵|>||||||| entry->mime_type=ConstantString("image/bmp");↵|>||||||| (void) RegisterMagickInfo(entry);↵|>||||||| return(MagickImageCoderSignature);↵|>|||||||}↵|>||||||| ↵|>|||||||/*↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% U n r e g i s t e r B M P I m a g e %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||%↵|>|||||||% UnregisterBMPImage() removes format registrations made by the↵|>|||||||% BMP module from the list of supported formats.↵|>|||||||%↵|>|||||||% The format of the UnregisterBMPImage method is:↵|>|||||||%↵|>|||||||% UnregisterBMPImage(void)↵|>|||||||%↵|>|||||||*/↵|>|||||||ModuleExport void UnregisterBMPImage(void)↵|>|||||||{↵|>||||||| (void) UnregisterMagickInfo("BMP");↵|>||||||| (void) UnregisterMagickInfo("BMP2");↵|>||||||| (void) UnregisterMagickInfo("BMP3");↵|>|||||||}↵|>||||||| ↵|>|||||||/*↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% W r i t e B M P I m a g e %↵|>|||||||% %↵|>|||||||% %↵|>|||||||% %↵|>|||||||%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%↵|>|||||||%↵|>|||||||% WriteBMPImage() writes an image in Microsoft Windows bitmap encoded↵|>|||||||% image format, version 3 for Windows or (if the image has a matte channel)↵|>|||||||% version 4.↵|>|||||||%↵|>|||||||% The format of the WriteBMPImage method is:↵|>|||||||%↵|>|||||||% MagickBooleanType WriteBMPImage(const ImageInfo *image_info,↵|>|||||||% Image *image,ExceptionInfo *exception)↵|>|||||||%↵|>|||||||% A description of each parameter follows.↵|>|||||||%↵|>|||||||% o image_info: the image info.↵|>|||||||%↵|>|||||||% o image: The image.↵|>|||||||%↵|>|||||||% o exception: return any errors or warnings in this structure.↵|>|||||||%↵|>|||||||*/↵|>|||||||static MagickBooleanType WriteBMPImage(const ImageInfo *image_info,Image *image,↵|>||||||| ExceptionInfo *exception)↵|>|||||||{↵|>||||||| BMPInfo↵|>||||||| bmp_info;↵|>|||||||↵|>||||||| BMPSubtype↵|>||||||| bmp_subtype;↵|>|||||||↵|>||||||| const char↵|>||||||| *option;↵|>|||||||↵|>||||||| const StringInfo↵|>||||||| *profile;↵|>|||||||↵|>||||||| MagickBooleanType↵|>||||||| have_color_info,↵|>||||||| status;↵|>|||||||↵|>||||||| MagickOffsetType↵|>||||||| scene;↵|>|||||||↵|>||||||| MemoryInfo↵|>||||||| *pixel_info;↵|>|||||||↵|>||||||| const Quantum↵|>||||||| *p;↵|>|||||||↵|>||||||| ssize_t↵|>||||||| i,↵|>||||||| x;↵|>|||||||↵|>||||||| unsigned char↵|>||||||| *q;↵|>|||||||↵|>||||||| size_t↵|>||||||| bytes_per_line,↵|>||||||| imageListLength,↵|>||||||| type;↵|>|||||||↵|>||||||| ssize_t↵|>||||||| y;↵|>|||||||↵|>||||||| unsigned char↵|>||||||| *bmp_data,↵|>||||||| *pixels;↵|>|||||||↵|>||||||| MagickOffsetType↵|>||||||| profile_data,↵|>||||||| profile_size,↵|>||||||| profile_size_pad;↵|>|||||||↵|>||||||| /*↵|>||||||| Open output image file.↵|>||||||| */↵|>||||||| assert(image_info != (const ImageInfo *) NULL);↵|>||||||| assert(image_info->signature == MagickCoreSignature);↵|>||||||| assert(image != (Image *) NULL);↵|>||||||| assert(image->signature == MagickCoreSignature);↵|>||||||| assert(exception != (ExceptionInfo *) NULL);↵|>||||||| assert(exception->signature == MagickCoreSignature);↵|>||||||| if (IsEventLogging() != MagickFalse)↵|>||||||| (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);↵|>||||||| status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);↵|>||||||| if (status == MagickFalse)↵|>||||||| return(status);↵|>||||||| if (((image->columns << 3) != (size_t) ((int) (image->columns << 3))) ||↵|>||||||| ((image->rows << 3) != (size_t) ((int) (image->rows << 3))))↵|>||||||| ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");↵|>||||||| type=4;↵|>||||||| if (LocaleCompare(image_info->magick,"BMP2") == 0)↵|>||||||| type=2;↵|>||||||| else↵|>||||||| if (LocaleCompare(image_info->magick,"BMP3") == 0)↵|>||||||| type=3;↵|>||||||| option=GetImageOption(image_info,"bmp:format");↵|>||||||| if (option != (char *) NULL)↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Format=%s",option);↵|>||||||| if (LocaleCompare(option,"bmp2") == 0)↵|>||||||| type=2;↵|>||||||| if (LocaleCompare(option,"bmp3") == 0)↵|>||||||| type=3;↵|>||||||| if (LocaleCompare(option,"bmp4") == 0)↵|>||||||| type=4;↵|>||||||| }↵|>||||||| scene=0;↵|>||||||| imageListLength=GetImageListLength(image);↵|>||||||| do↵|>||||||| {↵|>||||||| /*↵|>||||||| Initialize BMP raster file header.↵|>||||||| */↵|>||||||| if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)↵|>||||||| (void) TransformImageColorspace(image,sRGBColorspace,exception);↵|>||||||| (void) memset(&bmp_info,0,sizeof(bmp_info));↵|>||||||| bmp_info.file_size=14+12;↵|>||||||| if (type > 2)↵|>||||||| bmp_info.file_size+=28;↵|>||||||| bmp_info.offset_bits=bmp_info.file_size;↵|>||||||| bmp_info.compression=BI_RGB;↵|>||||||| bmp_info.red_mask=0x00ff0000U;↵|>||||||| bmp_info.green_mask=0x0000ff00U;↵|>||||||| bmp_info.blue_mask=0x000000ffU;↵|>||||||| bmp_info.alpha_mask=0xff000000U;↵|>||||||| bmp_subtype=UndefinedSubtype;↵|>||||||| if ((image->storage_class == PseudoClass) && (image->colors > 256))↵|>||||||| (void) SetImageStorageClass(image,DirectClass,exception);↵|>||||||| if (image->storage_class != DirectClass)↵|>||||||| {↵|>||||||| /*↵|>||||||| Colormapped BMP raster.↵|>||||||| */↵|>||||||| bmp_info.bits_per_pixel=8;↵|>||||||| if (image->colors <= 2)↵|>||||||| bmp_info.bits_per_pixel=1;↵|>||||||| else↵|>||||||| if (image->colors <= 16)↵|>||||||| bmp_info.bits_per_pixel=4;↵|>||||||| else↵|>||||||| if (image->colors <= 256)↵|>||||||| bmp_info.bits_per_pixel=8;↵|>||||||| if (image_info->compression == RLECompression)↵|>||||||| bmp_info.bits_per_pixel=8;↵|>||||||| bmp_info.number_colors=1U << bmp_info.bits_per_pixel;↵|>||||||| if (image->alpha_trait != UndefinedPixelTrait)↵|>||||||| (void) SetImageStorageClass(image,DirectClass,exception);↵|>||||||| else↵|>||||||| if ((size_t) bmp_info.number_colors < image->colors)↵|>||||||| (void) SetImageStorageClass(image,DirectClass,exception);↵|>||||||| else↵|>||||||| {↵|>||||||| bmp_info.file_size+=3*(1UL << bmp_info.bits_per_pixel);↵|>||||||| bmp_info.offset_bits+=3*(1UL << bmp_info.bits_per_pixel);↵|>||||||| if (type > 2)↵|>||||||| {↵|>||||||| bmp_info.file_size+=(1UL << bmp_info.bits_per_pixel);↵|>||||||| bmp_info.offset_bits+=(1UL << bmp_info.bits_per_pixel);↵|>||||||| }↵|>||||||| }↵|>||||||| }↵|>||||||| if (image->storage_class == DirectClass)↵|>||||||| {↵|>||||||| /*↵|>||||||| Full color BMP raster.↵|>||||||| */↵|>||||||| bmp_info.number_colors=0;↵|>||||||| option=GetImageOption(image_info,"bmp:subtype");↵|>||||||| if (option != (const char *) NULL)↵|>||||||| {↵|>||||||| if (image->alpha_trait != UndefinedPixelTrait)↵|>||||||| {↵|>||||||| if (LocaleNCompare(option,"ARGB4444",8) == 0)↵|>||||||| {↵|>||||||| bmp_subtype=ARGB4444;↵|>||||||| bmp_info.red_mask=0x00000f00U;↵|>||||||| bmp_info.green_mask=0x000000f0U;↵|>||||||| bmp_info.blue_mask=0x0000000fU;↵|>||||||| bmp_info.alpha_mask=0x0000f000U;↵|>||||||| }↵|>||||||| else if (LocaleNCompare(option,"ARGB1555",8) == 0)↵|>||||||| {↵|>||||||| bmp_subtype=ARGB1555;↵|>||||||| bmp_info.red_mask=0x00007c00U;↵|>||||||| bmp_info.green_mask=0x000003e0U;↵|>||||||| bmp_info.blue_mask=0x0000001fU;↵|>||||||| bmp_info.alpha_mask=0x00008000U;↵|>||||||| }↵|>||||||| }↵|>||||||| else↵|>||||||| {↵|>||||||| if (LocaleNCompare(option,"RGB555",6) == 0)↵|>||||||| {↵|>||||||| bmp_subtype=RGB555;↵|>||||||| bmp_info.red_mask=0x00007c00U;↵|>||||||| bmp_info.green_mask=0x000003e0U;↵|>||||||| bmp_info.blue_mask=0x0000001fU;↵|>||||||| bmp_info.alpha_mask=0U;↵|>||||||| }↵|>||||||| else if (LocaleNCompare(option,"RGB565",6) == 0)↵|>||||||| {↵|>||||||| bmp_subtype=RGB565;↵|>||||||| bmp_info.red_mask=0x0000f800U;↵|>||||||| bmp_info.green_mask=0x000007e0U;↵|>||||||| bmp_info.blue_mask=0x0000001fU;↵|>||||||| bmp_info.alpha_mask=0U;↵|>||||||| }↵|>||||||| }↵|>||||||| }↵|>||||||| if (bmp_subtype != UndefinedSubtype)↵|>||||||| {↵|>||||||| bmp_info.bits_per_pixel=16;↵|>||||||| bmp_info.compression=BI_BITFIELDS;↵|>||||||| }↵|>||||||| else↵|>||||||| {↵|>||||||| bmp_info.bits_per_pixel=(unsigned short) ((type > 3) &&↵|>||||||| (image->alpha_trait != UndefinedPixelTrait) ? 32 : 24);↵|>||||||| bmp_info.compression=(unsigned int) ((type > 3) &&↵|>||||||| (image->alpha_trait != UndefinedPixelTrait) ? BI_BITFIELDS : BI_RGB);↵|>||||||| if ((type == 3) && (image->alpha_trait != UndefinedPixelTrait))↵|>||||||| {↵|>||||||| option=GetImageOption(image_info,"bmp3:alpha");↵|>||||||| if (IsStringTrue(option))↵|>||||||| bmp_info.bits_per_pixel=32;↵|>||||||| }↵|>||||||| }↵|>||||||| }↵|>||||||| bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);↵|>||||||| bmp_info.ba_offset=0;↵|>||||||| profile=GetImageProfile(image,"icc");↵|>||||||| have_color_info=(image->rendering_intent != UndefinedIntent) ||↵|>||||||| (profile != (StringInfo *) NULL) || (image->gamma != 0.0) ? MagickTrue :↵|>||||||| MagickFalse;↵|>||||||| if (type == 2)↵|>||||||| bmp_info.size=12;↵|>||||||| else↵|>||||||| if ((type == 3) || ((image->alpha_trait == UndefinedPixelTrait) &&↵|>||||||| (have_color_info == MagickFalse)))↵|>||||||| {↵|>||||||| type=3;↵|>||||||| bmp_info.size=40;↵|>||||||| }↵|>||||||| else↵|>||||||| {↵|>||||||| int↵|>||||||| extra_size;↵|>|||||||↵|>||||||| bmp_info.size=108;↵|>||||||| extra_size=68;↵|>||||||| if ((image->rendering_intent != UndefinedIntent) ||↵|>||||||| (profile != (StringInfo *) NULL))↵|>||||||| {↵|>||||||| bmp_info.size=124;↵|>||||||| extra_size+=16;↵|>||||||| }↵|>||||||| bmp_info.file_size+=extra_size;↵|>||||||| bmp_info.offset_bits+=extra_size;↵|>||||||| }↵|>||||||| if (((ssize_t) image->columns != (ssize_t) ((signed int) image->columns)) ||↵|>||||||| ((ssize_t) image->rows != (ssize_t) ((signed int) image->rows)))↵|>||||||| ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");↵|>||||||| bmp_info.width=(ssize_t) image->columns;↵|>||||||| bmp_info.height=(ssize_t) image->rows;↵|>||||||| bmp_info.planes=1;↵|>||||||| bmp_info.image_size=(unsigned int) (bytes_per_line*image->rows);↵|>||||||| bmp_info.file_size+=bmp_info.image_size;↵|>||||||| bmp_info.x_pixels=75*39;↵|>||||||| bmp_info.y_pixels=75*39;↵|>||||||| switch (image->units)↵|>||||||| {↵|>||||||| case UndefinedResolution:↵|>||||||| case PixelsPerInchResolution:↵|>||||||| {↵|>||||||| bmp_info.x_pixels=(unsigned int) (100.0*image->resolution.x/2.54);↵|>||||||| bmp_info.y_pixels=(unsigned int) (100.0*image->resolution.y/2.54);↵|>||||||| break;↵|>||||||| }↵|>||||||| case PixelsPerCentimeterResolution:↵|>||||||| {↵|>||||||| bmp_info.x_pixels=(unsigned int) (100.0*image->resolution.x);↵|>||||||| bmp_info.y_pixels=(unsigned int) (100.0*image->resolution.y);↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| bmp_info.colors_important=bmp_info.number_colors;↵|>||||||| /*↵|>||||||| Convert MIFF to BMP raster pixels.↵|>||||||| */↵|>||||||| pixel_info=AcquireVirtualMemory(image->rows,MagickMax(bytes_per_line,↵|>||||||| image->columns+256UL)*sizeof(*pixels));↵|>||||||| if (pixel_info == (MemoryInfo *) NULL)↵|>||||||| ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");↵|>||||||| pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);↵|>||||||| (void) memset(pixels,0,(size_t) bmp_info.image_size);↵|>||||||| switch (bmp_info.bits_per_pixel)↵|>||||||| {↵|>||||||| case 1:↵|>||||||| {↵|>||||||| size_t↵|>||||||| bit,↵|>||||||| byte;↵|>|||||||↵|>||||||| /*↵|>||||||| Convert PseudoClass image to a BMP monochrome image.↵|>||||||| */↵|>||||||| for (y=0; y < (ssize_t) image->rows; y++)↵|>||||||| {↵|>||||||| ssize_t↵|>||||||| offset;↵|>|||||||↵|>||||||| p=GetVirtualPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (p == (const Quantum *) NULL)↵|>||||||| break;↵|>||||||| q=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| bit=0;↵|>||||||| byte=0;↵|>||||||| for (x=0; x < (ssize_t) image->columns; x++)↵|>||||||| {↵|>||||||| byte<<=1;↵|>||||||| byte|=GetPixelIndex(image,p) != 0 ? 0x01 : 0x00;↵|>||||||| bit++;↵|>||||||| if (bit == 8)↵|>||||||| {↵|>||||||| *q++=(unsigned char) byte;↵|>||||||| bit=0;↵|>||||||| byte=0;↵|>||||||| }↵|>||||||| p+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| if (bit != 0)↵|>||||||| {↵|>||||||| *q++=(unsigned char) (byte << (8-bit));↵|>||||||| x++;↵|>||||||| }↵|>||||||| offset=(ssize_t) (image->columns+7)/8;↵|>||||||| for (x=offset; x < (ssize_t) bytes_per_line; x++)↵|>||||||| *q++=0x00;↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,↵|>||||||| image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| break;↵|>||||||| }↵|>||||||| case 4:↵|>||||||| {↵|>||||||| unsigned int↵|>||||||| byte,↵|>||||||| nibble;↵|>|||||||↵|>||||||| ssize_t↵|>||||||| offset;↵|>|||||||↵|>||||||| /*↵|>||||||| Convert PseudoClass image to a BMP monochrome image.↵|>||||||| */↵|>||||||| for (y=0; y < (ssize_t) image->rows; y++)↵|>||||||| {↵|>||||||| p=GetVirtualPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (p == (const Quantum *) NULL)↵|>||||||| break;↵|>||||||| q=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| nibble=0;↵|>||||||| byte=0;↵|>||||||| for (x=0; x < (ssize_t) image->columns; x++)↵|>||||||| {↵|>||||||| byte<<=4;↵|>||||||| byte|=((unsigned int) GetPixelIndex(image,p) & 0x0f);↵|>||||||| nibble++;↵|>||||||| if (nibble == 2)↵|>||||||| {↵|>||||||| *q++=(unsigned char) byte;↵|>||||||| nibble=0;↵|>||||||| byte=0;↵|>||||||| }↵|>||||||| p+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| if (nibble != 0)↵|>||||||| {↵|>||||||| *q++=(unsigned char) (byte << 4);↵|>||||||| x++;↵|>||||||| }↵|>||||||| offset=(ssize_t) (image->columns+1)/2;↵|>||||||| for (x=offset; x < (ssize_t) bytes_per_line; x++)↵|>||||||| *q++=0x00;↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,↵|>||||||| image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| break;↵|>||||||| }↵|>||||||| case 8:↵|>||||||| {↵|>||||||| /*↵|>||||||| Convert PseudoClass packet to BMP pixel.↵|>||||||| */↵|>||||||| for (y=0; y < (ssize_t) image->rows; y++)↵|>||||||| {↵|>||||||| p=GetVirtualPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (p == (const Quantum *) NULL)↵|>||||||| break;↵|>||||||| q=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| for (x=0; x < (ssize_t) image->columns; x++)↵|>||||||| {↵|>||||||| *q++=(unsigned char) ((ssize_t) GetPixelIndex(image,p));↵|>||||||| p+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| for ( ; x < (ssize_t) bytes_per_line; x++)↵|>||||||| *q++=0x00;↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,↵|>||||||| image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| break;↵|>||||||| }↵|>||||||| case 16:↵|>||||||| {↵|>||||||| /*↵|>||||||| Convert DirectClass packet to BMP BGR888.↵|>||||||| */↵|>||||||| for (y=0; y < (ssize_t) image->rows; y++)↵|>||||||| {↵|>||||||| p=GetVirtualPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (p == (const Quantum *) NULL)↵|>||||||| break;↵|>||||||| q=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| for (x=0; x < (ssize_t) image->columns; x++)↵|>||||||| {↵|>||||||| unsigned short↵|>||||||| pixel;↵|>|||||||↵|>||||||| pixel=0;↵|>||||||| if (bmp_subtype == ARGB4444)↵|>||||||| {↵|>||||||| pixel=(unsigned short) (ScaleQuantumToAny(↵|>||||||| GetPixelAlpha(image,p),15) << 12);↵|>||||||| pixel|=(unsigned short) (ScaleQuantumToAny(↵|>||||||| GetPixelRed(image,p),15) << 8);↵|>||||||| pixel|=(unsigned short) (ScaleQuantumToAny(↵|>||||||| GetPixelGreen(image,p),15) << 4);↵|>||||||| pixel|=(unsigned short) (ScaleQuantumToAny(↵|>||||||| GetPixelBlue(image,p),15));↵|>||||||| }↵|>||||||| else if (bmp_subtype == RGB565)↵|>||||||| {↵|>||||||| pixel=(unsigned short) (ScaleQuantumToAny(↵|>||||||| GetPixelRed(image,p),31) << 11);↵|>||||||| pixel|=(unsigned short) (ScaleQuantumToAny(↵|>||||||| GetPixelGreen(image,p),63) << 5);↵|>||||||| pixel|=(unsigned short) (ScaleQuantumToAny(↵|>||||||| GetPixelBlue(image,p),31));↵|>||||||| }↵|>||||||| else↵|>||||||| {↵|>||||||| if (bmp_subtype == ARGB1555)↵|>||||||| pixel=(unsigned short) (ScaleQuantumToAny(↵|>||||||| GetPixelAlpha(image,p),1) << 15);↵|>||||||| pixel|=(unsigned short) (ScaleQuantumToAny(↵|>||||||| GetPixelRed(image,p),31) << 10);↵|>||||||| pixel|=(unsigned short) (ScaleQuantumToAny(↵|>||||||| GetPixelGreen(image,p),31) << 5);↵|>||||||| pixel|=(unsigned short) (ScaleQuantumToAny(↵|>||||||| GetPixelBlue(image,p),31));↵|>||||||| }↵|>||||||| *((unsigned short *) q)=pixel;↵|>||||||| q+=2;↵|>||||||| p+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| for (x=2L*(ssize_t) image->columns; x < (ssize_t) bytes_per_line; x++)↵|>||||||| *q++=0x00;↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,↵|>||||||| image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| break;↵|>||||||| }↵|>||||||| case 24:↵|>||||||| {↵|>||||||| /*↵|>||||||| Convert DirectClass packet to BMP BGR888.↵|>||||||| */↵|>||||||| for (y=0; y < (ssize_t) image->rows; y++)↵|>||||||| {↵|>||||||| p=GetVirtualPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (p == (const Quantum *) NULL)↵|>||||||| break;↵|>||||||| q=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| for (x=0; x < (ssize_t) image->columns; x++)↵|>||||||| {↵|>||||||| *q++=ScaleQuantumToChar(GetPixelBlue(image,p));↵|>||||||| *q++=ScaleQuantumToChar(GetPixelGreen(image,p));↵|>||||||| *q++=ScaleQuantumToChar(GetPixelRed(image,p));↵|>||||||| p+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| for (x=3L*(ssize_t) image->columns; x < (ssize_t) bytes_per_line; x++)↵|>||||||| *q++=0x00;↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,↵|>||||||| image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| break;↵|>||||||| }↵|>||||||| case 32:↵|>||||||| {↵|>||||||| /*↵|>||||||| Convert DirectClass packet to ARGB8888 pixel.↵|>||||||| */↵|>||||||| for (y=0; y < (ssize_t) image->rows; y++)↵|>||||||| {↵|>||||||| p=GetVirtualPixels(image,0,y,image->columns,1,exception);↵|>||||||| if (p == (const Quantum *) NULL)↵|>||||||| break;↵|>||||||| q=pixels+(image->rows-y-1)*bytes_per_line;↵|>||||||| for (x=0; x < (ssize_t) image->columns; x++)↵|>||||||| {↵|>||||||| *q++=ScaleQuantumToChar(GetPixelBlue(image,p));↵|>||||||| *q++=ScaleQuantumToChar(GetPixelGreen(image,p));↵|>||||||| *q++=ScaleQuantumToChar(GetPixelRed(image,p));↵|>||||||| *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));↵|>||||||| p+=GetPixelChannels(image);↵|>||||||| }↵|>||||||| if (image->previous == (Image *) NULL)↵|>||||||| {↵|>||||||| status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,↵|>||||||| image->rows);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| if ((type > 2) && (bmp_info.bits_per_pixel == 8))↵|>||||||| if (image_info->compression != NoCompression)↵|>||||||| {↵|>||||||| MemoryInfo↵|>||||||| *rle_info;↵|>|||||||↵|>||||||| /*↵|>||||||| Convert run-length encoded raster pixels.↵|>||||||| */↵|>||||||| rle_info=AcquireVirtualMemory((size_t) (2*(bytes_per_line+2)+2),↵|>||||||| (image->rows+2)*sizeof(*pixels));↵|>||||||| if (rle_info == (MemoryInfo *) NULL)↵|>||||||| {↵|>||||||| pixel_info=RelinquishVirtualMemory(pixel_info);↵|>||||||| ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");↵|>||||||| }↵|>||||||| bmp_data=(unsigned char *) GetVirtualMemoryBlob(rle_info);↵|>||||||| bmp_info.file_size-=bmp_info.image_size;↵|>||||||| bmp_info.image_size=(unsigned int) EncodeImage(image,bytes_per_line,↵|>||||||| pixels,bmp_data);↵|>||||||| bmp_info.file_size+=bmp_info.image_size;↵|>||||||| pixel_info=RelinquishVirtualMemory(pixel_info);↵|>||||||| pixel_info=rle_info;↵|>||||||| pixels=bmp_data;↵|>||||||| bmp_info.compression=BI_RLE8;↵|>||||||| }↵|>||||||| /*↵|>||||||| Write BMP for Windows, all versions, 14-byte header.↵|>||||||| */↵|>||||||| if (image->debug != MagickFalse)↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Writing BMP version %.20g datastream",(double) type);↵|>||||||| if (image->storage_class == DirectClass)↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Storage class=DirectClass");↵|>||||||| else↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Storage class=PseudoClass");↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Image depth=%.20g",(double) image->depth);↵|>||||||| if (image->alpha_trait != UndefinedPixelTrait)↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Matte=True");↵|>||||||| else↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Matte=MagickFalse");↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " BMP bits_per_pixel=%.20g",(double) bmp_info.bits_per_pixel);↵|>||||||| switch ((int) bmp_info.compression)↵|>||||||| {↵|>||||||| case BI_RGB:↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Compression=BI_RGB");↵|>||||||| break;↵|>||||||| }↵|>||||||| case BI_RLE8:↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Compression=BI_RLE8");↵|>||||||| break;↵|>||||||| }↵|>||||||| case BI_BITFIELDS:↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Compression=BI_BITFIELDS");↵|>||||||| break;↵|>||||||| }↵|>||||||| default:↵|>||||||| {↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Compression=UNKNOWN (%u)",bmp_info.compression);↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| if (bmp_info.number_colors == 0)↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Number_colors=unspecified");↵|>||||||| else↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Number_colors=%u",bmp_info.number_colors);↵|>||||||| }↵|>||||||| profile_data=0;↵|>||||||| profile_size=0;↵|>||||||| profile_size_pad=0;↵|>||||||| if (profile != (StringInfo *) NULL)↵|>||||||| {↵|>||||||| profile_data=(MagickOffsetType) bmp_info.file_size-14; /* from head of BMP info header */↵|>||||||| profile_size=(MagickOffsetType) GetStringInfoLength(profile);↵|>||||||| if ((profile_size % 4) > 0)↵|>||||||| profile_size_pad=4-(profile_size%4);↵|>||||||| bmp_info.file_size+=profile_size+profile_size_pad;↵|>||||||| }↵|>||||||| (void) WriteBlob(image,2,(unsigned char *) "BM");↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.file_size);↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.ba_offset); /* always 0 */↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.offset_bits);↵|>||||||| if (type == 2)↵|>||||||| {↵|>||||||| /*↵|>||||||| Write 12-byte version 2 bitmap header.↵|>||||||| */↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.size);↵|>||||||| (void) WriteBlobLSBSignedShort(image,(signed short) bmp_info.width);↵|>||||||| (void) WriteBlobLSBSignedShort(image,(signed short) bmp_info.height);↵|>||||||| (void) WriteBlobLSBShort(image,bmp_info.planes);↵|>||||||| (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);↵|>||||||| }↵|>||||||| else↵|>||||||| {↵|>||||||| /*↵|>||||||| Write 40-byte version 3+ bitmap header.↵|>||||||| */↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.size);↵|>||||||| (void) WriteBlobLSBSignedLong(image,(signed int) bmp_info.width);↵|>||||||| (void) WriteBlobLSBSignedLong(image,(signed int) bmp_info.height);↵|>||||||| (void) WriteBlobLSBShort(image,bmp_info.planes);↵|>||||||| (void) WriteBlobLSBShort(image,bmp_info.bits_per_pixel);↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.compression);↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.image_size);↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.x_pixels);↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.y_pixels);↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.number_colors);↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.colors_important);↵|>||||||| }↵|>||||||| if ((type > 3) && ((image->alpha_trait != UndefinedPixelTrait) ||↵|>||||||| (have_color_info != MagickFalse)))↵|>||||||| {↵|>||||||| /*↵|>||||||| Write the rest of the 108-byte BMP Version 4 header.↵|>||||||| */↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.red_mask);↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.green_mask);↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.blue_mask);↵|>||||||| (void) WriteBlobLSBLong(image,bmp_info.alpha_mask);↵|>||||||| if (profile != (StringInfo *) NULL)↵|>||||||| (void) WriteBlobLSBLong(image,0x4D424544U); /* PROFILE_EMBEDDED */↵|>||||||| else↵|>||||||| (void) WriteBlobLSBLong(image,0x73524742U); /* sRGB */↵|>||||||| ↵|>||||||| // bounds check, assign .0 if invalid value↵|>||||||| if (isgreater(image->chromaticity.red_primary.x, 1.0) ||↵|>||||||| !isgreater(image->chromaticity.red_primary.x, 0.0))↵|>||||||| image->chromaticity.red_primary.x = 0.0;↵|>||||||| if (isgreater(image->chromaticity.red_primary.y, 1.0) ||↵|>||||||| !isgreater(image->chromaticity.red_primary.y, 0.0))↵|>||||||| image->chromaticity.red_primary.y = 0.0;↵|>||||||| if (isgreater(image->chromaticity.green_primary.x, 1.0) ||↵|>||||||| !isgreater(image->chromaticity.green_primary.x, 0.0))↵|>||||||| image->chromaticity.green_primary.x = 0.0;↵|>||||||| if (isgreater(image->chromaticity.green_primary.y, 1.0) ||↵|>||||||| !isgreater(image->chromaticity.green_primary.y, 0.0))↵|>||||||| image->chromaticity.green_primary.y = 0.0;↵|>||||||| if (isgreater(image->chromaticity.blue_primary.x, 1.0) ||↵|>||||||| !isgreater(image->chromaticity.blue_primary.x, 0.0))↵|>||||||| image->chromaticity.blue_primary.x = 0.0;↵|>||||||| if (isgreater(image->chromaticity.blue_primary.y, 1.0) ||↵|>||||||| !isgreater(image->chromaticity.blue_primary.y, 0.0))↵|>||||||| image->chromaticity.blue_primary.y = 0.0;↵|>||||||| if (isgreater(bmp_info.gamma_scale.x, 1.0) ||↵|>||||||| !isgreater(bmp_info.gamma_scale.x, 0.0))↵|>||||||| bmp_info.gamma_scale.x = 0.0;↵|>||||||| if (isgreater(bmp_info.gamma_scale.y, 1.0) ||↵|>||||||| !isgreater(bmp_info.gamma_scale.y, 0.0))↵|>||||||| bmp_info.gamma_scale.y = 0.0;↵|>||||||| if (isgreater(bmp_info.gamma_scale.z, 1.0) ||↵|>||||||| !isgreater(bmp_info.gamma_scale.z, 0.0))↵|>||||||| bmp_info.gamma_scale.z = 0.0;↵|>|||||||↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| (image->chromaticity.red_primary.x*0x40000000));↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| (image->chromaticity.red_primary.y*0x40000000));↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| ((1.000f-(image->chromaticity.red_primary.x+↵|>||||||| image->chromaticity.red_primary.y))*0x40000000));↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| (image->chromaticity.green_primary.x*0x40000000));↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| (image->chromaticity.green_primary.y*0x40000000));↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| ((1.000f-(image->chromaticity.green_primary.x+↵|>||||||| image->chromaticity.green_primary.y))*0x40000000));↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| (image->chromaticity.blue_primary.x*0x40000000));↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| (image->chromaticity.blue_primary.y*0x40000000));↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| ((1.000f-(image->chromaticity.blue_primary.x+↵|>||||||| image->chromaticity.blue_primary.y))*0x40000000));↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| (bmp_info.gamma_scale.x*0x10000));↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| (bmp_info.gamma_scale.y*0x10000));↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| (bmp_info.gamma_scale.z*0x10000));↵|>||||||| if ((image->rendering_intent != UndefinedIntent) ||↵|>||||||| (profile != (StringInfo *) NULL))↵|>||||||| {↵|>||||||| ssize_t↵|>||||||| intent;↵|>|||||||↵|>||||||| switch ((int) image->rendering_intent)↵|>||||||| {↵|>||||||| case SaturationIntent:↵|>||||||| {↵|>||||||| intent=LCS_GM_BUSINESS;↵|>||||||| break;↵|>||||||| }↵|>||||||| case RelativeIntent:↵|>||||||| {↵|>||||||| intent=LCS_GM_GRAPHICS;↵|>||||||| break;↵|>||||||| }↵|>||||||| case PerceptualIntent:↵|>||||||| {↵|>||||||| intent=LCS_GM_IMAGES;↵|>||||||| break;↵|>||||||| }↵|>||||||| case AbsoluteIntent:↵|>||||||| {↵|>||||||| intent=LCS_GM_ABS_COLORIMETRIC;↵|>||||||| break;↵|>||||||| }↵|>||||||| default:↵|>||||||| {↵|>||||||| intent=0;↵|>||||||| break;↵|>||||||| }↵|>||||||| }↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int) intent);↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int) profile_data);↵|>||||||| (void) WriteBlobLSBLong(image,(unsigned int)↵|>||||||| (profile_size+profile_size_pad));↵|>||||||| (void) WriteBlobLSBLong(image,0x00); /* reserved */↵|>||||||| }↵|>||||||| }↵|>||||||| if (image->storage_class == PseudoClass)↵|>||||||| {↵|>||||||| unsigned char↵|>||||||| *bmp_colormap;↵|>|||||||↵|>||||||| /*↵|>||||||| Dump colormap to file.↵|>||||||| */↵|>||||||| if (image->debug != MagickFalse)↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Colormap: %.20g entries",(double) image->colors);↵|>||||||| bmp_colormap=(unsigned char *) AcquireQuantumMemory((size_t) (1UL <<↵|>||||||| bmp_info.bits_per_pixel),4*sizeof(*bmp_colormap));↵|>||||||| if (bmp_colormap == (unsigned char *) NULL)↵|>||||||| {↵|>||||||| pixel_info=RelinquishVirtualMemory(pixel_info);↵|>||||||| ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");↵|>||||||| }↵|>||||||| q=bmp_colormap;↵|>||||||| for (i=0; i < (ssize_t) MagickMin((ssize_t) image->colors,(ssize_t) bmp_info.number_colors); i++)↵|>||||||| {↵|>||||||| *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));↵|>||||||| *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));↵|>||||||| *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));↵|>||||||| if (type > 2)↵|>||||||| *q++=(unsigned char) 0x0;↵|>||||||| }↵|>||||||| for ( ; i < (ssize_t) (1UL << bmp_info.bits_per_pixel); i++)↵|>||||||| {↵|>||||||| *q++=(unsigned char) 0x00;↵|>||||||| *q++=(unsigned char) 0x00;↵|>||||||| *q++=(unsigned char) 0x00;↵|>||||||| if (type > 2)↵|>||||||| *q++=(unsigned char) 0x00;↵|>||||||| }↵|>||||||| if (type <= 2)↵|>||||||| (void) WriteBlob(image,(size_t) (3*(1L << bmp_info.bits_per_pixel)),↵|>||||||| bmp_colormap);↵|>||||||| else↵|>||||||| (void) WriteBlob(image,(size_t) (4*(1L << bmp_info.bits_per_pixel)),↵|>||||||| bmp_colormap);↵|>||||||| bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);↵|>||||||| }↵|>||||||| if (image->debug != MagickFalse)↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Pixels: %u bytes",bmp_info.image_size);↵|>||||||| (void) WriteBlob(image,(size_t) bmp_info.image_size,pixels);↵|>||||||| if (profile != (StringInfo *) NULL)↵|>||||||| {↵|>||||||| if (image->debug != MagickFalse)↵|>||||||| (void) LogMagickEvent(CoderEvent,GetMagickModule(),↵|>||||||| " Profile: %g bytes",(double) profile_size+profile_size_pad);↵|>||||||| (void) WriteBlob(image,(size_t) profile_size,GetStringInfoDatum(profile));↵|>||||||| if (profile_size_pad > 0) /* padding for 4 bytes multiple */↵|>||||||| (void) WriteBlob(image,(size_t) profile_size_pad,"\0\0\0");↵|>||||||| }↵|>||||||| pixel_info=RelinquishVirtualMemory(pixel_info);↵|>||||||| if (GetNextImageInList(image) == (Image *) NULL)↵|>||||||| break;↵|>||||||| image=SyncNextImageInList(image);↵|>||||||| status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);↵|>||||||| if (status == MagickFalse)↵|>||||||| break;↵|>||||||| } while (image_info->adjoin != MagickFalse);↵|>||||||| (void) CloseBlob(image);↵|>||||||| return(MagickTrue);↵|>|||||||}↵|>||||||||>|||| \ No newline at end of file diff --git a/projects/blades-engine/source/Bmp.hx b/projects/blades-engine/source/Bmp.hx index e69de29b..131393d8 100644 --- a/projects/blades-engine/source/Bmp.hx +++ b/projects/blades-engine/source/Bmp.hx @@ -0,0 +1,103 @@ +package; + +import sys.io.File; +import haxe.io.Bytes; +import flash.display.BitmapData; +import flixel.util.FlxColor; + +typedef ByteStream = { + bytes:Bytes, + position:Int +}; + +class Bmp { + static function getByteStream(file:String):ByteStream { + return { + bytes: File.getBytes(file), + position:0 + }; + } + + static function readByte(bytes:ByteStream):Int { + return bytes.bytes.get(bytes.position++); + } + + static function readInt32(bytes:ByteStream):Int { + var int = bytes.bytes.getInt32(bytes.position); + bytes.position += 4; + return int; + } + + static function readUInt32(bytes:ByteStream):Int { + var int = readInt32(bytes); + return if (int < 0) cast (4294967296 + cast int) else int; + } + + static function readUInt16(bytes:ByteStream):Int { + var int = bytes.bytes.getUInt16(bytes.position); + bytes.position += 2; + return int; + } + + static function checkHeader(bytes:ByteStream) { + // 42 4D + if (readByte(bytes) != 66 || readByte(bytes) != 77) + throw 'Bad bmp header!'; + } + + public static function loadBitmapData(bmpFile:String) { + var stream = getByteStream(bmpFile); + checkHeader(stream); + + var fileSize = readUInt32(stream); + var fileReserved = readUInt32(stream); + var fileOffBits = readUInt32(stream); + + var imgSize = readUInt32(stream); + + var imgWidth = readInt32(stream); + var imgHeight = readInt32(stream); + + var planes = readUInt16(stream); + var bitsPerPixel = readUInt16(stream); + + var compression = readUInt32(stream); + var sizeImage = readUInt32(stream); + + var xPixelsPerMeter = readInt32(stream); + var yPixelsPerMeter = readInt32(stream); + + var colorsUsed = readUInt32(stream); + var colorsImportant = readUInt32(stream); + + var colors:Array = []; + + for (c in 0...colorsUsed) { + var blue = readByte(stream); + var green = readByte(stream); + var red = readByte(stream); + var _ = readByte(stream); + colors.push(FlxColor.fromRGB(red, green, blue)); + } + + // BMPs can be encoded upside-down when the height is negative + var realHeight:Int = cast Math.abs(imgHeight); + var data = new BitmapData(imgWidth, realHeight); + var y = if (imgHeight > 0) 0 else realHeight - 1; + var dy = if (imgHeight > 0) 1 else -1; + var rowPadding:Int = cast (sizeImage - (realHeight * imgWidth)) / realHeight; + for (_ in 0... realHeight) { + for (x in 0... imgWidth) { + var colorIdx = readByte(stream); + data.setPixel(x, realHeight-1-y, colors[colorIdx]); + } + for (_ in 0... rowPadding) { + readByte(stream); + } + + y += dy; + } + + return data; + } +} \ No newline at end of file diff --git a/projects/blades-engine/source/IsometricMapState.kiss b/projects/blades-engine/source/IsometricMapState.kiss index 45c787ca..75c45deb 100644 --- a/projects/blades-engine/source/IsometricMapState.kiss +++ b/projects/blades-engine/source/IsometricMapState.kiss @@ -9,7 +9,7 @@ (method &override :Void create [] (super.create) // TODO load from a more accessible path - (let [bitmapData (BitmapData.fromFile "Data/Terrain Graphics/G796.png") + (let [bitmapData (Bmp.loadBitmapData "Data/Terrain Graphics/G796.bmp") spriteSheet (.loadGraphic (new FlxSprite) (FlxGraphic.fromBitmapData bitmapData))] (spriteSheet.replaceColor FlxColor.WHITE FlxColor.TRANSPARENT) (let [sheetWidth (/ (- spriteSheet.frameWidth SPRITE_PADDING) (+ SPRITE_PADDING FLOOR_WIDTH))