具有透明加载形式 PNG 的 MFC Draw Icons 图像显示为灰色
MFC Draw Icons images with transparency loaded form PNG are displayed greyish
我正在尝试显示来自 PNG 条带的加载图标。问题是由于透明度因素,它们显示为灰色。我不知道为什么,因为背景是白色的。
这是一个代码片段:
class CPslToolBarImages : public CMFCToolBarImages
{
public:
CPslToolBarImages() { m_sizeImageDest.cx = m_sizeImageDest.cy = 32; }
~CPslToolBarImages() {}
public:
BOOL ToImageList(CImageList *imagelist);
};
BOOL CPslToolBarImages::ToImageList(CImageList *imagelist)
{
CSize size = GetImageSize();
imagelist->Create(size.cx, size.cy, ILC_COLOR32 | ILC_MASK, 0, 0);
HBITMAP hbmImageWellCopy = (HBITMAP) ::CopyImage(m_hbmImageWell, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
imagelist->Add(CBitmap::FromHandle(hbmImageWellCopy), m_clrTransparent == -1 ? afxGlobalData.clrBtnFace : m_clrTransparent);
extern void AFXAPI AfxDeleteObject(HGDIOBJ* pObject);
AfxDeleteObject((HGDIOBJ*)&hbmImageWellCopy);
return TRUE;
}
BOOL PlMakeHighColorImageList(CImageList *imagelist, LPCTSTR resid, CSize sizeImage)
{
CPslToolBarImages images;
images.SetImageSize(sizeImage);
images.LoadStr(resid);
return images.ToImageList2(imagelist);
}
// Draw call
CImageList imagelist;
PlMakeHighColorImageList(imagelist, "ImageStrip.PNG", CSize(16, 16));
imagelist.Draw(dc, nImage, rc.TopLeft(), ILD_TRANSPARENT);
我注意到当我从 PNG 中读取它们时,像素值已经与 alpha 通道混合,所以我对它们进行了反向操作。
static BYTE computeColor(int color, int alpha)
{
if (alpha == 0)
return 0;
int result = 255 * color / alpha;
return (result > 255) ? 255 : (result < 0) ? 0 : result;
}
void MyClass::ComputeColorWithAlphaChannel(HBITMAP hbmImageWellCopy)
{
HDC hDC = GetDC(0);
BITMAP bm = { 0 };
GetObject(hbmImageWellCopy, sizeof(bm), &bm);
BITMAPINFO* bmi = (BITMAPINFO*)_alloca(sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)));
::ZeroMemory(bmi, sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)));
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BOOL bRes = ::GetDIBits(hDC, hbmImageWellCopy, 0, bm.bmHeight, NULL, bmi, DIB_RGB_COLORS);
if (!bRes || bmi->bmiHeader.biBitCount != 32) return;
LPBYTE pBitData = (LPBYTE) ::LocalAlloc(LPTR, bm.bmWidth * bm.bmHeight * sizeof(DWORD));
if (pBitData == NULL) return;
LPBYTE pData = pBitData;
::GetDIBits(hDC, hbmImageWellCopy, 0, bm.bmHeight, pData, bmi, DIB_RGB_COLORS);
for (int y = 0; y < bm.bmHeight; y++) {
for (int x = 0; x < bm.bmWidth; x++) {
pData[0] = computeColor(pData[0], pData[3]);
pData[1] = computeColor(pData[1], pData[3]);
pData[2] = computeColor(pData[2], pData[3]);
}
}
::SetDIBits(hDC, hbmImageWellCopy, 0, bm.bmHeight, pBitData, bmi, DIB_RGB_COLORS);
::LocalFree(pBitData);
}
我正在尝试显示来自 PNG 条带的加载图标。问题是由于透明度因素,它们显示为灰色。我不知道为什么,因为背景是白色的。 这是一个代码片段:
class CPslToolBarImages : public CMFCToolBarImages
{
public:
CPslToolBarImages() { m_sizeImageDest.cx = m_sizeImageDest.cy = 32; }
~CPslToolBarImages() {}
public:
BOOL ToImageList(CImageList *imagelist);
};
BOOL CPslToolBarImages::ToImageList(CImageList *imagelist)
{
CSize size = GetImageSize();
imagelist->Create(size.cx, size.cy, ILC_COLOR32 | ILC_MASK, 0, 0);
HBITMAP hbmImageWellCopy = (HBITMAP) ::CopyImage(m_hbmImageWell, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
imagelist->Add(CBitmap::FromHandle(hbmImageWellCopy), m_clrTransparent == -1 ? afxGlobalData.clrBtnFace : m_clrTransparent);
extern void AFXAPI AfxDeleteObject(HGDIOBJ* pObject);
AfxDeleteObject((HGDIOBJ*)&hbmImageWellCopy);
return TRUE;
}
BOOL PlMakeHighColorImageList(CImageList *imagelist, LPCTSTR resid, CSize sizeImage)
{
CPslToolBarImages images;
images.SetImageSize(sizeImage);
images.LoadStr(resid);
return images.ToImageList2(imagelist);
}
// Draw call
CImageList imagelist;
PlMakeHighColorImageList(imagelist, "ImageStrip.PNG", CSize(16, 16));
imagelist.Draw(dc, nImage, rc.TopLeft(), ILD_TRANSPARENT);
我注意到当我从 PNG 中读取它们时,像素值已经与 alpha 通道混合,所以我对它们进行了反向操作。
static BYTE computeColor(int color, int alpha)
{
if (alpha == 0)
return 0;
int result = 255 * color / alpha;
return (result > 255) ? 255 : (result < 0) ? 0 : result;
}
void MyClass::ComputeColorWithAlphaChannel(HBITMAP hbmImageWellCopy)
{
HDC hDC = GetDC(0);
BITMAP bm = { 0 };
GetObject(hbmImageWellCopy, sizeof(bm), &bm);
BITMAPINFO* bmi = (BITMAPINFO*)_alloca(sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)));
::ZeroMemory(bmi, sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD)));
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BOOL bRes = ::GetDIBits(hDC, hbmImageWellCopy, 0, bm.bmHeight, NULL, bmi, DIB_RGB_COLORS);
if (!bRes || bmi->bmiHeader.biBitCount != 32) return;
LPBYTE pBitData = (LPBYTE) ::LocalAlloc(LPTR, bm.bmWidth * bm.bmHeight * sizeof(DWORD));
if (pBitData == NULL) return;
LPBYTE pData = pBitData;
::GetDIBits(hDC, hbmImageWellCopy, 0, bm.bmHeight, pData, bmi, DIB_RGB_COLORS);
for (int y = 0; y < bm.bmHeight; y++) {
for (int x = 0; x < bm.bmWidth; x++) {
pData[0] = computeColor(pData[0], pData[3]);
pData[1] = computeColor(pData[1], pData[3]);
pData[2] = computeColor(pData[2], pData[3]);
}
}
::SetDIBits(hDC, hbmImageWellCopy, 0, bm.bmHeight, pBitData, bmi, DIB_RGB_COLORS);
::LocalFree(pBitData);
}