bsp; if(oldbmpimg)
dcimg.SelectObject(oldbmpimg);
if(oldbmptrans)
dctrans.SelectObject(oldbmptrans);
pdc->SetBkColor(crOldBack);
pdc->SetTextColor(crOldText);
return TRUE;
}
Alpha混合
Alpha混合是一种像素混合的方法。所谓的像素混合就是使用一定的算法把两个像素的值混合成一个新的像素值(倒,和没说一样),通常我们都把两个像素的值,分别叫做源(src)和目的(dst),然后把混合后的结果存入dst中:
dst= src blend dst
如果源像素和目的像素都是RGBA格式,你可以使用每个像素的Alpha信息(或者叫做Alpha通道)组合出各种运算公式,例如
dst= src*src.alpha+dst*dst.alpha;
或者
dst=src*src.alpha + dst*(1-src.alpha)//这里我们假设alpha值是0~1的浮点数。
可惜标准GDI没有支持类似这种操作的函数(起码我没找到),它只支持另一种Alpha混合,我把它叫做const alpha blend,也就是把两幅都不包含Alpha通道的图像的按照一个固定的Alpha值混合到一起,也就是每个像素都使用同一Alpha值。GDI的支持这个操作的函数是:
AlphaBlend(
HDC hdcDest,
int nXOriginDest,
int nYOriginDest,
int nWidthDest,
int hHeightDest,
HDC hdcSrc,
int nXOriginSrc,
int nYOriginSrc,
int nWidthSrc,
int nHeightSrc,
BLENDFUNCTION blendFunction
);
这个API的参数个数略多了一些,但是我想其中的位置参数你可以轻松搞定,还有就是源DC和目的DC,当然了,我们的GDI只能对DC操作,而不是对我们的像素数据,而我们只要把我的位图select到DC中就OK了,最后一个参数是一个结构,是用来指定Alpha的运算方式的,请看一个实际的例子:
BLENDFUNCTION bf;
bf.AlphaFormat=0;
bf.BlendFlags=0;
bf.BlendOp=AC_SRC_OVER;
bf.SourceConstantAlpha=100;//指明透明度,取值范围是0~255
AlphaBlend(pdc->GetSafeHdc(),rc.left,rc.top,rc.Width(),rc.Height(),
memdc.GetSafeHdc(),0,0,rc.Width(),rc.Height(),bf);
也许你看过很多游戏,在弹出文字对话框的时候都是在游戏画面上蒙一层半透明的黑色,然后在这上面印字。使用上述操作就可以达到此效果。你可以先建立一个Memory DC,然后把他填充为黑,然后把Alpha值设为128,然后混合到你要绘制的DC上(不一定是窗口DC哦,记得我们前面将的双缓冲吗?)就OK了。
读取JPEG,GIF文件
JPEG压缩算法综合的信号学和视觉心理学,而GIF格式,特别是支持动画的GIF89a格式为了节约容量也做了很多种非常变态的优化,所以要写一个完全支持这些标准格式的解码器相当困难,也没有必要。
如果你需要进行JPEG文件的读写我推荐你使用Intel Jpeg Lib,速度相当令人满意。而GIF由于授权问题,没有任何官方组织提供的读写代码。
如果你只是需要读入JPEG和静态GIF(或者只一帧的动态GIF),我推荐你使用Windows提供的OleLoadPicture函数,下面这段代码可以把一个JPG,GIF,BMP读入到Bitmap对象中:
BOOL CIJLBitmap::Load(LPCTSTR lpszPathName)
{
BOOL bSuccess = FALSE;
file://Free up any resource we may currently have
DeleteObject();
file://open the file