VC透明显示带透明度PNG图片及不带透明度的图片
2012-11-06 15:42
591 查看
一、显示带透明度的PNG图片
PNG图片的透明背景总是一片白色,后来才发现这其实是微软GDI+的设计问题,PNG图片是ARGB,使用GDI+载入图片的时候,GDI+会默认已经进行了预剩运算(PARGB),即每象素的实际值是已经和ALPHA值按比例相乘的结果,实际上它根本就没有做预乘,在使用透明图片的象素ALPHA通道的时候,CImage内部正是调用的AlphaBlend,没有预乘的图当作预乘的图片处理的结果就是这相当于一张和纯白背景进行了预剩,所以图象总是出现白色背景。所以先要进行处理一下:
CImage img;
HRESULT result = img.Load(_T("(1.png"));
for(int i = 0; i < img.GetWidth(); i++)
{
for(int j = 0; j < img.GetHeight(); j++)
{
unsigned char* pucColor = reinterpret_cast<unsigned char *>(img.GetPixelAddress(i , j));
pucColor[0] = pucColor[0] * pucColor[3] / 255;
pucColor[1] = pucColor[1] * pucColor[3] / 255;
pucColor[2] = pucColor[2] * pucColor[3] / 255;
}
}
然后再Draw到对应的DC上
img.Draw(pDC->m_hDC,0,0);
二、显示不带透明度的图片,且要透明显示:
void AlphaBmp(HDC hdc,HBITMAP hBitmap,int x,int y,short limit,HRGN hRgn,COLORREF col)
{
BLENDFUNCTION blendfunc;
HDC hMaskDc;
HBITMAP hOld=NULL;
BITMAP Bmp;
blendfunc.BlendFlags=0;
blendfunc.AlphaFormat=0;
blendfunc.SourceConstantAlpha=(unsigned char)limit;
blendfunc.BlendOp=AC_SRC_OVER;
GetObject(hBitmap,sizeof(BITMAP),(LPSTR)&Bmp);
hMaskDc=CreateCompatibleDC(hdc);
hOld=(HBITMAP)SelectObject(hMaskDc,hBitmap);
HDC hTempDC=CreateCompatibleDC(hdc);
HBITMAP hBitmap2=CreateCompatibleBitmap(hdc,Bmp.bmWidth,Bmp.bmHeight);
hOld=(HBITMAP)SelectObject(hTempDC,hBitmap2);
BitBlt(hTempDC,0,0,Bmp.bmWidth,Bmp.bmHeight,hdc,0,0,SRCCOPY);
AlphaBlend (hTempDC,0,0,Bmp.bmWidth,Bmp.bmHeight,hMaskDc,0,0,Bmp.bmWidth,Bmp.bmHeight,blendfunc);
HRGN hR=CreateRectRgn(0,0,Bmp.bmWidth,Bmp.bmHeight);
HBRUSH hbr=CreateSolidBrush(col);
CombineRgn(hR,hR,hRgn,RGN_DIFF);
FillRgn(hTempDC,hR,hbr);
TransparentBlt(hdc,x,y,Bmp.bmWidth,Bmp.bmHeight,hTempDC,0,0,Bmp.bmWidth,Bmp.bmHeight,col);
SelectObject(hTempDC,hOld);
DeleteObject(hBitmap2);
DeleteObject(hR);
DeleteObject(hbr);
DeleteDC(hTempDC);
SelectObject(hMaskDc,hOld);
DeleteDC(hMaskDc);
}
参数的含义一次是:hdc为要显示图片的DC
hBitmap为要显示的图片句柄
x,y为坐标
limit为透明度(0-255)
hRgn为图片除掉要屏蔽的颜色的区域(对于球体就是一个圆形区域)
col为要屏蔽的颜色(例如一幅周围是白色的球,不显示周围的白色,只要球(白色就是屏蔽色))
对于hRgn有一点,怎么得到这个区域呢,看下面这个函数:
HRGN BitmapToRgn(HBITMAP hBitmap,COLORREF col)
{
HDC hMemDc;
HBITMAP hOld;
COLORREF CPixel;
HRGN rTemp,hGoal;
BITMAP Bmp;
GetObject(hBitmap,sizeof(BITMAP),&Bmp);
hMemDc=CreateCompatibleDC(NULL);
hOld=(HBITMAP)SelectObject(hMemDc,hBitmap);
hGoal=CreateRectRgn(0,0,Bmp.bmWidth,Bmp.bmHeight);
for(int x=0;x<=Bmp.bmWidth;x++)
for(int y=0;y<=Bmp.bmHeight;y++)
{
CPixel=GetPixel(hMemDc,x,y);
if(CPixel==col)
{
rTemp=CreateRectRgn(x,y,x+1,y+1);
CombineRgn(hGoal,hGoal,rTemp,RGN_XOR);
DeleteObject(rTemp);
}
}
SelectObject(hMemDc,hOld);
DeleteDC(hMemDc);
return hGoal;
}
参数一次是hBitmap为要得到区域的位图,col为屏蔽色
用法例子为:
HBITMAP hBitmap=LoadBitmap(GetModuleHandle(0),MAKEINTRESOURCE(IDB_BITMAP2));
HRGN hrgn=BitmapToRgn(hBitmap,RGB(255,0,255));
AlphaBmp(hDc,hBitmap,450,0,200,hrgn,RGB(255,0,255));
DeleteObject(hBitmap);
DeleteObject(hrgn);//为了提高速度,这个应该用全局变量保存,不易频繁删除
PNG图片的透明背景总是一片白色,后来才发现这其实是微软GDI+的设计问题,PNG图片是ARGB,使用GDI+载入图片的时候,GDI+会默认已经进行了预剩运算(PARGB),即每象素的实际值是已经和ALPHA值按比例相乘的结果,实际上它根本就没有做预乘,在使用透明图片的象素ALPHA通道的时候,CImage内部正是调用的AlphaBlend,没有预乘的图当作预乘的图片处理的结果就是这相当于一张和纯白背景进行了预剩,所以图象总是出现白色背景。所以先要进行处理一下:
CImage img;
HRESULT result = img.Load(_T("(1.png"));
for(int i = 0; i < img.GetWidth(); i++)
{
for(int j = 0; j < img.GetHeight(); j++)
{
unsigned char* pucColor = reinterpret_cast<unsigned char *>(img.GetPixelAddress(i , j));
pucColor[0] = pucColor[0] * pucColor[3] / 255;
pucColor[1] = pucColor[1] * pucColor[3] / 255;
pucColor[2] = pucColor[2] * pucColor[3] / 255;
}
}
然后再Draw到对应的DC上
img.Draw(pDC->m_hDC,0,0);
二、显示不带透明度的图片,且要透明显示:
void AlphaBmp(HDC hdc,HBITMAP hBitmap,int x,int y,short limit,HRGN hRgn,COLORREF col)
{
BLENDFUNCTION blendfunc;
HDC hMaskDc;
HBITMAP hOld=NULL;
BITMAP Bmp;
blendfunc.BlendFlags=0;
blendfunc.AlphaFormat=0;
blendfunc.SourceConstantAlpha=(unsigned char)limit;
blendfunc.BlendOp=AC_SRC_OVER;
GetObject(hBitmap,sizeof(BITMAP),(LPSTR)&Bmp);
hMaskDc=CreateCompatibleDC(hdc);
hOld=(HBITMAP)SelectObject(hMaskDc,hBitmap);
HDC hTempDC=CreateCompatibleDC(hdc);
HBITMAP hBitmap2=CreateCompatibleBitmap(hdc,Bmp.bmWidth,Bmp.bmHeight);
hOld=(HBITMAP)SelectObject(hTempDC,hBitmap2);
BitBlt(hTempDC,0,0,Bmp.bmWidth,Bmp.bmHeight,hdc,0,0,SRCCOPY);
AlphaBlend (hTempDC,0,0,Bmp.bmWidth,Bmp.bmHeight,hMaskDc,0,0,Bmp.bmWidth,Bmp.bmHeight,blendfunc);
HRGN hR=CreateRectRgn(0,0,Bmp.bmWidth,Bmp.bmHeight);
HBRUSH hbr=CreateSolidBrush(col);
CombineRgn(hR,hR,hRgn,RGN_DIFF);
FillRgn(hTempDC,hR,hbr);
TransparentBlt(hdc,x,y,Bmp.bmWidth,Bmp.bmHeight,hTempDC,0,0,Bmp.bmWidth,Bmp.bmHeight,col);
SelectObject(hTempDC,hOld);
DeleteObject(hBitmap2);
DeleteObject(hR);
DeleteObject(hbr);
DeleteDC(hTempDC);
SelectObject(hMaskDc,hOld);
DeleteDC(hMaskDc);
}
参数的含义一次是:hdc为要显示图片的DC
hBitmap为要显示的图片句柄
x,y为坐标
limit为透明度(0-255)
hRgn为图片除掉要屏蔽的颜色的区域(对于球体就是一个圆形区域)
col为要屏蔽的颜色(例如一幅周围是白色的球,不显示周围的白色,只要球(白色就是屏蔽色))
对于hRgn有一点,怎么得到这个区域呢,看下面这个函数:
HRGN BitmapToRgn(HBITMAP hBitmap,COLORREF col)
{
HDC hMemDc;
HBITMAP hOld;
COLORREF CPixel;
HRGN rTemp,hGoal;
BITMAP Bmp;
GetObject(hBitmap,sizeof(BITMAP),&Bmp);
hMemDc=CreateCompatibleDC(NULL);
hOld=(HBITMAP)SelectObject(hMemDc,hBitmap);
hGoal=CreateRectRgn(0,0,Bmp.bmWidth,Bmp.bmHeight);
for(int x=0;x<=Bmp.bmWidth;x++)
for(int y=0;y<=Bmp.bmHeight;y++)
{
CPixel=GetPixel(hMemDc,x,y);
if(CPixel==col)
{
rTemp=CreateRectRgn(x,y,x+1,y+1);
CombineRgn(hGoal,hGoal,rTemp,RGN_XOR);
DeleteObject(rTemp);
}
}
SelectObject(hMemDc,hOld);
DeleteDC(hMemDc);
return hGoal;
}
参数一次是hBitmap为要得到区域的位图,col为屏蔽色
用法例子为:
HBITMAP hBitmap=LoadBitmap(GetModuleHandle(0),MAKEINTRESOURCE(IDB_BITMAP2));
HRGN hrgn=BitmapToRgn(hBitmap,RGB(255,0,255));
AlphaBmp(hDc,hBitmap,450,0,200,hrgn,RGB(255,0,255));
DeleteObject(hBitmap);
DeleteObject(hrgn);//为了提高速度,这个应该用全局变量保存,不易频繁删除
相关文章推荐
- VC利用GDI+显示透明的PNG图片
- VC利用GDI+显示透明的PNG图片
- VC利用GDI+显示透明的PNG图片
- VC利用GDI+显示透明的PNG图片
- VC利用GDI+显示透明的PNG图片
- VC利用GDI+显示透明的PNG图片
- VC利用GDI+显示透明的PNG图片
- VC利用GDI+显示透明的PNG图片
- vc透明显示图片
- vc++加载透明png图片方法——GDI+和CImage两种
- 图片显示、PNG透明
- IE6下PNG图片透明显示解决方法(From QQ)
- 解决IE6下的,不能显示透明PNG图片的问题(转载)
- png格式的图片在IE6透明显示
- 让IE6显示透明PNG背景图片
- vc win32 gdi+ 怎么显示PNG图片
- vc++加载透明png图片方法——GDI+和CImage两种
- 使png图片在网页上显示为透明的方法
- VC6.0显示透明PNG图片
- 利用CImage显示透明PNG图片