GDI+ 在Delphi程序的应用 -- 图像的透明显示技巧
在Delphi中,通过设置TBitmap的Transparent、TransparentColor和TransparentMode属性,可以很方便的实现图像中某种颜色的透明显示;也可以采用某种算法对图像像素逐点计算,实现图像各种形式的透明显示。
使用GDI+,可以比常规方式更方便、快捷的实现图像各种形式的透明显示。本文拟以几个简单的GDI+应用例子来实现图像的透明显示。
一、设置ColorKey,实现图像某种或者某个范围颜色的透明显示。
GDI+的TGpImageAttributes类有个SetColorKey过程,用来设置色键(透明范围),其原形为:
procedure SetColorKey(const colorLow, colorHigh: TARGB; catype: TColorAdjustType = ctDefault);
其中,colorLow 为低色键值; colorHigh 为高色键值,只要颜色成分处于高低色键范围内,该颜色就会成为透明的。需要说明的是:
1、colorLow的R、G、B三个分量必须同时小于colorHigh的R、G、B三个分量,才是有效的ColorKey设置;
2、如果colorLow = colorHigh,则可实现该单色的透明显示。
3、虽然colorLow和colorHigh是TARGB类型,但是色键范围与Alpha分量无关。
下面是个使用ColorKey的例子:
procedureTForm1.Button1Click(Sender:TObject);
var
Image,Mask:TGpImage;
Attr:TGpImageAttributes;
g:TGpGraphics;
W,H:Integer;
begin
Image:=TGpImage.Create('..mediamsn.jpg');
Mask:=TGpImage.Create('..mediaMask1.jpg');
Attr:=TGpImageAttributes.Create;
g:=TGpGraphics.Create(Handle,False);
try
W:=Image.Width;
H:=Image.Height;
g.DrawImage(Image,10,10,W,H);//显示图片原图
g.TranslateTransform(W+4,0);
g.DrawImage(mask,10,10,W,H);//显示掩码原图
Attr.SetColorKey(0,$555555);//设置ColorKey
g.TranslateTransform(W+4,0);
g.DrawImage(Image,10,10,W,H);//混合显示
g.DrawImage(mask,GpRect(10,10,W,H),0,0,W,H,utPixel,Attr);
finally
g.Free;
Attr.Free;
Mask.Free;
Image.Free;
end;
end;
显示效果见图一,左边是原图,中间是一张以中心为圆点的黑色到灰色的渐进色掩码图片,右边是对掩码图设置色键后和原图的混合显示,由于色键范围为黑色(0)- 中灰色($555555),正好是掩码图的中心的一个圆的颜色范围,所以混合后该圆的范围为透明显示。
图一
二、设置颜色重新映射表,实现图像多种颜色的透明或半透明显示。
GDI+的TGpImageAttributes类有个SetRemapTable过程,用来设置颜色重新映射表,其原形为:
procedure SetRemapTable(const map: array of TColorMap; catype: TColorAdjustType = ctDefault);
其中,map是个TColorMap类型数组,其定义为:
TColorMap = packed record
oldColor: TARGB; // 老颜色
newColor: TARGB; // 新颜色
end;
大家一看这个记录类型便知道是用newColor替换oldColor,使由oldColor表示的像素点呈现为newColor的颜色。由于oldColor和newColor是TARGB类型,通过调整TARGB类型的的Alpha分量的值,便可实现各种颜色的透明或半透明显示。例子如下:
procedureTForm1.Button1Click(Sender:TObject);
const
maps:array[0..3]ofTColorMap=(
(oldColor:$FFFF0000;newColor:$00FF0000),
(oldColor:$FF00FFFF;newColor:$5500FFFF),
(oldColor:$FFFF00FF;newColor:$80FF00FF),
(oldColor:$FF00FF00;newColor:$A000FF00)
);
var
Image,Mask:TGpImage;
Attr:TGpImageAttributes;
g:TGpGraphics;
W,H:Integer;
begin
Image:=TGpImage.Create('..mediamsn.jpg');
Mask:=TGpImage.Create('..mediaMask1.bmp');
Attr:=TGpImageAttributes.Create;
g:=TGpGraphics.Create(Handle,False);
try
W:=Image.Width;
H:=Image.Height;
g.DrawImage(Image,10,10,W,H);//显示图片原图
g.TranslateTransform(W+4,0);
g.DrawImage(mask,10,10,W,H);//显示掩码原图
Attr.SetRemapTable(maps);
g.TranslateTransform(W+4,0);
g.DrawImage(Image,10,10,W,H);//混合显示
g.DrawImage(mask,GpRect(10,10,W,H),0,0,W,H,utPixel,Attr);
finally
g.Free;
Attr.Free;
Mask.Free;
Image.Free;
end;
end;
显示效果见图二,左边是原图,中间是一张掩码图片,右边是对掩码图设置颜色重新映射后和原图的混合显示。
掩码图是个由黄、红、青、绿、粉红和蓝等6纯色条组成的图,例子对两边的黄色和蓝色没做处理,因此这两个色条是不透明显示,而对中间4色条作了重新映射,映射时对颜色未作改变,只是将其Alpha值分别修改为0、$55、$80、$A0,所以中间4色条由全透明向大半透明显示过渡。
图二
三、调整颜色矩阵,实现图像的透明显示。
通过调整颜色矩阵(ColorMatrix)的Alpha值,可以轻松的实现图像整体的透明和半透明显示,这也是在GDI+中使用最广泛的技术之一,所谓的水印技术,就是通过调整颜色矩阵实现的。
关于ColorMatrix,很多文章都予以了介绍,我在《GDI+ 在Delphi程序的应用 -- 图像的灰度化》也涉及过它,这里不再讨论。例子如下:
procedureTForm1.Button1Click(Sender:TObject);
const
ColorMatrix:TColorMatrix=
((1.0,0.0,0.0,0.0,0.0),
(0.0,1.0,0.0,0.0,0.0),
(0.0,0.0,1.0,0.0,0.0),
(0.0,0.0,0.0,0.5,0.0),
(0.0,0.0,0.0,0.0,1.0));
var
Image,Mask:TGpImage;
Attr:TGpImageAttributes;
g:TGpGraphics;
W,H:Integer;
begin
Image:=TGpImage.Create('..mediamsn.jpg');
Mask:=TGpImage.Create({'..mediamsn1.gif'}'..mediaMask1.bmp');
Attr:=TGpImageAttributes.Create;
g:=TGpGraphics.Create(Handle,False);
try
W:=Image.Width;
H:=Image.Height;
g.DrawImage(Image,10,10,W,H);//显示图片原图
g.TranslateTransform(W+4,0);
g.DrawImage(mask,10,10,W,H);//显示掩码原图
Attr.SetColorMatrix(ColorMatrix);
g.TranslateTransform(W+4,0);
g.DrawImage(Image,10,10,W,H);//混合显示
g.DrawImage(mask,GpRect(10,10,W,H),0,0,W,H,utPixel,Attr);
finally
g.Free;
Attr.Free;
Mask.Free;
Image.Free;
end;
end;
显示效果见图三,因为ColorMatrix的Alpha位设置为0.5,右边图为6色条码图与主图半透明混合显示。
图三
四、利用GDI+位图扫描线,实现其它特色透明显示
通过调用TGpBitmap的LockBits过程,可获得位图的属性,运用这些属性对位图直接对扫描线地址进行读写操作,也是GDI+最多的图像操作手段之一,LockBits必须和UnLockBits成对使用,其原形如下:
// 将 Bitmap 对象锁定到系统内存中。参数 rect: 它指定要锁定的 Bitmap 部分。
// flags: ImageLockMode 枚举,它指定 Bitmap 对象的访问级别(读和写)。
// format: Bitmap 对象的数据格式
function LockBits(const rect: TGpRect; flags: TImageLockModes; format: TPixelFormat): TBitmapData;
// 从系统内存解锁 Bitmap。
procedure UnlockBits(var lockedBitmapData: TBitmapData);
这其中最重要的参数类型是TBitmapData,它的定义如下:
TBitmapData = packed record // 位图图像的属性
Width: UINT; // 像素宽度。也可以看作是一个扫描行中的像素数。
Height: UINT; // 像素高度。也称作扫描行数。
Stride: INT; // 跨距宽度(也称为扫描宽度)。
PixelFormat: TPixelFormat; // 像素信息的格式
Scan0: Pointer; // 第一个像素数据的地址。也可以看成位图中的第一个扫描行
Reserved: UINT; // 保留
end;
我们直接对图像扫描线操作,离不开这些属性的运用。另外,LockBits的format参数并不要求是图像实际的像素格式,除了Gif格式的图像,其它图像都可根据自己对扫描线操作的需要给定,例如本例子的图像是24位RGB的jpeg格式文件,但是由于要对Alpha操作,必须将format参数设置为32位ARGB格式。
下面举例通过直接对图像扫描线操作,进行图像比较特殊的渐进透明显示。
procedureTForm1.Button1Click(Sender:TObject);
var
Image:TGpBitmap;
g:TGpGraphics;
W,H:Integer;
Data:TBitmapData;
p:PByte;
x,y,Offset:Integer;
begin
Image:=TGpBitmap.Create('..mediamsn.jpg');
g:=TGpGraphics.Create(Handle,False);
try
W:=Image.Width;
H:=Image.Height;
g.DrawImage(Image,10,10,W,H);//显示图片原图
Data:=Image.LockBits(GpRect(0,0,W,H),[imRead,imWrite],pf32bppARGB);
p:=Data.Scan0;
inc(p,3);
Offset:=Data.Stride-W*4;
fory:=0toH-1do
begin
forx:=0toW-1do
begin
p^:=255*xdivW;
Inc(p,4);
end;
Inc(p,Offset);
end;
Image.UnlockBits(Data);
g.TranslateTransform(W+4,0);
g.DrawImage(Image,10,10,W,H);//渐变透明显示
finally
g.Free;
Image.Free;
end;
end;
从例子代码可以看到,我把图像的设置成4个字节的ARGB格式,只对图像像素点的Alpha字节进行了写操作p^ := 255 * x div W,所以开始时指针p就指向了图像第一个像素点的Alpha字节(p := Data.Scan0; Inc(3);),以后通过Inc(p, 4)移到下一个字节,最终就形成左边第一列像素是完全透明显示,右边最后一列像素是不透明显示,中间各列像素为这2种状态的渐进过渡显示。
效果见图四。
图四
以上大部分内容都是本人学习时摸索出的一些方法和技巧,未免有不当和以偏概全甚至完全错误之处,望浏览者予以批评指正。并再次声明,本人使用的GDI+单元是自己写的,与网上流通的不完全兼容,仅供参考。
分享到:
相关推荐
GDI+入门指导书------经典 非常适合于GDI+初学者
windwos C++ gdi++实现jpg图像压缩-图像裁剪和缩放-图像格式转换-图像dpi修改
——在GDI+ Painter应用程序中添加颜色、钢笔和画笔 总结 第5章 颜色、字体和文本 5.1 访问Graphics对象 5.2 使用颜色 5.3 使用字体 5.4 使用文本和字符串 5.5 渲染文本的质量和性能 5.6 高级版式 5.7 一个...
DELPHI版的GDI++库,内有Demos.
——在GDI+ Painter应用程序中添加颜色、钢笔和画笔 总结 第5章 颜色、字体和文本 5.1 访问Graphics对象 5.2 使用颜色 5.3 使用字体 5.4 使用文本和字符串 5.5 渲染文本的质量和性能 5.6 高级版式 5.7 一个...
使用Delphi+GDI实现图片的镜像翻转,有需要的可以试试。
使用GDI+进行图形缩放、拖动,多种图片格式支持,仅简单示例。 问题源贴:http://bbs.csdn.net/topics/390638094
WINDOWS GDI和GDI+编程实例剖析. - READ
GDI+程序设计.pdf,书籍和随书源码。
GDI+程序设计 GDI+程序设计 GDI+程序设计 GDI+程序设计
教你在VC下如何使用GDI+进行 图像程序设计,是整理的比较全的资料。
在Delphi中使用GDI+,范例中包含GDI+各种效果的测试。
一本为C#开发人员准备的图形图像处理技术的书籍
用GDI+做的透明窗体实例,支持png,附模块在目录根。
运用Gdi+技术对图像进行圆形、任意四边形、扇形拉伸,半透明、透度渐变、任意角度旋转等处理。思路不成熟,下载后如有好的思路,共同学习探讨。
Delphi GDI+
GDI+对话框的显示,里面有5个特效和打开文件的代码