欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

duilib c++ 加载网络图片到内存中,并直接显示出来

相关标签: 技术经验积累