// Created: 03.03.03 (replaces the old file with the same name)
// RCS-ID: $Id$
// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
-// License: wxWidgets licence
+// License: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
/*
{
// only 1, 4 and 8bpp bitmaps use palettes (well, they could be used with
// 24bpp ones too but we don't support this as I think it's quite uncommon)
- return bitsPerPixel <= 8 ? 1 << bitsPerPixel : 0;
+ return (WORD)(bitsPerPixel <= 8 ? 1 << bitsPerPixel : 0);
}
// wrapper around ::GetObject() for DIB sections
info->bmiHeader.biHeight = height;
info->bmiHeader.biPlanes = 1;
- info->bmiHeader.biBitCount = depth;
+ info->bmiHeader.biBitCount = (WORD)depth;
info->bmiHeader.biSizeImage = GetLineSize(width, depth)*height;
m_handle = ::CreateDIBSection
{
wxCHECK_MSG( bmp.Ok(), false, _T("wxDIB::Create(): invalid bitmap") );
+ if ( !Create(GetHbitmapOf(bmp)) )
+ return false;
+
+ m_hasAlpha = bmp.HasAlpha();
+
+ return true;
+}
+
+bool wxDIB::Create(HBITMAP hbmp)
+{
// this bitmap could already be a DIB section in which case we don't need
// to convert it to DIB
- HBITMAP hbmp = GetHbitmapOf(bmp);
-
DIBSECTION ds;
if ( GetDIBSection(hbmp, &ds) )
{
}
else // no, it's a DDB -- convert it to DIB
{
- const int w = bmp.GetWidth();
- const int h = bmp.GetHeight();
- int d = bmp.GetDepth();
+ // prepare all the info we need
+ BITMAP bm;
+ if ( !::GetObject(hbmp, sizeof(bm), &bm) )
+ {
+ wxLogLastError(wxT("GetObject(bitmap)"));
+
+ return false;
+ }
+
+ int d = bm.bmBitsPixel;
if ( d <= 0 )
d = wxDisplayDepth();
- if ( !Create(w, h, d) || !CopyFromDDB(hbmp) )
+ if ( !Create(bm.bmWidth, bm.bmHeight, d) || !CopyFromDDB(hbmp) )
return false;
}
// initialize the palette header
pPalette->palVersion = 0x300; // magic number, not in docs but works
- pPalette->palNumEntries = biClrUsed;
+ pPalette->palNumEntries = (WORD)biClrUsed;
// and the colour table (it starts right after the end of the header)
const RGBQUAD *pRGB = (RGBQUAD *)((char *)&ds.dsBmih + ds.dsBmih.biSize);
// if we have alpha channel, we need to create a 32bpp RGBA DIB, otherwise
// a 24bpp RGB is sufficient
- const bool hasAlpha = image.HasAlpha();
- const int bpp = hasAlpha ? 32 : 24;
+ m_hasAlpha = image.HasAlpha();
+ const int bpp = m_hasAlpha ? 32 : 24;
if ( !Create(w, h, bpp) )
return false;
const int srcBytesPerLine = w * 3;
const int dstBytesPerLine = GetLineSize(w, bpp);
const unsigned char *src = image.GetData() + ((h - 1) * srcBytesPerLine);
- const unsigned char *alpha = hasAlpha ? image.GetAlpha() + (h - 1)*w : NULL;
+ const unsigned char *alpha = m_hasAlpha ? image.GetAlpha() + (h - 1)*w
+ : NULL;
unsigned char *dstLineStart = (unsigned char *)m_data;
for ( int y = 0; y < h; y++ )
{
// copy one DIB line
unsigned char *dst = dstLineStart;
- for ( int x = 0; x < w; x++ )
+ if ( alpha )
{
- // also, the order of RGB is inversed for DIBs
- *dst++ = src[2];
- *dst++ = src[1];
- *dst++ = src[0];
-
- src += 3;
-
- if ( alpha )
- *dst++ = *alpha++;
+ for ( int x = 0; x < w; x++ )
+ {
+ // RGB order is reversed, and we need to premultiply
+ // all channels by alpha value for use with ::AlphaBlend.
+ const unsigned char a = *alpha++;
+ *dst++ = (unsigned char)((src[2] * a + 127) / 255);
+ *dst++ = (unsigned char)((src[1] * a + 127) / 255);
+ *dst++ = (unsigned char)((src[0] * a + 127) / 255);
+ *dst++ = a;
+ src += 3;
+ }
+ }
+ else // no alpha channel
+ {
+ for ( int x = 0; x < w; x++ )
+ {
+ // RGB order is reversed.
+ *dst++ = src[2];
+ *dst++ = src[1];
+ *dst++ = src[0];
+ src += 3;
+ }
}
// pass to the previous line in the image
return wxNullImage;
}
- const int bpp = GetDepth();
- if ( bpp == 32 )
+ if ( m_hasAlpha )
{
image.SetAlpha();
}
// this is the same loop as in Create() just above but with copy direction
// reversed
+ const int bpp = GetDepth();
const int dstBytesPerLine = w * 3;
const int srcBytesPerLine = GetLineSize(w, bpp);
unsigned char *dst = image.GetData() + ((h - 1) * dstBytesPerLine);
unsigned char *alpha = image.HasAlpha() ? image.GetAlpha() + (h - 1)*w
: NULL;
+ const bool is32bit = bpp == 32;
const unsigned char *srcLineStart = (unsigned char *)GetData();
for ( int y = 0; y < h; y++ )
{
dst += 3;
- if ( alpha )
- *alpha++ = *src++;
+ if ( is32bit )
+ {
+ if ( alpha )
+ *alpha++ = *src;
+ src++;
+ }
}
// pass to the previous line in the image