GDI+DrawImage

      在指定位置并且按原始大小绘制指定的  Image
  函数名称 及说明
  DrawImage(Image, Point) 在指定的位置使用原始物理大小绘制指定的 Image。
  DrawImage(Image, array<Point>[]()[]) 在指定位置并且按指定形状和大小绘制指定的 Image。
  DrawImage(Image, PointF) 在指定的位置使用原始物理大小绘制指定的 Image。
  DrawImage(Image, array<PointF>[]()[]) 在指定位置并且按指定形状和大小绘制指定的 Image。
  DrawImage(Image, Rectangle) 在指定位置并且按指定大小绘制指定的 Image。
  DrawImage(Image, RectangleF) 在指定位置并且按指定大小绘制指定的 Image。
  DrawImage(Image, Int32, Int32) 在由坐标对指定的位置,使用图像的原始物理大小绘制指定的图像。
  DrawImage(Image, Single, Single) 在指定的位置使用原始物理大小绘制指定的 Image。
  DrawImage(Image, array<Point>[]()[], Rectangle, GraphicsUnit) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, array<PointF>[]()[], RectangleF, GraphicsUnit) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, Rectangle, Rectangle, GraphicsUnit) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, RectangleF, RectangleF, GraphicsUnit) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, array<Point>[]()[], Rectangle, GraphicsUnit, ImageAttributes) 在指定位置绘制指定的 Image 的指定部分。
  DrawImage(Image, array<PointF>[]()[], RectangleF, GraphicsUnit, ImageAttributes) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, Int32, Int32, Rectangle, GraphicsUnit) 在指定的位置绘制图像的一部分。
  DrawImage(Image, Int32, Int32, Int32, Int32) 在指定位置并且按指定大小绘制指定的 Image。
  DrawImage(Image, Single, Single, RectangleF, GraphicsUnit) 在指定的位置绘制图像的一部分。
  DrawImage(Image, Single, Single, Single, Single) 在指定位置并且按指定大小绘制指定的 Image。
  DrawImage(Image, array<Point>[]()[], Rectangle, GraphicsUnit, ImageAttributes, Graphics..::.DrawImageAbort) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, array<PointF>[]()[], RectangleF, GraphicsUnit, ImageAttributes, Graphics..::.DrawImageAbort) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, array<Point>[]()[], Rectangle, GraphicsUnit, ImageAttributes, Graphics..::.DrawImageAbort, Int32) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, array<PointF>[]()[], RectangleF, GraphicsUnit, ImageAttributes, Graphics..::.DrawImageAbort, Int32) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, Rectangle, Int32, Int32, Int32, Int32, GraphicsUnit) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, Rectangle, Single, Single, Single, Single, GraphicsUnit) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, Rectangle, Int32, Int32, Int32, Int32, GraphicsUnit, ImageAttributes) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, Rectangle, Single, Single, Single, Single, GraphicsUnit, ImageAttributes) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, Rectangle, Int32, Int32, Int32, Int32, GraphicsUnit, ImageAttributes, Graphics..::.DrawImageAbort) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, Rectangle, Single, Single, Single, Single, GraphicsUnit, ImageAttributes, Graphics..::.DrawImageAbort) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。
  DrawImage(Image, Rectangle, Int32, Int32, Int32, Int32, GraphicsUnit, ImageAttributes, Graphics..::.DrawImageAbort, IntPtr) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。

  DrawImage(Image, Rectangle, Single, Single, Single, Single, GraphicsUnit, ImageAttributes, Graphics..::.DrawImageAbort, IntPtr) 在指定位置并且按指定大小绘制指定的 Image 的指定部分。

GDI+ DrawImage的应用  

在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的例子:
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分量的值,便可实现各种颜色的透明或半透明显示。 例子如下:
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程序的应用 -- 图像的灰度化》也涉及过它,这里不再讨论。例子如下:

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格式。
下面举例通过直接对图像扫描线操作,进行图像比较特殊的渐进透明显示。
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种状态的渐进过渡显示。

 


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值