duilib做网络开发的时候肯定会用到把图片从网络直接下载后加载到程序里的功能。网络下载图片后一般都是存在字节数组里,如果保存到本地后再用duilib加载就很简单啦,直接设置路径就可以加载,但是下载后本来就是在内存的,如果再保存到本地再加载到程序,麻烦啦一步效率还不好。下面添加一个方法实现直接从内存加载图片数据使用。
首先在CRenderEngine 这个类中添加一个从内存中加载图片数据转成HBITMAP的函数,原来已经有一个函数啦。只不过是传入一个图片字符串路径。然后读取到内存返回的。这里只是把原来的代码修改下直接从内存取数据转成HBITMAPHBITMAP CRenderEngine::LoadImage(unsigned char* bytesImg,DWORD bytesLength, LPCTSTR type , DWORD mask)
{
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 (!pImage) {
//::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
{
pDest[i * 4 + 3] = pImage[i * 4 + 3];
if (pDest[i * 4 + 3]
{
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;
}
使用方法如下//下面随后演示从网络下载图片后加载
TCHAR bdurl[] = _T("http://www.zhaokeli.com/public/home/blog/images/touxiang.jpg");
//定义接收图片的缓冲区..
unsigned char lpPicBuff[1024 * 100] = { 0 };
DWORD dwSize = 1024 * 1000;
Ank::Helper::DownloadFile(bdurl, _T(""), NULL, _T(""), lpPicBuff,&dwSize);
//字节数据转成位图
HBITMAP img=CRenderEngine::LoadImage(lpPicBuff, dwSize);
BITMAP bmp;
GetObject(img, sizeof(BITMAP), &bmp);
// 先释放图片占用内存(会自动判断不存在的话返回),防止多次加载时内存泄露
m_PaintManager.RemoveImage(bdurl);
m_PaintManager.AddImage(bdurl,img,bmp.bmWidth,bmp.bmHeight,true);
m_pBtnLoadImg->SetHotImage(bdurl);
上面代码中从网络下载图片的代码需要自己实现。
效果