I'm currently updating a Windows GDI application to use Direct2D rendering and I need to support "transparent" bitmaps via color-keying for backwards compatibility.
Right now I'm working with a HWND render target and a converted WIC bitmap source (to GUID_WICPixelFormat32bppPBGRA). My plan so far is to create a IWICBitmap from the converted bitmap, Lock() it, and then process each pixel setting it's alpha value to 0 if it matches the color key.
This seems a bit "brute force" - Is this the best method of approaching this or is there a better way?
Edit: In the interests of completeness here's an extract of what I went with - looks like it's working fine but I'm open to any improvements!
// pConvertedBmp contains a IWICFormatConverter* bitmap with the pixel
// format set to GUID_WICPixelFormat32bppPBGRA
IWICBitmap* pColorKeyedBmp = NULL;
HRESULT hr = S_OK;
UINT uBmpW = 0;
UINT uBmpH = 0;
pConvertedBmp->GetSize( &uBmpW, &uBmpH );
WICRect rcLock = { 0, 0, uBmpW, uBmpH };
// GetWIC() returns the WIC Factory instance in this app
hr = GetWIC()->CreateBitmapFromSource( pConvertedBmp,
WICBitmapCacheOnLoad,
&pColorKeyedBmp );
if ( FAILED( hr ) ) {
return hr;
}
IWICBitmapLock* pBitmapLock = NULL;
hr = pColorKeyedBmp->Lock( &rcLock, WICBitmapLockRead, &pBitmapLock );
if ( FAILED( hr ) ) {
SafeRelease( &pColorKeyedBmp );
return hr;
}
UINT uPixel = 0;
UINT cbBuffer = 0;
UINT cbStride = 0;
BYTE* pPixelBuffer = NULL;
hr = pBitmapLock->GetStride( &cbStride );
if ( SUCCEEDED( hr ) ) {
hr = pBitmapLock->GetDataPointer( &cbBuffer, &pPixelBuffer );
if ( SUCCEEDED( hr ) ) {
// If we haven't got a resolved color key then we need to
// grab the pixel at the specified coordinates and get
// it's RGB
if ( !clrColorKey.IsValidColor() ) {
// This is an internal function to grab the color of a pixel
ResolveColorKey( pPixelBuffer, cbBuffer, cbStride, uBmpW, uBmpH );
}
// Convert the RGB to BGR
UINT uColorKey = (UINT) RGB2BGR( clrColorKey.GetRGB() );
LPBYTE pPixel = pPixelBuffer;
for ( UINT uRow = 0; uRow < uBmpH; uRow++ ) {
pPixel = pPixelBuffer + ( uRow * cbStride );
for ( UINT uCol = 0; uCol < uBmpW; uCol++ ) {
uPixel = *( (LPUINT) pPixel );
if ( ( uPixel & 0x00FFFFFF ) == uColorKey ) {
*( (LPUINT) pPixel ) = 0;
}
pPixel += sizeof( uPixel );
}
}
}
}
pBitmapLock->Release();
if ( FAILED( hr ) ) {
// We still use the original image
SafeRelease( &pColorKeyedBmp );
}
else {
// We use the new image so we release the original
SafeRelease( &pConvertedBmp );
}
return hr;