【问题标题】:Correctly displaying s 32 bit transparent PNG file in a DC在 DC 中正确显示 32 位透明 PNG 文件
【发布时间】:2017-08-01 11:52:05
【问题描述】:

这是我将透明 PNG 文件加载到缓冲区的方法:

/* static */ void CRibbonButton::LoadImageFromRelativeFilespec(HGLOBAL& rhDIB, bool bLarge, 
                                                                const CString& rstrImageRelFilespec, UINT32& ruDIBW, int& ruDIBH) 
{
    USES_CONVERSION;

    using namespace RibbonBar ; 

    // Clear any existing image away. 
    if (rhDIB != NULL)
        ::GlobalFree(rhDIB);

    // Build the correct filespec. 
    CString strThisEXE = _T(""); 
    ::GetModuleFileName(AfxGetInstanceHandle(), 
                        strThisEXE.GetBuffer(_MAX_PATH + 1),_MAX_PATH); 
    strThisEXE.ReleaseBuffer(); 

    LPCTSTR lpszPath = (LPCTSTR)strThisEXE ; 
    LPTSTR lpszFilename = ::PathFindFileName(lpszPath); 
    CString strPath = strThisEXE.Left( (int)(lpszFilename - lpszPath) ); 

    CString strFilespec = strPath ; 
    ::PathAppend(strFilespec.GetBuffer(_MAX_PATH + 1), rstrImageRelFilespec); 
    strFilespec.ReleaseBuffer(); 

    HISSRC hSrc = is6_OpenFileSource(CT2A((LPCTSTR)strFilespec));
    if (hSrc)
    {
        // read it
        UINT32 w, h;
        rhDIB = is6_ReadImage(hSrc, &w, &h, 2, 0);   // the "2" = load directly to DIB, in the lowest bit depth possible.
        if (rhDIB)
        {
            // get the dimensions
            is6_DIBWidth((BITMAPINFOHEADER *)rhDIB, &ruDIBW);
            is6_DIBHeight((BITMAPINFOHEADER *)rhDIB, &ruDIBH);

            UINT32 bc;
            is6_DIBBitCount((BITMAPINFOHEADER *)rhDIB, &bc);

            is6_ClearJPGInputMarkers();
        }
        else
        {
            AfxMessageBox(_T("Can't read that image"));
        }

        is6_CloseSource(hSrc);
    }
}

这是渲染代码:

/* virtual */ void CRibbonButton::PaintData(CDC& rDC) 
{
    CDC dcMem ; 
    dcMem.CreateCompatibleDC(NULL); // Screen. 

    const CRect& rrctImage = GetImageBounds(); 


    if (m_hDIB)
    {
        // draw to a memory DC
        CDC memDC;
        if (memDC.CreateCompatibleDC(&rDC))
        {
            CBitmap bmp;
            if (bmp.CreateCompatibleBitmap(&rDC, rrctImage.Width(), rrctImage.Height()))
            {
                CBitmap *ob = memDC.SelectObject(&bmp);
                if (ob)
                {
                    // dark red background
                    memDC.FillSolidRect(CRect(rrctImage.left, rrctImage.top, rrctImage.Width(), rrctImage.Height()), RibbonBar::kBackColour);

                    // stretchDrawDIB is typically the fastest way to draw an image from ImgSource.
                    BOOL ok = is6_StretchDrawDIB(memDC.m_hDC, (BITMAPINFOHEADER *)m_hDIB, 0, 0, m_uDIBW, m_uDIBH);

                    if (!ok)
                    {
                        memDC.SetBkMode(TRANSPARENT);
                        memDC.SetTextColor(RGB(255, 255, 255));
                        memDC.TextOut(rrctImage.left, rrctImage.top, _T("X"));
                    }

                    // copy this to the window
                    rDC.BitBlt(rrctImage.left, rrctImage.top, rrctImage.Width(), rrctImage.Height(), &memDC, 0, 0, SRCCOPY);

                    memDC.SelectObject(ob);
                }
            }
        }
    }

    dcMem.DeleteDC(); 

}

它没有正确绘制透明的 PNG 文件。我总是以黑色背景结束。

我正在使用 ISSource 库进行渲染。但该公司现在倒闭了。我正在使用版本 6 库。

更新

根据答案,我现在正在加载和渲染图像,如下所示:

CRect rct;
CImage img;
img.Load(_T("d:\\Publishers.png"));

rct.SetRect(rrctImage.left, rrctImage.top, rrctImage.left + img.GetWidth(), rrctImage.top + img.GetHeight());
img.TransparentBlt(rDC.GetSafeHdc(), rct, RGB(255,255,255));

但是为什么我在设置透明度的地方还是变黑了?

如果我没有将RGB(255,255,255) 作为最后一个参数传递 并使用默认我得到一个例外。

更新

根据TransparentBit的文档:

TransparentBlt 支持每像素 4 位和每像素 8 位的源位图。使用 CImage::AlphaBlend 指定 每像素 32 位的位图 具有透明度。

所以,我已经停止使用:

img.TransparentBlt(rDC.GetSafeHdc(), rct);

现在我正在使用:

img.AlphaBlend(rDC.GetSafeHdc(), rct.left, rct.top, rct.Width(), rct.Height(), rct.left, rct.top, rct.Width(), rct.Height(), 0xff, AC_SRC_OVER);

我什么都没看到。我确认坐标是正确的:

CBrush br;
br.CreateStockObject(BLACK_BRUSH);
rDC.FrameRect(rct, &br);

为什么我什么都看不到?

【问题讨论】:

  • IIRC,你需要在img.Alphablend之后做img.ReleaseDC()
  • Dst 字段是 DC 中的坐标。 Src 值在您的图片中。通常它们以 0,0 开头,并以宽度和高度为值。 xSrc/ySrc 是否不是 0 您在源中有偏移量。你不想这样。

标签: mfc transparency imgsource


【解决方案1】:

这很复杂。 CImage中已有方法。

查看CImage::AlphaBlendCImage::TransparentBlt

AlphaBlend:Dst 字段是您的 DC 中的坐标。 Src 值在您的图片中。通常它们以 0,0 开头,并以宽度和高度为值。 xSrc/ySrc 是否不是 0 您在源中有偏移量。

【讨论】:

  • 谢谢。我可以询问答案以获得这些资源的链接吗?谢谢。
  • 谢谢。我还是黑了。请查看更新后的问题。
  • 更改了答案并将指向 MSDN 的链接放入其中。也有一篇关于所有这些透明 blt codeproject.com/Articles/1378/… 的真正旧文章,但我认为大部分已经过时了。
  • 如果我使用 Alphablend,我最终看不到图像。
  • Dst 字段是 DC 中的坐标。 Src 值在您的图片中。通常它们以 0,0 开头,并以宽度和高度为值。 xSrc/ySrc 是否不是 0 您在源中有偏移量。你不想这样。
猜你喜欢
  • 2010-11-25
  • 1970-01-01
  • 2011-06-22
  • 1970-01-01
  • 2022-10-17
  • 1970-01-01
  • 2012-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多