duilib c++ 加载网络图片到内存中,并直接显示出来
程序员文章站
2022-07-06 08:18:37
...
duilib中控件有个方法setbkimage,但是这个只能先下载到本地,再传入路径显示。
我想要的是直接加载网络图片到内存。然后直接显示出来。
下面记录下载过程:
BOOL CFunctionWnd::DowndloadImage(CString strMainPic)
{
//下面随后演示从网络下载图片后加载
//TCHAR bdurl[] = _T("https://img.alicdn.com/imgextra/i4/752144829/O1CN01cRd9LL1lXjBQBM07w_!!752144829.jpg");
TCHAR* bdurl = strMainPic.GetBuffer();
strMainPic.ReleaseBuffer();
DWORD dwSize = 0;
BYTE *pBuffer = NULL;
//仅加载到内存中
pBuffer = DownloadFile(bdurl, &dwSize);
if (!pBuffer)
{
return FALSE;
}
//字节数据转成位图
HBITMAP img = LoadImage(pBuffer, dwSize);
if (!img)
{
return FALSE;
}
BITMAP bmp;
GetObject(img, sizeof(BITMAP), &bmp);
// 先释放图片占用内存(会自动判断不存在的话返回),防止多次加载时内存泄露
m_pm.RemoveImage(bdurl);
m_pm.AddImage(bdurl, img, bmp.bmWidth, bmp.bmHeight, true);
/*CLabelUI* pBtn = static_cast<CLabelUI*>(m_pm.FindControl(_T("pic1")));
pBtn->SetBkImage(bdurl);*/
return TRUE;
}
#define RES_TYPE_COLOR _T("1")
HBITMAP LoadImage(unsigned char* bytesImg, DWORD bytesLength, LPCTSTR type, DWORD mask)
{
if (!bytesImg)
{
return NULL;
}
LPBYTE pImage = NULL;
int x = 1, y = 1, n;
if (!type || _tcscmp(type, RES_TYPE_COLOR) != 0) {
pImage = stbi_load_from_memory(bytesImg, bytesLength, &x, &y, &n, 4);
//delete[] pData;
if (!3) {
//::MessageBox(0, _T("解析图片失败"), _T("抓BUG"), MB_OK);
return NULL;
}
}
BITMAPINFO bmi;
::ZeroMemory(&bmi, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = x;
bmi.bmiHeader.biHeight = -y;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = x * y * 4;
bool bAlphaChannel = false;
LPBYTE pDest = NULL;
HBITMAP hBitmap = ::CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**)&pDest, NULL, 0);
if (!hBitmap) {
//::MessageBox(0, _T("CreateDIBSection失败"), _T("抓BUG"), MB_OK);
return NULL;
}
//BYTE bColorBits[4] = { 0 };
//if (type && _tcscmp(type, RES_TYPE_COLOR) == 0) {
// LPTSTR pstr = NULL;
// LPCTSTR pstrValue = bitmap.m_lpstr;
// if (*pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
// DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
// pImage = (LPBYTE)&clrColor;
// /* BGRA -> RGBA */
// bColorBits[3] = pImage[3];
// bColorBits[2] = pImage[0];
// bColorBits[1] = pImage[1];
// bColorBits[0] = pImage[2];
// pImage = bColorBits;
//}
for (int i = 0; i < x * y; i++)
{
pDest[i * 4 + 3] = pImage[i * 4 + 3];
if (pDest[i * 4 + 3] < 255)
{
pDest[i * 4] = (BYTE)(DWORD(pImage[i * 4 + 2])*pImage[i * 4 + 3] / 255);
pDest[i * 4 + 1] = (BYTE)(DWORD(pImage[i * 4 + 1])*pImage[i * 4 + 3] / 255);
pDest[i * 4 + 2] = (BYTE)(DWORD(pImage[i * 4])*pImage[i * 4 + 3] / 255);
bAlphaChannel = true;
}
else
{
pDest[i * 4] = pImage[i * 4 + 2];
pDest[i * 4 + 1] = pImage[i * 4 + 1];
pDest[i * 4 + 2] = pImage[i * 4];
}
if (*(DWORD*)(&pDest[i * 4]) == mask) {
pDest[i * 4] = (BYTE)0;
pDest[i * 4 + 1] = (BYTE)0;
pDest[i * 4 + 2] = (BYTE)0;
pDest[i * 4 + 3] = (BYTE)0;
bAlphaChannel = true;
}
}
if (!type || _tcscmp(type, RES_TYPE_COLOR) != 0) {
stbi_image_free(pImage);
}
//TImageInfo* data = new TImageInfo;
//data->hBitmap = hBitmap;
//data->pBits = pDest;
//data->nX = x;
//data->nY = y;
//data->bAlpha = bAlphaChannel;
//data->bUseHSL = false;
//data->pSrcBits = NULL;
//return data;
return hBitmap;
}
此方法用到了图像库stb_image。
下载:https://github.com/nothings/stb
下载后解压,在项目属性的包含目录加上stb-master路径即可。
使用方法:
CLabelUI* image_product = static_cast<CLabelUI*>(pListItem->FindSubControl(_T("image_product")));
//加载网络图片
//网络图片的地址
CString strMainPic = _A2W(data[i]["mainPic"].asCString());
if (!DowndloadImage(strMainPic))
{
continue;
}
image_product->SetBkImage(strMainPic);