reimplemented wxBitmap::ConvertToImage() using wxDIB
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28393 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -810,6 +810,7 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc)
|
|||||||
|
|
||||||
wxImage wxBitmap::ConvertToImage() const
|
wxImage wxBitmap::ConvertToImage() const
|
||||||
{
|
{
|
||||||
|
// convert DDB to DIB
|
||||||
wxDIB dib(*this);
|
wxDIB dib(*this);
|
||||||
|
|
||||||
if ( !dib.IsOk() )
|
if ( !dib.IsOk() )
|
||||||
@@ -817,122 +818,75 @@ wxImage wxBitmap::ConvertToImage() const
|
|||||||
return wxNullImage;
|
return wxNullImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// and then DIB to our wxImage
|
||||||
wxImage image = dib.ConvertToImage();
|
wxImage image = dib.ConvertToImage();
|
||||||
if ( !image.Ok() )
|
if ( !image.Ok() )
|
||||||
{
|
{
|
||||||
return wxNullImage;
|
return wxNullImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set mask
|
// now do the same for the mask, if we have any
|
||||||
|
HBITMAP hbmpMask = GetMask() ? (HBITMAP) GetMask()->GetMaskBitmap() : NULL;
|
||||||
// TODO: WinCE mask-copying support and use wxDIB
|
if ( hbmpMask )
|
||||||
#ifndef __WXWINCE__
|
|
||||||
|
|
||||||
if( GetMask() && GetMask()->GetMaskBitmap() )
|
|
||||||
{
|
{
|
||||||
static const int MASK_RED = 1;
|
wxDIB dibMask(hbmpMask);
|
||||||
static const int MASK_GREEN = 2;
|
if ( dibMask.IsOk() )
|
||||||
static const int MASK_BLUE = 3;
|
|
||||||
static const int MASK_BLUE_REPLACEMENT = 2;
|
|
||||||
|
|
||||||
HBITMAP hbitmap = (HBITMAP) GetMask()->GetMaskBitmap();
|
|
||||||
int width = GetWidth();
|
|
||||||
int height = GetHeight();
|
|
||||||
|
|
||||||
int bytesPerLine = width*3;
|
|
||||||
int sizeDWORD = sizeof( DWORD );
|
|
||||||
int lineBoundary = bytesPerLine % sizeDWORD;
|
|
||||||
int padding = 0;
|
|
||||||
if( lineBoundary > 0 )
|
|
||||||
{
|
{
|
||||||
padding = sizeDWORD - lineBoundary;
|
// TODO: use wxRawBitmap to iterate over DIB
|
||||||
bytesPerLine += padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a DIB header
|
// we hard code the mask colour for now but we could also make an
|
||||||
int headersize = sizeof(BITMAPINFOHEADER);
|
// effort (and waste time) to choose a colour not present in the
|
||||||
BITMAPINFO *lpDIBh = (BITMAPINFO *) malloc( headersize );
|
// image already to avoid having to fudge the pixels below --
|
||||||
if( !lpDIBh )
|
// whether it's worth to do it is unclear however
|
||||||
{
|
static const int MASK_RED = 1;
|
||||||
wxFAIL_MSG( wxT("could not allocate data for DIB header") );
|
static const int MASK_GREEN = 2;
|
||||||
//free( data );
|
static const int MASK_BLUE = 3;
|
||||||
return wxNullImage;
|
static const int MASK_BLUE_REPLACEMENT = 2;
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in the DIB header
|
const int h = dibMask.GetHeight();
|
||||||
lpDIBh->bmiHeader.biSize = headersize;
|
const int w = dibMask.GetWidth();
|
||||||
lpDIBh->bmiHeader.biWidth = width;
|
const int bpp = dibMask.GetDepth();
|
||||||
lpDIBh->bmiHeader.biHeight = -height;
|
const int maskBytesPerPixel = bpp >> 3;
|
||||||
lpDIBh->bmiHeader.biSizeImage = bytesPerLine * height;
|
const int maskBytesPerLine = wxDIB::GetLineSize(w, bpp);
|
||||||
lpDIBh->bmiHeader.biPlanes = 1;
|
unsigned char *data = image.GetData();
|
||||||
lpDIBh->bmiHeader.biBitCount = 24;
|
|
||||||
lpDIBh->bmiHeader.biCompression = BI_RGB;
|
|
||||||
lpDIBh->bmiHeader.biClrUsed = 0;
|
|
||||||
// These seem not really needed for our purpose here.
|
|
||||||
lpDIBh->bmiHeader.biClrImportant = 0;
|
|
||||||
lpDIBh->bmiHeader.biXPelsPerMeter = 0;
|
|
||||||
lpDIBh->bmiHeader.biYPelsPerMeter = 0;
|
|
||||||
|
|
||||||
// memory DC created, color set, data copied, and memory DC deleted
|
// remember that DIBs are stored in bottom to top order
|
||||||
|
unsigned char *
|
||||||
|
maskLineStart = dibMask.GetData() + ((h - 1) * maskBytesPerLine);
|
||||||
|
|
||||||
// memory for DIB data
|
for ( int y = 0; y < h; y++, maskLineStart -= maskBytesPerLine )
|
||||||
unsigned char *lpBits
|
|
||||||
= (unsigned char *) malloc( lpDIBh->bmiHeader.biSizeImage );
|
|
||||||
if( !lpBits )
|
|
||||||
{
|
|
||||||
wxFAIL_MSG( wxT("could not allocate data for DIB") );
|
|
||||||
free( lpDIBh );
|
|
||||||
return wxNullImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HDC hdc = ::GetDC(NULL);
|
|
||||||
|
|
||||||
HDC memdc = ::CreateCompatibleDC( hdc );
|
|
||||||
::SetTextColor( memdc, RGB( 0, 0, 0 ) );
|
|
||||||
::SetBkColor( memdc, RGB( 255, 255, 255 ) );
|
|
||||||
::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
|
|
||||||
::DeleteDC( memdc );
|
|
||||||
unsigned char *ptdata = image.GetData();//data;
|
|
||||||
unsigned char *ptbits = lpBits;
|
|
||||||
int i, j;
|
|
||||||
for( i=0; i<height; i++ )
|
|
||||||
{
|
|
||||||
for( j=0; j<width; j++ )
|
|
||||||
{
|
{
|
||||||
// is this pixel transparent?
|
// traverse one mask DIB line
|
||||||
if ( *ptbits != 0 )
|
unsigned char *mask = maskLineStart;
|
||||||
|
for ( int x = 0; x < w; x++, mask += maskBytesPerPixel )
|
||||||
{
|
{
|
||||||
if ( (ptdata[0] == MASK_RED) &&
|
// should this pixel be transparent?
|
||||||
(ptdata[1] == MASK_GREEN) &&
|
if ( *mask )
|
||||||
(ptdata[2] == MASK_BLUE) )
|
|
||||||
{
|
{
|
||||||
// we have to fudge the colour a bit to prevent this
|
// no, check that it isn't transparent by accident
|
||||||
// pixel from appearing transparent
|
if ( (data[0] == MASK_RED) &&
|
||||||
ptdata[2] = MASK_BLUE_REPLACEMENT;
|
(data[1] == MASK_GREEN) &&
|
||||||
|
(data[2] == MASK_BLUE) )
|
||||||
|
{
|
||||||
|
// we have to fudge the colour a bit to prevent
|
||||||
|
// this pixel from appearing transparent
|
||||||
|
data[2] = MASK_BLUE_REPLACEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
data += 3;
|
||||||
|
}
|
||||||
|
else // yes, transparent pixel
|
||||||
|
{
|
||||||
|
*data++ = MASK_RED;
|
||||||
|
*data++ = MASK_GREEN;
|
||||||
|
*data++ = MASK_BLUE;
|
||||||
}
|
}
|
||||||
ptdata += 3;
|
|
||||||
}
|
}
|
||||||
else // masked pixel
|
|
||||||
{
|
|
||||||
*(ptdata++) = MASK_RED;
|
|
||||||
*(ptdata++) = MASK_GREEN;
|
|
||||||
*(ptdata++) = MASK_BLUE;
|
|
||||||
}
|
|
||||||
ptbits += 3;
|
|
||||||
}
|
}
|
||||||
ptbits += padding;
|
|
||||||
|
image.SetMaskColour(MASK_RED, MASK_GREEN, MASK_BLUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
image.SetMaskColour( MASK_RED, MASK_GREEN, MASK_BLUE );
|
|
||||||
image.SetMask( true );
|
|
||||||
|
|
||||||
// free allocated resources
|
|
||||||
::ReleaseDC(NULL, hdc);
|
|
||||||
free(lpDIBh);
|
|
||||||
free(lpBits);
|
|
||||||
}
|
}
|
||||||
#endif // __WXWINCE__
|
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user