-= r.left;
y -= r.top;
if (x > 0)
{
r.left += x;
x = 0;
}
if (y > 0)
{
r.top += y;
y = 0;
}
// 计算data传输到DC的实际尺寸到图像数据dst
tmp.Width = r.right - r.left;
tmp.Height = r.bottom - r.top;
tmp.Reserved = 0;
if (!GetSubBitmapData(&tmp, x, y, data->Width, data->Height, &dst))
return;
// 按32位像素格式分配dst扫描线内存
dst.Stride = dst.Width << 2;
dst.Scan0 = scan0 = (LPVOID)new CHAR[dst.Height * dst.Stride];
// 计算data与DC的交集子图像数据
if (x < 0) x = -x;
if (y < 0) y = -y;
GetSubBitmapData(data, x, y, dst.Width, dst.Height, &src);
GetBitmapInfoHeader(&src, &bi);
// 如果alpha<1,或者data含Alpha信息,获取DC原图形到dst
if (alphaI < 255 || (data->Reserved & PixelAlphaFlag));
GetDCImageData(DC, r.left, r.top, &dst, &bi);
// dst扫描线内存转换成Windows位图格式
dst.Scan0 = (LPBYTE)scan0 + (dst.Height - 1) * dst.Stride;
dst.Stride = -dst.Stride;
// 图像混合
ImageMixer(&dst, &src, alphaI);
// 还原dst扫描线内存格式后,传输到DC
dst.Scan0 = scan0;
BitBltImageData(DC, r.left, r.top, &dst, &bi);
delete[] scan0;
}
//---------------------------------------------------------------------------
ImageDraw函数实现了直接显示BitmapData位图数据到设备DC。其中的几个步骤都作了注释,这里不再 嗦,至于其中调用的Windows API,也请参见Windows API大全之类的书籍。
下面将《图像(层)正常混合模式详解(上)》中的例子修改一下,将其中的GDI+的Graphics对象显示位图,改为上面的ImageDraw函数直接显示位图数据结构:
void __fastcall TForm1::Button4Click(TObject *Sender)
{
Gdiplus::Bitmap *dest = new Gdiplus::Bitmap(L"d:\\xmas_011.png");
Gdiplus::Bitmap *source = new Gdiplus::Bitmap(L"d:\\Apple.png");
BitmapData dst, src;
LockBitmap(dest, &dst);
LockBitmap(source, &src);
ImageDraw(Canvas->Handle, 0, 0, &dst);
ImageDraw(Canvas->Handle, dst.Width, 0, &src);
ImageMixer(&dst, &src, 192);
ImageDraw(Canvas->Handle, dst.Width + src.Width, 0, &dst);
UnlockBitmap(source, &src);
UnlockBitmap(dest, &dst);
delete source;
delete dest;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
Gdiplus::Bitmap *dest = new Gdiplus::Bitmap(L"d:\\xmas_011.png");
Gdiplus::Bitmap *source = new Gdiplus::Bitmap(L"d:\\Apple.png");
BitmapData dst, src;
LockBitmap(dest, &dst);
LockBitmap(source, &src);
ImageDraw(Canvas->Handle, 0, 0, &dst);
ImageDraw(Canvas->Handle, dst.Width, 0, &src);
ImageMixer(&dst, &src, 192);
ImageDraw(Canvas->Handle, dst.Width + src.Width, 0, &dst);
UnlockBitmap(source, &src);
UnlockBitmap(dest, &dst);
delete source;
delete dest;
}
//---------------------------------------------------------------------------
显示效果同http://www.2cto.com/kf/201201/116377.html中的例子运行效果,其截图可参见上面的贴图。显示速度看起来也不会比GDI+的Graphics对象慢(没测试),但如果将http://www.2cto.com/kf/201201/116377.html中的几个混合子函数进行一些优化,其显示速度肯定超过会GDI+的Graphics对象。
水平有限,错误在所难免,欢迎指正和指导。邮箱地址:maozefa@hotmail.com
摘自 闲人阿发伯的业余编程心得