2010-11-24 11 views
3

私はHBITMAPをアルファでストレッチし、それを他のhdcに描画しようとしています。AlphaBlendが「false」を返す理由

私はStretchDIBitsを使用し、次にAlphaBlendを使用しています(下のコードを参照)。

問題は、AlphaBlendが失敗し、falseを返すことです。
1.何が原因なのか誰も知っていますか? 2.透明な画像を引き伸ばして描画する方が良い理由はありますか?

void AnimationManager::Draw(HDC hBBDC, Instance sInstance,RECT sClientRect) 
{ 
    // sClientRect is the hwnd rect 

    int nID = GetId(sInstance.nAnemationId); 
    int nFrameindex = sInstance.nFrameIndexs; 

    HDC hdcScreen = GetDC(NULL); 
    HDC hdcMem = CreateCompatibleDC(hdcScreen); 

    BITMAP bmp; 
    PBITMAPINFO pbmi; 
    WORD cClrBits; 

    ///******************* create PBITMAPINFO *********************/// 

    GetObject(m_pAnimations[nID]->m_pFramesArray[nFrameindex]->hBmp, sizeof(bmp), &bmp); 
    cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
    if(cClrBits == 1) 
     cClrBits = 1; 
    else if(cClrBits <= 4) 
      cClrBits = 4; 
    else if(cClrBits <= 8) 
      cClrBits = 8; 
    else if(cClrBits <= 24) 
      cClrBits = 24; 
    else cClrBits = 32; 

    if(cClrBits != 24) 
     pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*(1<<cClrBits)); 
    else 
     pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER)); 

    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    pbmi->bmiHeader.biWidth = bmp.bmWidth; 
    pbmi->bmiHeader.biHeight = bmp.bmHeight; 
    pbmi->bmiHeader.biPlanes = bmp.bmPlanes; 
    pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; 
    if(cClrBits < 24) 
     pbmi->bmiHeader.biClrUsed = (1<<cClrBits); 

    pbmi->bmiHeader.biCompression = BI_RGB; 

    pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits + 31)& ~31)/8 * pbmi->bmiHeader.biHeight; 
    pbmi->bmiHeader.biClrImportant = 0; 


    ///**************************end PBITMAPINFO creation *****************************************/// 


    // I checked the code to this point and it seems to be fine. The problem stasrts here: 

    ///create a pointer to the image bits 
    LPVOID lpvBits = (LPVOID)LocalAlloc(GPTR,pbmi->bmiHeader.biSizeImage); 
    GetBitmapBits(m_pAnimations[nID]->m_pFramesArray[nFrameindex]->hBmp, pbmi->bmiHeader.biSizeImage, lpvBits); 

    ///stretch 
    bool test = StretchDIBits(hdcMem,0,sClientRect.bottom,sClientRect.right, -1*sClientRect.bottom,0,0,pbmi->bmiHeader.biWidth,pbmi->bmiHeader.biHeight, lpvBits,pbmi,DIB_RGB_COLORS, SRCCOPY); 

    ///blend 
    test = AlphaBlend(hBBDC,0,0,sClientRect.right, sClientRect.bottom,hdcMem,0,0,sClientRect.right,sClientRect.bottom,m_sBlendfunc); 


    test = DeleteDC(hdcMem); // after CreateCompatibleDC 
    test = ReleaseDC(NULL, hdcScreen); // after GetDC 

    LocalFree(pbmi); 
    LocalFree(lpvBits); 
} 
+3

Windowsがあなたに伝えるまで、あなたは知らないでしょう。 GetLastError()を使用します。 –

+0

残念ながら、GetLastErrorは役に立たず、無効なパラメータを示すコード87を常に返します。 –

+0

SelectObjectを呼び出す必要はありません。 SelectObjectを使用して互換性のあるDCにビットマップを選択する必要があると思います。私の答えのサンプルコードを参照してください。 –

答えて

0

も伸ばすことができStretchDIBitsAlphaBlend場合を使用したのはなぜ?

0

なぜコードが失敗したのか正確に言うことはできませんが、最近の経験から、AlphaBlendは受け入れるビットマップフォーマットについて非常に気に入っています。幸いにも、私は他の状況に適応可能な作業コードを提供することができます。

static void DrawBitmapWithAlpha(HDC aDeviceContext,const CartoType::TBitmap* aBitmap,const CartoType::TRect& aDestRect,const CartoType::TRect& aSourceRect) 
{ 
HDC hdc = CreateCompatibleDC(aDeviceContext); 
BITMAPINFOHEADER bitmap_header; 
memset(&bitmap_header,0,sizeof(bitmap_header)); 
bitmap_header.biSize = sizeof(BITMAPINFOHEADER); 
bitmap_header.biWidth = aBitmap->Width(); 
bitmap_header.biHeight = aBitmap->Height(); 
bitmap_header.biPlanes = 1; 
bitmap_header.biBitCount = 32; 
bitmap_header.biCompression = BI_RGB; 
bitmap_header.biSizeImage = 0; 
bitmap_header.biXPelsPerMeter = 1000; 
bitmap_header.biYPelsPerMeter = 1000; 
bitmap_header.biClrUsed = 0; 
bitmap_header.biClrImportant = 0; 

void* bitmap_data = NULL; 
HBITMAP hbitmap = CreateDIBSection(hdc,(const BITMAPINFO*)&bitmap_header,DIB_RGB_COLORS,&bitmap_data,NULL,0); 

// Reflect the data vertically and change from ABGR to BGRA. 
unsigned char* dest_row = (unsigned char*)bitmap_data; 
const unsigned char* source_row = aBitmap->Data() + (aBitmap->Height() - 1) * aBitmap->RowBytes(); 
for (int y = 0; y < aBitmap->Height(); y++, dest_row += aBitmap->RowBytes(), source_row -= aBitmap->RowBytes()) 
    { 
    const unsigned char* p = source_row; 
    unsigned char* q = dest_row; 
    unsigned char* end = q + aBitmap->RowBytes(); 
    while (q < end) 
     { 
     *q++ = p[1]; 
     *q++ = p[2]; 
     *q++ = p[3]; 
     *q++ = p[0]; 
     p += 4; 
     } 
    } 
SelectObject(hdc,hbitmap); 

BLENDFUNCTION bf; 
bf.BlendOp = AC_SRC_OVER; 
bf.BlendFlags = 0; 
bf.SourceConstantAlpha = 0xFF; 
bf.AlphaFormat = AC_SRC_ALPHA; 

AlphaBlend(aDeviceContext,aDestRect.Left(),aDestRect.Top(),aDestRect.Width(),aDestRect.Height(), 
      hdc,aSourceRect.Left(),aSourceRect.Top(),aSourceRect.Width(),aSourceRect.Height(), 
      bf); 

DeleteObject(hbitmap); 
DeleteDC(hdc); 
} 

セクション開始「縦方向のデータを反映して」簡単にCreateDIBSectionによって作成されたビットマップにあなたのビットマップデータをコピーする必要があるものは何でもするように変更することができます。

私のビットマップフォーマットは、行バイト数が常に同じであるという点でWindowsと互換性があります。ビットマップ形式にそのプロパティがない場合は、コードを変更してそれに応じてデータをコピーする必要があります。

もう1つの有用な点:これはビットフィールドでは機能しませんでした。私はさらに、圧縮がBI_RGBに設定された32bppビットマップを提供する必要があると考えています。

関連する問題