% December 2001 %
% %
% %
-% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2018 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 %
% %
-% http://www.imagemagick.org/script/license.php %
+% https://www.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, %
#define BI_JPEG 4
#undef BI_PNG
#define BI_PNG 5
-#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__) || defined(__MINGW64__)
+#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
#undef BI_RGB
#define BI_RGB 0
#undef BI_RLE8
#define LCS_GM_ABS_COLORIMETRIC 8 /* Absolute */
#endif
\f
+/*
+ Enumerated declaractions.
+*/
+typedef enum
+{
+ UndefinedSubtype,
+ RGB555,
+ RGB565,
+ ARGB4444,
+ ARGB1555
+} BMPSubtype;
+
/*
Typedef declarations.
*/
alpha_mask,
colors_important;
- int
+ long
colorspace;
PrimaryInfo
%
% The format of the DecodeImage method is:
%
-% MagickBooleanType DecodeImage(Image *image,
-% const size_t compression,unsigned char *pixels)
+% MagickBooleanType DecodeImage(Image *image,const size_t compression,
+% unsigned char *pixels,const size_t number_pixels)
%
% A description of each parameter follows:
%
% 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)
+ unsigned char *pixels,const size_t number_pixels)
{
int
+ byte,
count;
register ssize_t
ssize_t
y;
- unsigned char
- byte;
-
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(pixels != (unsigned char *) NULL);
- (void) ResetMagickMemory(pixels,0,(size_t) image->columns*image->rows*
- sizeof(*pixels));
+ (void) memset(pixels,0,number_pixels*sizeof(*pixels));
byte=0;
x=0;
p=pixels;
- q=pixels+(size_t) image->columns*image->rows;
+ q=pixels+number_pixels;
for (y=0; y < (ssize_t) image->rows; )
{
MagickBooleanType
count=ReadBlobByte(image);
if (count == EOF)
break;
- if (count != 0)
+ if (count > 0)
{
/*
Encoded mode.
*/
count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p));
- byte=(unsigned char) ReadBlobByte(image);
+ byte=ReadBlobByte(image);
+ if (byte == EOF)
+ break;
if (compression == BI_RLE8)
{
for (i=0; i < (ssize_t) count; i++)
count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p));
if (compression == BI_RLE8)
for (i=0; i < (ssize_t) count; i++)
- *p++=(unsigned char) ReadBlobByte(image);
+ {
+ 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=(unsigned char) ReadBlobByte(image);
+ {
+ byte=ReadBlobByte(image);
+ if (byte == EOF)
+ break;
+ }
*p++=(unsigned char)
((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
}
if (compression == BI_RLE8)
{
if ((count & 0x01) != 0)
- (void) ReadBlobByte(image);
+ if (ReadBlobByte(image) == EOF)
+ break;
}
else
if (((count & 0x03) == 1) || ((count & 0x03) == 2))
- (void) ReadBlobByte(image);
+ if (ReadBlobByte(image) == EOF)
+ break;
break;
}
}
Runlength encode pixels.
*/
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(pixels != (const unsigned char *) NULL);
size_t
bit,
- blue,
bytes_per_line,
- green,
- length,
- red;
+ length;
ssize_t
count,
magick[12],
*pixels;
+ unsigned int
+ blue,
+ green,
+ offset_bits,
+ red;
+
/*
Open image file.
*/
assert(image_info != (const ImageInfo *) NULL);
- assert(image_info->signature == MagickSignature);
+ assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image_info->filename);
assert(exception != (ExceptionInfo *) NULL);
- assert(exception->signature == MagickSignature);
+ assert(exception->signature == MagickCoreSignature);
image=AcquireImage(image_info,exception);
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
if (status == MagickFalse)
/*
Determine if this a BMP file.
*/
- (void) ResetMagickMemory(&bmp_info,0,sizeof(bmp_info));
+ (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");
PixelPacket
shift;
- size_t
- profile_data,
- profile_size;
-
/*
Verify BMP identifier.
*/
- if (bmp_info.ba_offset == 0)
- start_position=TellBlob(image)-2;
+ start_position=TellBlob(image)-2;
bmp_info.ba_offset=0;
while (LocaleNCompare((char *) magick,"BA",2) == 0)
{
*/
if (bmp_info.size < 40)
ThrowReaderException(CorruptImageError,"NonOS2HeaderSizeError");
- bmp_info.width=(ssize_t) ((int) ReadBlobLSBLong(image));
- bmp_info.height=(ssize_t) ((int) ReadBlobLSBLong(image));
+ 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);
bmp_info.x_pixels=ReadBlobLSBLong(image);
bmp_info.y_pixels=ReadBlobLSBLong(image);
bmp_info.number_colors=ReadBlobLSBLong(image);
+ if (bmp_info.number_colors > GetBlobSize(image))
+ ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
bmp_info.colors_important=ReadBlobLSBLong(image);
- profile_data=0;
- profile_size=0;
if (image->debug != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
bmp_info.height);
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Bits per pixel: %.20g",(double) bmp_info.bits_per_pixel);
- switch ((int) bmp_info.compression)
+ switch (bmp_info.compression)
{
case BI_RGB:
{
bmp_info.blue_mask=ReadBlobLSBLong(image);
if (bmp_info.size > 40)
{
-
double
- sum;
+ gamma;
/*
Read color management information.
*/
bmp_info.alpha_mask=ReadBlobLSBLong(image);
- bmp_info.colorspace=(int) ReadBlobLSBLong(image);
+ bmp_info.colorspace=ReadBlobLSBSignedLong(image);
/*
Decode 2^30 fixed point formatted CIE primaries.
*/
bmp_info.blue_primary.y=(double) ReadBlobLSBLong(image)/BMP_DENOM;
bmp_info.blue_primary.z=(double) ReadBlobLSBLong(image)/BMP_DENOM;
- sum=bmp_info.red_primary.x+bmp_info.red_primary.y+
+ gamma=bmp_info.red_primary.x+bmp_info.red_primary.y+
bmp_info.red_primary.z;
- bmp_info.red_primary.x/=sum;
- bmp_info.red_primary.y/=sum;
+ 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;
- sum=bmp_info.green_primary.x+bmp_info.green_primary.y+
+ gamma=bmp_info.green_primary.x+bmp_info.green_primary.y+
bmp_info.green_primary.z;
- bmp_info.green_primary.x/=sum;
- bmp_info.green_primary.y/=sum;
+ 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;
- sum=bmp_info.blue_primary.x+bmp_info.blue_primary.y+
+ gamma=bmp_info.blue_primary.x+bmp_info.blue_primary.y+
bmp_info.blue_primary.z;
- bmp_info.blue_primary.x/=sum;
- bmp_info.blue_primary.y/=sum;
+ 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;
break;
}
}
- profile_data=ReadBlobLSBLong(image);
- profile_size=ReadBlobLSBLong(image);
- (void) profile_data;
- (void) profile_size;
+ (void) ReadBlobLSBLong(image); /* Profile data */
+ (void) ReadBlobLSBLong(image); /* Profile size */
(void) ReadBlobLSBLong(image); /* Reserved byte */
}
}
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:
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
packet_size=4;
offset=SeekBlob(image,start_position+14+bmp_info.size,SEEK_SET);
if (offset < 0)
- ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+ {
+ 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))
- ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
+ {
+ bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
+ ThrowReaderException(CorruptImageError,
+ "InsufficientImageDataInFile");
+ }
p=bmp_colormap;
for (i=0; i < (ssize_t) image->colors; i++)
{
}
bmp_colormap=(unsigned char *) RelinquishMagickMemory(bmp_colormap);
}
- 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));
/*
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");
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;
- pixel_info=AcquireVirtualMemory((size_t) 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 (((MagickSizeType) length/8) > GetBlobSize(image))
+ 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);
/*
Convert run-length encoded raster pixels.
*/
- status=DecodeImage(image,bmp_info.compression,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);
bmp_info.blue_mask=0x0000001fU;
}
}
- (void) ResetMagickMemory(&shift,0,sizeof(shift));
- (void) ResetMagickMemory(&quantum_bits,0,sizeof(quantum_bits));
+ (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))
{
- register size_t
+ register unsigned int
sample;
/*
*/
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)
break;
for (x=0; x < ((ssize_t) image->columns-1); x+=2)
{
- if (IsValidColormapIndex(image,(*p >> 4) & 0x0f,&index,exception)
- == MagickFalse)
- break;
+ ValidateColormapValue(image,(ssize_t) ((*p >> 4) & 0x0f),&index,
+ exception);
SetPixelIndex(image,index,q);
q+=GetPixelChannels(image);
- if (IsValidColormapIndex(image,*p & 0x0f,&index,exception) ==
- MagickFalse)
- break;
+ ValidateColormapValue(image,(ssize_t) (*p & 0x0f),&index,exception);
SetPixelIndex(image,index,q);
q+=GetPixelChannels(image);
p++;
}
if ((image->columns % 2) != 0)
{
- if (IsValidColormapIndex(image,(*p >> 4) & 0xf,&index,exception)
- == MagickFalse)
- break;
+ 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;
break;
for (x=(ssize_t) image->columns; x != 0; --x)
{
- if (IsValidColormapIndex(image,*p++,&index,exception) ==
- MagickFalse)
- break;
+ ValidateColormapValue(image,(ssize_t) *p++,&index,exception);
SetPixelIndex(image,index,q);
q+=GetPixelChannels(image);
}
- if (x > 0)
- break;
if (SyncAuthenticPixels(image,exception) == MagickFalse)
break;
offset=(MagickOffsetType) (image->rows-y-1);
}
case 16:
{
- size_t
+ unsigned int
alpha,
pixel;
/*
Convert bitfield encoded 16-bit PseudoColor scanline.
*/
- if (bmp_info.compression != BI_RGB &&
- bmp_info.compression != BI_BITFIELDS)
+ if ((bmp_info.compression != BI_RGB) &&
+ (bmp_info.compression != BI_BITFIELDS))
{
pixel_info=RelinquishVirtualMemory(pixel_info);
ThrowReaderException(CorruptImageError,
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
- pixel=(size_t) (*p++);
+ pixel=(unsigned int) (*p++);
pixel|=(*p++) << 8;
red=((pixel & bmp_info.red_mask) << shift.red) >> 16;
if (quantum_bits.red == 5)
bytes_per_line=4*(image->columns);
for (y=(ssize_t) image->rows-1; y >= 0; y--)
{
- size_t
+ unsigned int
alpha,
pixel;
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
- pixel=(size_t) (*p++);
- pixel|=((size_t) *p++ << 8);
- pixel|=((size_t) *p++ << 16);
- pixel|=((size_t) *p++ << 24);
+ 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);
if (flipped_image != (Image *) NULL)
{
DuplicateBlob(flipped_image,image);
- image=DestroyImage(image);
+ ReplaceImageInList(&image, flipped_image);
image=flipped_image;
}
}
AcquireNextImage(image_info,image,exception);
if (GetNextImageInList(image) == (Image *) NULL)
{
- image=DestroyImageList(image);
+ status=MagickFalse;
return((Image *) NULL);
}
image=SyncNextImageInList(image);
}
} while (IsBMP(magick,2) != MagickFalse);
(void) CloseBlob(image);
+ if (status == MagickFalse)
+ return(DestroyImageList(image));
return(GetFirstImageInList(image));
}
\f
entry->encoder=(EncodeImageHandler *) WriteBMPImage;
entry->magick=(IsImageFormatHandler *) IsBMP;
entry->flags^=CoderAdjoinFlag;
- entry->flags|=CoderSeekableStreamFlag;
+ entry->flags|=CoderDecoderSeekableStreamFlag;
(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|=CoderSeekableStreamFlag;
+ entry->flags|=CoderDecoderSeekableStreamFlag;
(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|=CoderSeekableStreamFlag;
+ entry->flags|=CoderDecoderSeekableStreamFlag;
(void) RegisterMagickInfo(entry);
return(MagickImageCoderSignature);
}
{
BMPInfo
bmp_info;
- const char
- *value;
+ BMPSubtype
+ bmp_subtype;
+
+ const char
+ *option;
const StringInfo
*profile;
size_t
bytes_per_line,
+ imageListLength,
type;
ssize_t
Open output image file.
*/
assert(image_info != (const ImageInfo *) NULL);
- assert(image_info->signature == MagickSignature);
+ assert(image_info->signature == MagickCoreSignature);
assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
+ assert(image->signature == MagickCoreSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(exception != (ExceptionInfo *) NULL);
- assert(exception->signature == MagickSignature);
+ assert(exception->signature == MagickCoreSignature);
status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
if (status == MagickFalse)
return(status);
else
if (LocaleCompare(image_info->magick,"BMP3") == 0)
type=3;
-
- value=GetImageOption(image_info,"bmp:format");
-
- if (value != (char *) NULL)
+ option=GetImageOption(image_info,"bmp:format");
+ if (option != (char *) NULL)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Format=%s",value);
-
- if (LocaleCompare(value,"bmp2") == 0)
+ " Format=%s",option);
+ if (LocaleCompare(option,"bmp2") == 0)
type=2;
- if (LocaleCompare(value,"bmp3") == 0)
+ if (LocaleCompare(option,"bmp3") == 0)
type=3;
- if (LocaleCompare(value,"bmp4") == 0)
+ if (LocaleCompare(option,"bmp4") == 0)
type=4;
}
-
scene=0;
+ imageListLength=GetImageListLength(image);
do
{
/*
Initialize BMP raster file header.
*/
- (void) TransformImageColorspace(image,sRGBColorspace,exception);
- (void) ResetMagickMemory(&bmp_info,0,sizeof(bmp_info));
+ 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)
Full color BMP raster.
*/
bmp_info.number_colors=0;
- 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);
+ 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;
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;
/*
Convert MIFF to BMP raster pixels.
*/
- pixel_info=AcquireVirtualMemory((size_t) bmp_info.image_size,
- sizeof(*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) ResetMagickMemory(pixels,0,(size_t) bmp_info.image_size);
+ (void) memset(pixels,0,(size_t) bmp_info.image_size);
switch (bmp_info.bits_per_pixel)
{
case 1:
}
case 4:
{
- size_t
+ unsigned int
byte,
nibble;
for (x=0; x < (ssize_t) image->columns; x++)
{
byte<<=4;
- byte|=((size_t) GetPixelIndex(image,p) & 0x0f);
+ byte|=((unsigned int) GetPixelIndex(image,p) & 0x0f);
nibble++;
if (nibble == 2)
{
}
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:
{
/*
Write 12-byte version 2 bitmap header.
*/
(void) WriteBlobLSBLong(image,bmp_info.size);
- (void) WriteBlobLSBShort(image,(unsigned short) bmp_info.width);
- (void) WriteBlobLSBShort(image,(unsigned short) bmp_info.height);
+ (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);
}
Write 40-byte version 3+ bitmap header.
*/
(void) WriteBlobLSBLong(image,bmp_info.size);
- (void) WriteBlobLSBLong(image,(unsigned int) bmp_info.width);
- (void) WriteBlobLSBLong(image,(unsigned int) bmp_info.height);
+ (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);
/*
Write the rest of the 108-byte BMP Version 4 header.
*/
- (void) WriteBlobLSBLong(image,0x00ff0000U); /* Red mask */
- (void) WriteBlobLSBLong(image,0x0000ff00U); /* Green mask */
- (void) WriteBlobLSBLong(image,0x000000ffU); /* Blue mask */
- (void) WriteBlobLSBLong(image,0xff000000U); /* Alpha mask */
+ (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);
(void) WriteBlobLSBLong(image,0x73524742U); /* sRGB */
(void) WriteBlobLSBLong(image,(unsigned int)
(image->chromaticity.red_primary.x*0x40000000));
if (GetNextImageInList(image) == (Image *) NULL)
break;
image=SyncNextImageInList(image);
- status=SetImageProgress(image,SaveImagesTag,scene++,
- GetImageListLength(image));
+ status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
if (status == MagickFalse)
break;
} while (image_info->adjoin != MagickFalse);