% Read/Write Microsoft Windows Bitmap Image Format %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% Glenn Randers-Pehrson %
% December 2001 %
% %
% %
-% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2015 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 %
#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"
#define BI_JPEG 4
#undef BI_PNG
#define BI_PNG 5
-#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
+#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__) || defined(__MINGW64__)
#undef BI_RGB
#define BI_RGB 0
#undef BI_RLE8
% the decoding process.
%
*/
-
-static inline ssize_t MagickAbsoluteValue(const ssize_t x)
-{
- if (x < 0)
- return(-x);
- return(x);
-}
-
-static inline size_t MagickMax(const size_t x,const size_t y)
-{
- if (x > y)
- return(x);
- return(y);
-}
-
-static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
-{
- if (x < y)
- return(x);
- return(y);
-}
-
static MagickBooleanType DecodeImage(Image *image,const size_t compression,
unsigned char *pixels)
{
q=pixels+(size_t) image->columns*image->rows;
for (y=0; y < (ssize_t) image->rows; )
{
- if ((p < pixels) || (p >= q))
+ MagickBooleanType
+ status;
+
+ if ((p < pixels) || (p > q))
break;
count=ReadBlobByte(image);
if (count == EOF)
/*
Encoded mode.
*/
- count=MagickMin(count,(int) (q-p));
+ count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p));
byte=(unsigned char) ReadBlobByte(image);
if (compression == BI_RLE8)
{
- for (i=0; i < count; i++)
+ for (i=0; i < (ssize_t) count; i++)
*p++=(unsigned char) byte;
}
else
{
- for (i=0; i < count; i++)
+ for (i=0; i < (ssize_t) count; i++)
*p++=(unsigned char)
((i & 0x01) != 0 ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
}
Escape mode.
*/
count=ReadBlobByte(image);
+ if (count == EOF)
+ break;
if (count == 0x01)
return(MagickTrue);
switch (count)
/*
Absolute mode.
*/
- count=MagickMin(count,(int) (q-p));
+ count=(int) MagickMin((ssize_t) count,(ssize_t) (q-p));
if (compression == BI_RLE8)
- for (i=0; i < count; i++)
+ for (i=0; i < (ssize_t) count; i++)
*p++=(unsigned char) ReadBlobByte(image);
else
- for (i=0; i < count; i++)
+ for (i=0; i < (ssize_t) count; i++)
{
if ((i & 0x01) == 0)
byte=(unsigned char) ReadBlobByte(image);
}
}
}
- if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
+ status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
+ image->rows);
+ if (status == MagickFalse)
break;
}
(void) ReadBlobByte(image); /* end of line */
(void) ReadBlobByte(image);
- return(MagickTrue);
+ return(y < (ssize_t) image->rows ? MagickFalse : MagickTrue);
}
\f
/*
offset,
start_position;
+ MemoryInfo
+ *pixel_info;
+
Quantum
index;
bytes_per_line,
green,
length,
- opacity,
red;
ssize_t
bmp_info.ba_offset=0;
start_position=0;
count=ReadBlob(image,2,magick);
+ if (count != 2)
+ ThrowReaderException(CorruptImageError,"ImproperImageHeader");
do
{
PixelInfo
if (image->debug != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule()," Magick: %c%c",
magick[0],magick[1]);
- if ((count == 0) || ((LocaleNCompare((char *) magick,"BM",2) != 0) &&
+ if ((count != 2) || ((LocaleNCompare((char *) magick,"BM",2) != 0) &&
(LocaleNCompare((char *) magick,"CI",2) != 0)))
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
bmp_info.file_size=ReadBlobLSBLong(image);
/*
OS/2 BMP image file.
*/
- bmp_info.width=(short) ReadBlobLSBShort(image);
- bmp_info.height=(short) ReadBlobLSBShort(image);
+ (void) CopyMagickString(image->magick,"BMP2",MaxTextExtent);
+ 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;
*/
if (bmp_info.size < 40)
ThrowReaderException(CorruptImageError,"NonOS2HeaderSizeError");
- bmp_info.width=(int) ReadBlobLSBLong(image);
- bmp_info.height=(int) ReadBlobLSBLong(image);
+ bmp_info.width=(ssize_t) ((int) ReadBlobLSBLong(image));
+ bmp_info.height=(ssize_t) ((int) ReadBlobLSBLong(image));
bmp_info.planes=ReadBlobLSBShort(image);
bmp_info.bits_per_pixel=ReadBlobLSBShort(image);
bmp_info.compression=ReadBlobLSBLong(image);
bmp_info.blue_mask=ReadBlobLSBLong(image);
if (bmp_info.size > 40)
{
+
double
sum;
/*
Decode 2^30 fixed point formatted CIE primaries.
*/
- bmp_info.red_primary.x=(double) ReadBlobLSBLong(image)/0x3ffffff;
- bmp_info.red_primary.y=(double) ReadBlobLSBLong(image)/0x3ffffff;
- bmp_info.red_primary.z=(double) ReadBlobLSBLong(image)/0x3ffffff;
- bmp_info.green_primary.x=(double) ReadBlobLSBLong(image)/0x3ffffff;
- bmp_info.green_primary.y=(double) ReadBlobLSBLong(image)/0x3ffffff;
- bmp_info.green_primary.z=(double) ReadBlobLSBLong(image)/0x3ffffff;
- bmp_info.blue_primary.x=(double) ReadBlobLSBLong(image)/0x3ffffff;
- bmp_info.blue_primary.y=(double) ReadBlobLSBLong(image)/0x3ffffff;
- bmp_info.blue_primary.z=(double) ReadBlobLSBLong(image)/0x3ffffff;
+# 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;
+
sum=bmp_info.red_primary.x+bmp_info.red_primary.y+
bmp_info.red_primary.z;
- image->chromaticity.red_primary.x/=sum;
- image->chromaticity.red_primary.y/=sum;
+ bmp_info.red_primary.x/=sum;
+ bmp_info.red_primary.y/=sum;
+ 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+
bmp_info.green_primary.z;
- image->chromaticity.green_primary.x/=sum;
- image->chromaticity.green_primary.y/=sum;
+ bmp_info.green_primary.x/=sum;
+ bmp_info.green_primary.y/=sum;
+ 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+
bmp_info.blue_primary.z;
- image->chromaticity.blue_primary.x/=sum;
- image->chromaticity.blue_primary.y/=sum;
+ bmp_info.blue_primary.x/=sum;
+ bmp_info.blue_primary.y/=sum;
+ 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)/0xffff;
- bmp_info.gamma_scale.y=(double) ReadBlobLSBLong(image)/0xffff;
- bmp_info.gamma_scale.z=(double) ReadBlobLSBLong(image)/0xffff;
+ 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",MaxTextExtent);
+
if (bmp_info.size > 108)
{
size_t
(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,"UnrecognizedBitsPerPixel");
- if (bmp_info.number_colors > (1U << bmp_info.bits_per_pixel))
- {
- if (bmp_info.bits_per_pixel < 24)
- ThrowReaderException(CorruptImageError,"UnrecognizedNumberOfColors");
- bmp_info.number_colors=0;
- }
+ if (bmp_info.bits_per_pixel < 16 &&
+ bmp_info.number_colors > (1U << bmp_info.bits_per_pixel))
+ ThrowReaderException(CorruptImageError,"UnrecognizedNumberOfColors");
if ((bmp_info.compression == 1) && (bmp_info.bits_per_pixel != 8))
ThrowReaderException(CorruptImageError,"UnrecognizedBitsPerPixel");
if ((bmp_info.compression == 2) && (bmp_info.bits_per_pixel != 4))
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;
- if ((bmp_info.bits_per_pixel == 16) || (bmp_info.bits_per_pixel == 32))
- image->matte=bmp_info.alpha_mask != 0 ? MagickTrue : MagickFalse;
- if ((bmp_info.number_colors != 0) || (bmp_info.bits_per_pixel < 16))
+ 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;
p=bmp_colormap;
for (i=0; i < (ssize_t) image->colors; i++)
{
- image->colormap[i].blue=ScaleCharToQuantum(*p++);
- image->colormap[i].green=ScaleCharToQuantum(*p++);
- image->colormap[i].red=ScaleCharToQuantum(*p++);
+ 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++;
}
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.
*/
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;
- pixels=(unsigned char *) AcquireQuantumMemory((size_t) image->rows,
+ pixel_info=AcquireVirtualMemory((size_t) image->rows,
MagickMax(bytes_per_line,image->columns+256UL)*sizeof(*pixels));
- if (pixels == (unsigned char *) NULL)
+ if (pixel_info == (MemoryInfo *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+ pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
if ((bmp_info.compression == BI_RGB) ||
(bmp_info.compression == BI_BITFIELDS))
{
count=ReadBlob(image,length,pixels);
if (count != (ssize_t) length)
{
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
ThrowReaderException(CorruptImageError,
"InsufficientImageDataInFile");
}
status=DecodeImage(image,bmp_info.compression,pixels);
if (status == MagickFalse)
{
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
ThrowReaderException(CorruptImageError,
"UnableToRunlengthDecodeImage");
}
*/
if (bmp_info.compression == BI_RGB)
{
- bmp_info.alpha_mask=0;
+ /*
+ 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;
bmp_info.blue_mask=0x0000001fU;
}
}
+ (void) ResetMagickMemory(&shift,0,sizeof(shift));
+ (void) ResetMagickMemory(&quantum_bits,0,sizeof(quantum_bits));
if ((bmp_info.bits_per_pixel == 16) || (bmp_info.bits_per_pixel == 32))
{
register size_t
/*
Get shift and quantum bits info from bitfield masks.
*/
- (void) ResetMagickMemory(&shift,0,sizeof(shift));
- (void) ResetMagickMemory(&quantum_bits,0,sizeof(quantum_bits));
if (bmp_info.red_mask != 0)
while (((bmp_info.red_mask << shift.red) & 0x80000000UL) == 0)
shift.red++;
sample=shift.red;
while (((bmp_info.red_mask << sample) & 0x80000000UL) != 0)
sample++;
- quantum_bits.red=(Quantum) (sample-shift.red);
+ quantum_bits.red=(MagickRealType) (sample-shift.red);
sample=shift.green;
while (((bmp_info.green_mask << sample) & 0x80000000UL) != 0)
sample++;
- quantum_bits.green=(Quantum) (sample-shift.green);
+ quantum_bits.green=(MagickRealType) (sample-shift.green);
sample=shift.blue;
while (((bmp_info.blue_mask << sample) & 0x80000000UL) != 0)
sample++;
- quantum_bits.blue=(Quantum) (sample-shift.blue);
+ quantum_bits.blue=(MagickRealType) (sample-shift.blue);
sample=shift.alpha;
while (((bmp_info.alpha_mask << sample) & 0x80000000UL) != 0)
sample++;
- quantum_bits.alpha=(Quantum) (sample-shift.alpha);
+ quantum_bits.alpha=(MagickRealType) (sample-shift.alpha);
}
switch (bmp_info.bits_per_pixel)
{
break;
if (image->previous == (Image *) NULL)
{
- status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
- image->rows);
+ status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
+ (image->rows-y),image->rows);
if (status == MagickFalse)
break;
}
break;
for (x=0; x < ((ssize_t) image->columns-1); x+=2)
{
- index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
+ if (IsValidColormapIndex(image,(*p >> 4) & 0x0f,&index,exception)
+ == MagickFalse)
+ break;
SetPixelIndex(image,index,q);
q+=GetPixelChannels(image);
- index=ConstrainColormapIndex(image,*p & 0x0f,exception);
+ if (IsValidColormapIndex(image,*p & 0x0f,&index,exception) ==
+ MagickFalse)
+ break;
SetPixelIndex(image,index,q);
q+=GetPixelChannels(image);
p++;
}
if ((image->columns % 2) != 0)
{
- index=ConstrainColormapIndex(image,(*p >> 4) & 0xf,exception);
+ if (IsValidColormapIndex(image,(*p >> 4) & 0xf,&index,exception)
+ == MagickFalse)
+ break;
SetPixelIndex(image,index,q);
q+=GetPixelChannels(image);
p++;
}
+ if (x < image->columns)
+ break;
if (SyncAuthenticPixels(image,exception) == MagickFalse)
break;
if (image->previous == (Image *) NULL)
{
- status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
- image->rows);
+ status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
+ (image->rows-y),image->rows);
if (status == MagickFalse)
break;
}
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
- for (x = (ssize_t)image->columns; x != 0; --x)
+ for (x=(ssize_t) image->columns; x != 0; --x)
{
- index=ConstrainColormapIndex(image,*p++,exception);
+ if (IsValidColormapIndex(image,*p++,&index,exception) ==
+ MagickFalse)
+ break;
SetPixelIndex(image,index,q);
q+=GetPixelChannels(image);
}
+ if (x > 0)
+ break;
if (SyncAuthenticPixels(image,exception) == MagickFalse)
break;
offset=(MagickOffsetType) (image->rows-y-1);
if (image->previous == (Image *) NULL)
{
- status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
- image->rows);
+ status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
+ (image->rows-y),image->rows);
if (status == MagickFalse)
break;
}
case 16:
{
size_t
+ alpha,
pixel;
/*
if (bmp_info.compression != BI_RGB &&
bmp_info.compression != BI_BITFIELDS)
{
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
ThrowReaderException(CorruptImageError,
"UnrecognizedImageCompression");
}
blue|=((blue & 0xe000) >> 5);
if (quantum_bits.blue <= 8)
blue|=((blue & 0xff00) >> 8);
- opacity=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16;
- if (quantum_bits.alpha <= 8)
- opacity|=((opacity & 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->matte != MagickFalse)
- SetPixelAlpha(image,
- ScaleShortToQuantum((unsigned short) opacity),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)
offset=(MagickOffsetType) (image->rows-y-1);
if (image->previous == (Image *) NULL)
{
- status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
- image->rows);
+ status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
+ (image->rows-y),image->rows);
if (status == MagickFalse)
break;
}
offset=(MagickOffsetType) (image->rows-y-1);
if (image->previous == (Image *) NULL)
{
- status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
- image->rows);
+ status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
+ (image->rows-y),image->rows);
if (status == MagickFalse)
break;
}
if ((bmp_info.compression != BI_RGB) &&
(bmp_info.compression != BI_BITFIELDS))
{
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
ThrowReaderException(CorruptImageError,
"UnrecognizedImageCompression");
}
for (y=(ssize_t) image->rows-1; y >= 0; y--)
{
size_t
+ alpha,
pixel;
p=pixels+(image->rows-y-1)*bytes_per_line;
for (x=0; x < (ssize_t) image->columns; x++)
{
pixel=(size_t) (*p++);
- pixel|=(*p++ << 8);
- pixel|=(*p++ << 16);
- pixel|=(*p++ << 24);
+ pixel|=((size_t) *p++ << 8);
+ pixel|=((size_t) *p++ << 16);
+ pixel|=((size_t) *p++ << 24);
red=((pixel & bmp_info.red_mask) << shift.red) >> 16;
if (quantum_bits.red == 8)
red|=(red >> 8);
blue=((pixel & bmp_info.blue_mask) << shift.blue) >> 16;
if (quantum_bits.blue == 8)
blue|=(blue >> 8);
- opacity=((pixel & bmp_info.alpha_mask) << shift.alpha) >> 16;
- if (quantum_bits.alpha == 8)
- opacity|=(opacity >> 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->matte != MagickFalse)
- SetPixelAlpha(image,
- ScaleShortToQuantum((unsigned short) opacity),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)
offset=(MagickOffsetType) (image->rows-y-1);
if (image->previous == (Image *) NULL)
{
- status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
- image->rows);
+ status=SetImageProgress(image,LoadImageTag,(MagickOffsetType)
+ (image->rows-y),image->rows);
if (status == MagickFalse)
break;
}
}
default:
{
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
}
}
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
+ if (y > 0)
+ break;
if (EOFBlob(image) != MagickFalse)
{
ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
entry->magick=(IsImageFormatHandler *) IsBMP;
entry->description=ConstantString("Microsoft Windows bitmap image");
entry->module=ConstantString("BMP");
- entry->adjoin=MagickFalse;
- entry->seekable_stream=MagickTrue;
+ entry->flags^=CoderAdjoinFlag;
+ entry->flags|=CoderSeekableStreamFlag;
(void) RegisterMagickInfo(entry);
entry=SetMagickInfo("BMP2");
entry->encoder=(EncodeImageHandler *) WriteBMPImage;
entry->magick=(IsImageFormatHandler *) IsBMP;
entry->description=ConstantString("Microsoft Windows bitmap image (V2)");
entry->module=ConstantString("BMP");
- entry->adjoin=MagickFalse;
- entry->seekable_stream=MagickTrue;
+ entry->flags^=CoderAdjoinFlag;
+ entry->flags|=CoderSeekableStreamFlag;
(void) RegisterMagickInfo(entry);
entry=SetMagickInfo("BMP3");
entry->encoder=(EncodeImageHandler *) WriteBMPImage;
entry->magick=(IsImageFormatHandler *) IsBMP;
entry->description=ConstantString("Microsoft Windows bitmap image (V3)");
entry->module=ConstantString("BMP");
- entry->adjoin=MagickFalse;
- entry->seekable_stream=MagickTrue;
+ entry->flags^=CoderAdjoinFlag;
+ entry->flags|=CoderSeekableStreamFlag;
(void) RegisterMagickInfo(entry);
return(MagickImageCoderSignature);
}
{
BMPInfo
bmp_info;
+ const char
+ *value;
+
const StringInfo
*profile;
MagickOffsetType
scene;
+ MemoryInfo
+ *pixel_info;
+
register const Quantum
*p;
else
if (LocaleCompare(image_info->magick,"BMP3") == 0)
type=3;
+
+ value=GetImageOption(image_info,"bmp:format");
+
+ if (value != (char *) NULL)
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Format=%s",value);
+
+ if (LocaleCompare(value,"bmp2") == 0)
+ type=2;
+ if (LocaleCompare(value,"bmp3") == 0)
+ type=3;
+ if (LocaleCompare(value,"bmp4") == 0)
+ type=4;
+ }
+
scene=0;
do
{
/*
Initialize BMP raster file header.
*/
- if (IssRGBColorspace(image->colorspace) == MagickFalse)
- (void) TransformImageColorspace(image,sRGBColorspace,exception);
+ (void) TransformImageColorspace(image,sRGBColorspace,exception);
(void) ResetMagickMemory(&bmp_info,0,sizeof(bmp_info));
bmp_info.file_size=14+12;
if (type > 2)
if (image_info->compression == RLECompression)
bmp_info.bits_per_pixel=8;
bmp_info.number_colors=1U << bmp_info.bits_per_pixel;
- if (image->matte != MagickFalse)
+ if (image->alpha_trait != UndefinedPixelTrait)
(void) SetImageStorageClass(image,DirectClass,exception);
else
if ((size_t) bmp_info.number_colors < image->colors)
*/
bmp_info.number_colors=0;
bmp_info.bits_per_pixel=(unsigned short)
- ((type > 3) && (image->matte != MagickFalse) ? 32 : 24);
+ ((type > 3) && (image->alpha_trait != UndefinedPixelTrait) ? 32 : 24);
bmp_info.compression=(unsigned int) ((type > 3) &&
- (image->matte != MagickFalse) ? BI_BITFIELDS : BI_RGB);
+ (image->alpha_trait != UndefinedPixelTrait) ? BI_BITFIELDS : BI_RGB);
}
bytes_per_line=4*((image->columns*bmp_info.bits_per_pixel+31)/32);
bmp_info.ba_offset=0;
if (type == 2)
bmp_info.size=12;
else
- if ((type == 3) || ((image->matte == MagickFalse) &&
+ if ((type == 3) || ((image->alpha_trait == UndefinedPixelTrait) &&
(have_color_info == MagickFalse)))
{
type=3;
/*
Convert MIFF to BMP raster pixels.
*/
- pixels=(unsigned char *) AcquireQuantumMemory((size_t) bmp_info.image_size,
+ pixel_info=AcquireVirtualMemory((size_t) bmp_info.image_size,
sizeof(*pixels));
- if (pixels == (unsigned char *) NULL)
+ if (pixel_info == (MemoryInfo *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+ pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
(void) ResetMagickMemory(pixels,0,(size_t) bmp_info.image_size);
switch (bmp_info.bits_per_pixel)
{
{
size_t
byte,
- nibble,
+ nibble;
+
+ ssize_t
offset;
/*
if ((type > 2) && (bmp_info.bits_per_pixel == 8))
if (image_info->compression != NoCompression)
{
- size_t
- length;
+ MemoryInfo
+ *rle_info;
/*
Convert run-length encoded raster pixels.
*/
- length=(size_t) (2*(bytes_per_line+2)*(image->rows+2)+2);
- bmp_data=(unsigned char *) NULL;
- if (~length >= bytes_per_line)
- bmp_data=(unsigned char *) AcquireQuantumMemory(length+
- bytes_per_line,sizeof(*bmp_data));
- if (bmp_data == (unsigned char *) NULL)
+ rle_info=AcquireVirtualMemory((size_t) (2*(bytes_per_line+2)+2),
+ (image->rows+2)*sizeof(*pixels));
+ if (rle_info == (MemoryInfo *) NULL)
{
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ 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;
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
+ pixel_info=rle_info;
pixels=bmp_data;
bmp_info.compression=BI_RLE8;
}
" Storage class=PseudoClass");
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Image depth=%.20g",(double) image->depth);
- if (image->matte != MagickFalse)
+ if (image->alpha_trait != UndefinedPixelTrait)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Matte=True");
else
(void) WriteBlobLSBLong(image,bmp_info.number_colors);
(void) WriteBlobLSBLong(image,bmp_info.colors_important);
}
- if ((type > 3) && ((image->matte != MagickFalse) ||
+ if ((type > 3) && ((image->alpha_trait != UndefinedPixelTrait) ||
(have_color_info != MagickFalse)))
{
/*
(void) WriteBlobLSBLong(image,0x0000ff00U); /* Green mask */
(void) WriteBlobLSBLong(image,0x000000ffU); /* Blue mask */
(void) WriteBlobLSBLong(image,0xff000000U); /* Alpha mask */
- (void) WriteBlobLSBLong(image,0x00000001U); /* CSType==Calib. RGB */
+ (void) WriteBlobLSBLong(image,0x73524742U); /* sRGB */
(void) WriteBlobLSBLong(image,(unsigned int)
- image->chromaticity.red_primary.x*0x3ffffff);
+ (image->chromaticity.red_primary.x*0x40000000));
(void) WriteBlobLSBLong(image,(unsigned int)
- image->chromaticity.red_primary.y*0x3ffffff);
+ (image->chromaticity.red_primary.y*0x40000000));
(void) WriteBlobLSBLong(image,(unsigned int)
- (1.000f-(image->chromaticity.red_primary.x+
- image->chromaticity.red_primary.y)*0x3ffffff));
+ ((1.000f-(image->chromaticity.red_primary.x+
+ image->chromaticity.red_primary.y))*0x40000000));
(void) WriteBlobLSBLong(image,(unsigned int)
- image->chromaticity.green_primary.x*0x3ffffff);
+ (image->chromaticity.green_primary.x*0x40000000));
(void) WriteBlobLSBLong(image,(unsigned int)
- image->chromaticity.green_primary.y*0x3ffffff);
+ (image->chromaticity.green_primary.y*0x40000000));
(void) WriteBlobLSBLong(image,(unsigned int)
- (1.000f-(image->chromaticity.green_primary.x+
- image->chromaticity.green_primary.y)*0x3ffffff));
+ ((1.000f-(image->chromaticity.green_primary.x+
+ image->chromaticity.green_primary.y))*0x40000000));
(void) WriteBlobLSBLong(image,(unsigned int)
- image->chromaticity.blue_primary.x*0x3ffffff);
+ (image->chromaticity.blue_primary.x*0x40000000));
(void) WriteBlobLSBLong(image,(unsigned int)
- image->chromaticity.blue_primary.y*0x3ffffff);
+ (image->chromaticity.blue_primary.y*0x40000000));
(void) WriteBlobLSBLong(image,(unsigned int)
- (1.000f-(image->chromaticity.blue_primary.x+
- image->chromaticity.blue_primary.y)*0x3ffffff));
+ ((1.000f-(image->chromaticity.blue_primary.x+
+ image->chromaticity.blue_primary.y))*0x40000000));
(void) WriteBlobLSBLong(image,(unsigned int)
- bmp_info.gamma_scale.x*0xffff);
+ (bmp_info.gamma_scale.x*0x10000));
(void) WriteBlobLSBLong(image,(unsigned int)
- bmp_info.gamma_scale.y*0xffff);
+ (bmp_info.gamma_scale.y*0x10000));
(void) WriteBlobLSBLong(image,(unsigned int)
- bmp_info.gamma_scale.z*0xffff);
+ (bmp_info.gamma_scale.z*0x10000));
if ((image->rendering_intent != UndefinedIntent) ||
(profile != (StringInfo *) NULL))
{
q=bmp_colormap;
for (i=0; i < (ssize_t) MagickMin((ssize_t) image->colors,(ssize_t) bmp_info.number_colors); i++)
{
- *q++=ScaleQuantumToChar(image->colormap[i].blue);
- *q++=ScaleQuantumToChar(image->colormap[i].green);
- *q++=ScaleQuantumToChar(image->colormap[i].red);
+ *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;
}
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Pixels: %u bytes",bmp_info.image_size);
(void) WriteBlob(image,(size_t) bmp_info.image_size,pixels);
- pixels=(unsigned char *) RelinquishMagickMemory(pixels);
+ pixel_info=RelinquishVirtualMemory(pixel_info);
if (GetNextImageInList(image) == (Image *) NULL)
break;
image=SyncNextImageInList(image);