📄 2.1.
字号:
----------------------------------------------------------------------
2.1 抽象类 TCnGraphic
----------------------------------------------------------------------
by 与月共舞(yygw@163.com) 2002.06.01
2.1.1 功能介绍
--------------
TCnGraphic 为 CnPack 快速图像处理库的图像抽象基类,类似于 TGraphic。
两者的相同之处为:
* 都是图像抽象类,包括未实现的 abstract 抽象方法。
* 都提供一些基本的图像属性如 Heihgt、Width、Empty 等。
* 作为持久性对象派生类,都提供了保存图像数据到窗体流的实现框架。
* 都支持更新通知。
两者的不同之处有:
* 派生对象用途不同,TGraphic 的子类用来支持各种格式的图象文件,而
TCnGraphic 仅派生出固定位格式的位图。
* 设计功能不同,TGraphic 及其子类的功能偏向于图像存取和显示,而后者
着重于内部图像数据访问和图像处理。
* TGraphic 支持调色板,而 TCnGraphic 不支持。
* TGraphic 不支持线程安全,而 TCnGraphic 支持。
* TGraphic 派生类大多支持基于引用计数的共享图像数据,而 TCnGraphic
子类不打算支持。
2.1.2 类继承
------------
TCnGraphic 派生自 TCnThreadPersistent 线程安全持久性类。
从 TCnThreadPersistent 中,主要继承了以下几个功能:
* 线程安全机制。
在多线程程序中,可以使用下面的方法来进行线程安全保护:
procedure Lock;
function TryLock: Boolean;
procedure Unlock;
* 更新通知。通过 Changing、Changed、BeginUpdate、EndUpdate 方法和
事件 OnChanging、OnChange 提供属性更新通知功能。
详见 TCnPersistent 的说明。
2.1.3 类属性
------------
TCnGraphic 对外提供以下 public 属性:
* 基本属性
property Height: Integer; 当前图像的高度
property Width: Integer; 当前图像的宽度
* 只读属性
property Empty: Boolean; 当前图像是否为空
property ClientRect: TRect; 当前图像的矩形区域
* 内部数据块属性(只读)
property Bits: Pointer; 图像数据块地址指针
property Buff: Pointer; 内部缓冲区数据块地址指针
property Size: Integer; 当前图像的数据块长度
property RowInc: Integer; 当前图像一行扫描线的存储长度
property Gap: Integer; 为了保证图像数据按4字节对齐而在一行扫
描线数据尾部保留的字节数
这几个属性提供了基于扫描线和象素遍历的方法来快速访问位图数据。
演示代码 1:
var
Col: PCnColor;
x, y: Integer;
begin
Col := Bmp.Bits;
for y := 0 to Bmp.Height - 1 do
begin
for x := 0 to Bmp.Width - 1 do
begin
... // 象素处理代码
Inc(Col); // 下一个象素
end;
Col := Pointer(Integer(Col) + Bmp.Gap); // 行末地址修正
end;
end;
演示代码 2:
var
Src, Dst: PCnLine;
x, y: Integer;
begin
Bmp.UseBuff; // 将当前图像数据复制到内部缓冲区
try
Src := Bmp.Buff; // 缓冲区用做源数据
Dst := Bmp.Bits; // 当前图像为目标数据
for y := 0 to Bmp.Height - 1 do
begin
for x := 0 to Bmp.Width - 1 do
begin
Src^[x] ... // 象素处理代码
Dst^[x] ...
end;
Src := Pointer(Integer(Src) + Bmp.RowInc); // 下一扫描线地址
Dst := Pointer(Integer(Dst) + Bmp.RowInc);
end;
finally
Bmp.FreeBuff; // 释放内部缓冲区
end;
end;
TCnGraphic 提供以下 protected 字段以描述图像类的共性:
protected
FBuff: Pointer;
FBits: Pointer;
FHeight: Integer;
FWidth: Integer;
FRowInc: Integer;
FSize: Integer;
FGap: Integer;
分别与 public 属性相对应,由子类设置。
2.1.4 抽象方法
--------------
TCnGraphic 设计了几个抽象方法,子类必须实现:
* procedure DoSetSize(AWidth, AHeight: Integer); virtual; abstract;
设置图像大小,protected 方法。
该方法在 SetSize 中调用,SetSize 进行了参数比较,更新通知等公共处
理,DoSetSize 只需要实现分配内存、设置 FWidth、FHeight、更新其它
状态等工作。
* procedure LoadFromStream(Stream: TStream); virtual; abstract;
procedure SaveToStream(Stream: TStream); virtual; abstract;
从流中装载和保存位图数据,public 方法。
* procedure DrawToDC(hDst: HDC; DstX, DstY: Integer; Width, Height:
Integer; SrcX, SrcY: Integer); virtual; abstract;
将当前图像绘制到目标DC,通常派生类使用 SetDIBitsToDevice 这个 API
来实现。
2.1.5 虚拟方法
--------------
以下是可供 override 的虚拟方法:
protected 方法
* procedure SetHeight(const Value: Integer); virtual;
procedure SetWidth(const Value: Integer); virtual;
Height、Width 属性的写方法,默认为调用 SetSize。
* function GetEmpty: Boolean; virtual;
Empty 属性的读方法,默认为检查 FBits 是否为 nil。
* procedure DefineProperties(Filer: TFiler); override;
function Equals(Bitmap: TCnGraphic): Boolean; virtual;
procedure ReadData(Stream: TStream); virtual;
procedure WriteData(Stream: TStream); virtual;
这几个方法用于定义 'Data' 属性,在 DFM 流中保存位图数据。
其中 Equals 用于比较两个位图是否完全相等,用在继承窗体数据比较中。
ReadData 和 WriteData 方法使用 LoadFromStream 和 SaveToStream 来工
作。这些方法一般不需要覆盖。
public 方法
* procedure LoadFromFile(const Filename: string); virtual;
procedure SaveToFile(const Filename: string); virtual;
从文件中装载或保存图像,默认使用 LoadFromStream 和 SaveToStream 来
实现。如果这两个方法操作的流中的数据结构与文件结构不一样,需要覆盖
它们。
* procedure UseBuff; virtual;
procedure FreeBuff; virtual;
更新和释放内部缓冲区,用于为图像处理提供临时图像。
很多图像处理操作需要使用当前图像的映象作临时缓冲区,这两个方法用于
操作内部缓冲区,缓冲区用 Buff (FBuff) 来访问。
TCnGraphics 中这两个方法是空方法。
2.1.6 其它设计
--------------
public 方法
* procedure SetSize(AWidth, AHeight: Integer); overload;
procedure SetSize(ARect: TRect); overload;
用来设置当前图像大小,内部调用抽象方法 DoSetSize 来实现。
完整的类结构参见 CnGraphic 单元。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -