Direct2D - 模拟色键透明位图

6

我目前正在更新一个使用Windows GDI应用程序,以使用Direct2D渲染,并且需要通过颜色键来支持“透明”位图,以保持向后兼容性。

现在,我正在使用HWND呈现目标和转换后的WIC位图源(到GUID_WICPixelFormat32bppPBGRA)。 我的计划是从转换后的位图中创建一个IWICBitmap,锁定它,然后处理每个像素,如果匹配颜色键,则将其Alpha值设置为0。

这似乎有点“蛮力法”- 这是接近这个问题的最佳方法,还是有更好的方法?

编辑:为了完整起见,这里是我采取的摘录 - 看起来它运行良好,但我欢迎任何改进!

// 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;
1个回答

1

如果您只需要“处理”位图以呈现它,那么最快的方式始终是使用GPU。在Direct2D中,有效果(ID2D1Effect)可以进行简单的位图处理。您可以编写自己的[似乎相对复杂],或者使用其中一个内置效果[比较简单]。其中有一个名为色度键(CLSID_D2D1ChromaKey)

另一方面,如果您需要在CPU上进行进一步的处理,则变得更加复杂。您最好优化已有的代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接