2

This is my method for loading a transparent PNG file into a buffer:

/* 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);
    }
}

And this is the rendering code:

/* 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(); 

}

It is not drawing the transparent PNG file correctly. I always end up with a black background.

I am using the ISSource libraries for rendering. But the company is now out of business. I am using version 6 library.

Update

Based on the answer I am now loading and rendering the image like this:

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));

But why do I still get black for where the transparency was set?

If I don't pass RGB(255,255,255) as the last parameter and use the default I get an exception.

Update

According to the documentation for TransparentBit:

TransparentBlt is supported for source bitmaps of 4 bits per pixel and 8 bits per pixel. Use CImage::AlphaBlend to specify 32 bits-per-pixel bitmaps with transparency.

So, I have stopped using:

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

Now I am using:

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

I don't see anything. I confirm the coordinates are right by doing:

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

Why do I not see anything?

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
  • IIRC, you need to do `img.ReleaseDC()` after `img.Alphablend` – sergiol Aug 01 '17 at 13:43
  • 1
    The Dst fields are the coordiantes in your DC. the Src values are inside your picture. Usually they start with 0,0 and have the width and height as values. Is xSrc/ySrc are not 0 you have an offset in the source. You don't want that. – xMRi Aug 01 '17 at 13:48

1 Answers1

2

This is much to complicate. There are existing methods in CImage.

Check out CImage::AlphaBlend or CImage::TransparentBlt.

AlphaBlend: The Dst fields are the coordinates in your DC. the Src values are inside your picture. Usually they start with 0,0 and have the width and height as values. Is xSrc/ySrc are not 0 you have an offset in the source.

xMRi
  • 14,982
  • 3
  • 26
  • 59
  • Thanks. Can I kindly ask for the answer to have a link to these resources? Thanks. – Andrew Truckle Aug 01 '17 at 13:00
  • Thanks. I still get black. Please see updated question. – Andrew Truckle Aug 01 '17 at 13:20
  • Changed answer and placed links to the MSDN into it. ALso there is a real old article about all this transparent blt https://www.codeproject.com/Articles/1378/Drawing-transparent-bitmaps-using-CImage, but I think most of it is obsolet. – xMRi Aug 01 '17 at 13:20
  • If I use Alphablend I end up with no visible image. – Andrew Truckle Aug 01 '17 at 13:25
  • Than I guess that your parameters are invalid... ;) – xMRi Aug 01 '17 at 13:35
  • 1
    The Dst fields are the coordiantes in your DC. the Src values are inside your picture. Usually they start with 0,0 and have the width and height as values. Is xSrc/ySrc are not 0 you have an offset in the source. You don't want that. – xMRi Aug 01 '17 at 13:48
  • @sergiol My updated question actually has the resolution. Using the `TransparentBit` as indicated by @xMRi. – Andrew Truckle Aug 02 '17 at 20:14