简体   繁体   English

Direct2D - 模拟颜色键控透明位图

[英]Direct2D - Emulating Color Keyed Transparent Bitmaps

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. 我目前正在更新Windows GDI应用程序以使用Direct2D渲染,我需要通过颜色键控支持“透明”位图以实现向后兼容性。

Right now I'm working with a HWND render target and a converted WIC bitmap source (to GUID_WICPixelFormat32bppPBGRA). 现在我正在使用HWND渲染目标和转换后的WIC位图源(到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. 到目前为止,我的计划是从转换后的位图Lock()创建一个IWICBitmap,然后处理每个像素,如果它与颜色键匹配,则将其alpha值设置为0。

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;

If you only need to "process" the bitmap to render it, then the fastest is always GPU. 如果您只需要“处理”位图来渲染它,那么最快的就是GPU。 In Direct2D there are effects (ID2D1Effect) for simple bitmap processing. 在Direct2D中,有简单位图处理的效果 (ID2D1Effect)。 You can write your own [it seems comparatively complicated], or use one of the built-in effects [which is rather simple]. 可以编写自己的[看起来比较复杂],或使用其中一种内置效果 [相当简单]。 There is one called chroma-key (CLSID_D2D1ChromaKey) . 有一个称为色度键(CLSID_D2D1ChromaKey)

On the other hand, if you need to do further processing on CPU, it gets more complex. 另一方面,如果您需要在CPU上进行进一步处理,则会变得更加复杂。 You might be better off optimizing the code you have. 您可能最好优化您拥有的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM