|
|
Posted on
2009-10-21 12:06
SunM
阅读( 3695)
评论()
收藏
举报
在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的例子:
 Code procedure TForm1.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.GetWidth; H := Image.GetHeight; 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, unitPixel, Attr); finally g.Free; Attr.Free; Mask.Free; Image.Free; end; end;
--------------------------------------------------------------------- 二、设置颜色重新映射表,实现图像多种颜色的透明或半透明显示。 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分量的值,便可实现各种颜色的透明或半透明显示。例子如下:
 Code procedure TForm1.Button1Click(Sender: TObject); const maps: array[0..3] of TColorMap = ( (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;
--------------------------------------------------------------------- 三、调整颜色矩阵,实现图像的透明显示。 通过调整颜色矩阵(ColorMatrix)的Alpha值,可以轻松的实现图像整体的透明和半透明显示,这也是在GDI+中使用最广泛的技术之一,所谓的水印技术,就是通过调整颜色矩阵实现的。 关于ColorMatrix,很多文章都予以了介绍,我在《GDI+ 在Delphi程序的应用 -- 图像的灰度化》也涉及过它,这里不再讨论。例子如下:  Code procedure TForm1.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; --------------------------------------------------------------------- 四、利用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格式。 下面举例通过直接对图像扫描线操作,进行图像比较特殊的渐进透明显示。  Code procedure TForm1.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;
for y := 0 to H - 1 do begin for x := 0 to W - 1 do begin p^ := 255 * x div W; 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种状态的渐进过渡显示。
|