第一章 圖像處理在可視化編程中的作用及其應用價值
圖像處理,是可視化編程的基礎內容。
在Windows操作系統中,一切要輸出到屏幕上的東西都是通過圖形處理這部分的內容來實現的。
比如一個程序使用了標簽控件,它看起來似乎並沒有用到什麼圖形處理,但實際上標簽控件就是通過使用GDI庫中的圖形處理函數來實現的。可見圖形處理在編程中的重要性。
圖像處理在實際的應用中也極具價值。
平面制作、動畫制作等都離不開它。這一部分的內容十分繁多。我本次研究的內容,只是其中最基礎的、最重要一部分。
探究Delphi的圖形處理 之二 -- 基本圖像處理函數
第二章 圖像處理函數
2.1 為什麼選擇Delphi
所有的可視化編程語言都能夠進行圖像處理。但由於這些語言的定位不同,它們在進行圖形處理的效率和便捷程度上也各不相同。
實際上,Visual C 的圖像處理效率是最高的,Delphi已經把絕大多數GDI繪圖函數都封裝成可直接調用的類,使用它進行圖形處理操作十分方便,而且Delphi 是Pascal演變而來的,Pascal具有嚴謹易讀的特點,因此很容易上手。
2.2 Delphi中用於圖形處理的類
Delphi為我們提供了許多圖形圖像方面的類,合理地使用這些類,我們可以方便地開發出各種圖形處理程序。
這些類有TPicture、TBitmap、TGraphic、TIcon、TJPEGImage和TCanvas。其中,
TCanvas類用於繪圖,
TPicture、TBitmap、TIcon和TJPEGImage是專門用來處理圖片的類,
TGraphic是一個抽象類,一般不直接使用。
TPicture類可以載入所有支持的圖片,
而TBitmap、TIcon、TJPEGImage分別用於處理各種類型的圖片。
在實際應用中,我們一般用這些具體類型的類載入圖片,再將圖片轉為Bitmap格式來處理。TPicture、TIcon、TJPEGImage類一般只用於輸入和輸出。例如,下面的代碼可以載入一幅任意支持格式的圖片(Delphi所支持的格式為bmp、jpg、dib、wmf和emf)。
[delphi]
Var Pic:TPicture;
Var Pic:TPicture;[delphi] view plaincopyprint?Begin
Pic := TPicture.Create;
Pic.LoadFromFile(FileName);
End;
Begin
Pic := TPicture.Create;
Pic.LoadFromFile(FileName);
End;
用TPicture類來載入圖片時,該類會根據文件名的擴展名來決定用何等方式來打開圖片。
這就出現了一個問題,如果這個圖片的擴展名被用戶非法修改,程序就會把這個圖片視為無效圖片。在真正編程中,我們要用TPicture、TBitmap、TJPEGImage、TIcon依次嘗試去打開圖片。
另外,Delphi本身是不支持GIF文件格式的。我們可以借用一個第三方的類——GIFImage來讓Delphi支持它。這個類在附帶的光盤中可以找到。最終我們用下面的代碼來完成載入圖片的操作。
Procedure ReadPicture(FileName: String; Bitmap: Graphics.TBitmap);
var pic:TPicture;Bit:Graphics.TBitmap;jpgPic:TJPEGImage;FGifPic:TGIFImage;
icoPic:TIcon;
begin
FGifPic := TGifImage.Create;
Pic:=Tpicture.Create;
bit:=Graphics.TBitmap.Create;
jpgPic:=TJPEGImage.Create;
icoPic:=TIcon.Create;
try
pic.LoadFromFile(FileName);
if uppercase(ExtractFileExt(Filename)) = '.ICO' then begin
Bitmap.Height:=pic.Height;
Bitmap.Width:=Pic.Width;
Bitmap.Canvas.Draw(0,0,Pic.Graphic);
end
else
bitmap.Assign(pic.Graphic);
except
try
bitmap.LoadFromFile(FileName);
except
try
jpgPic.LoadFromFile(FileName);
bitmap.Assign(jpgPic);
except
try
icoPic.LoadFromFile(Filename);
bitmap.Free;
Bitmap:=TBitmap.Create;
bitmap.Height:=icoPic.Height;
bitmap.Width:=icoPic.Width;
bitmap.Canvas.Draw(0,0,icoPic);
except
try
FgifPic.LoadFromFile(FileName);
Bitmap.Assign(FGifPic.Bitmap);
except
bitmap.Height:=bitmap.Canvas.TextHeight('8');
bitmap.Width:=bitmap.Canvas.TextWidth('無效圖片');
BitMap.Canvas.TextOut(0,0,'無效圖片');
end;{try}
end;
end;{try}
end;{try}
end;{try}
Pic.Free ;
bit.Free;
jpgPic.Free;
icoPic.Free;
FGifPic.Free;
end;
保存圖片的方法跟打開圖片的方法類似,我們可以使用不同類型的圖片類的SaveToFile方法保存文件。下面的代碼可以根據文件名中擴展名的不同使用不同的類來保存Bitmap。
Procedure SaveBitmap(FileName: String; PicB: TBitmap);
var pic:TPicture; FileExt:String;picJPG:TJPEGImage;picGIF:TGIFImage;
begin
pic:=TPicture.Create;
picJPG:=TJPEGImage.Create;
picGIF:=TGIFImage.Create;
try
pic.Assign(PicB);
FileExt:= ExtractFileEXT(FileName);
if (Uppercase(FileExt)='.JPG')or(Uppercase(FileExt)='.JPEG')
or(Uppercase(FileExt)='.JPE') then
begin
picJPG.Assign(PicB);
picJPG.SaveToFile(FileName);
end
else If (UpperCase(FileExt)='.BMP')OR(UpperCase(FileExt)='.DIB')THEN
Begin
PicB.SaveToFile(FileName);
end
else if (UpperCase(FileExt)='.GIF') then begin
picGIF.Assign(PicB);
PicGIF.SaveToFile(FileName);
end
else
Pic.SaveToFile(FileName);
{End If}
ShowPicture(PictureIndex,False,TPicture(PicB));
Finally
pic.Free;
picJPG.Free;
PicGIF.Free;
end;
end;
探究Delphi的圖形處理 之三 -- GDI及Canvas類簡介
作者:何詠 發布日期:(2005-4-12 21:
2.3 GDI及Canvas類簡介
GDI(Graphics Device Interface,圖形設備接口)是Windows為我們提供的一個專門用於圖形繪制和屏幕輸出的類庫。
這個類庫提供了許多繪圖函數,使用這些函數,我們幾乎可以開發出所有的平面繪制、平面處理的程序。它同時也是Windows系統的核心,Windows系統中所有的繪圖任務都由這個庫來完成。在任何語言中,我們都可以調用這個庫來完成繪圖任務。
在Delphi中,我們已經有了一個已經封裝了絕大多數GDI函數的類。使用這個類我們可以方便的完成各種圖像處理任務。這就是我們要研究的Canvas類。
探究Delphi的圖形處理 之四 -- Canvas類中的基本繪圖方法
作者:何詠 發布日期:(2005-4-12 21:04:21)
Canvas類中的基本繪圖方法
Canvas就是“畫布”的意思,使用Canvas類中的繪圖方法,我們可以在這塊畫布上繪制各種圖形。我們也可以通過設置每一個象素的顏色值來完成對圖像的處理。下面列出了Canvas類中的一些常用繪圖方法。
CopyRect(Dest:TRect;Canvas:TCanvas;Source:TRect);
此方法用於把Canvas所指定的畫布的一部分(由Source指定)復制到當前畫布中。Dest參數指定了復制後的圖像在當前畫布中的位置。例如下面的語句:
ThisCanvas.CopyRect(Rect(5,5,20,20),SourceCanvas,Rect(10,10,25,25));
可以把SourceCanvas中的(10,10,25,25)這一區域復制到ThisCanvas中的(5,5,20,20)區域中。
值得注意的是,TRect是一個Record類型的變量,用Rect的構造函數可以創建一個Rect變量。Rect類型所指定的區域是一個長方形,由(x1,y1,x2,y2)兩個點來確定。例如,Rect(10,10,25,25)所確定的就是下圖所示的區域:
Draw(x,y:Integer;Graphic:TGraphic);
此方法可以在當前畫布中,以(x,y)為繪圖原點繪制由Graphic所指定的圖形或圖片。
Ellips(x1,y1,x2,y2:Integer);
此方法可以在當前畫布中,以(x1,y1),(x2,y2)兩點所指定的矩形范圍內繪制一個橢圓。並用畫筆中所指定的顏色作為線條顏色,筆刷的顏色作為填充顏色。
MoveTo(x,y:Integer);
把畫筆的位置移動到點(x,y)。
LineTo(x,y:Integer);
從畫筆當前的位置繪制一條直線到點(x,y),並把畫筆的位置移動到(x,y);
Polygon(Points:array of TPoint);
以Points中的點為頂點繪制一個多邊形。並用畫筆中所指定的顏色作為線條顏色,筆刷的顏色作為填充顏色。
StretchDraw(Const Rect:TRect;Graphic : TGraphic);
此方法可以在由Rect所指定的區域中繪制圖片,圖片會根據Rect的大小自動縮放。
Rectangle(x1,y1,x2,y2);
繪制由(x1,y1),(x2,y2)所確定的矩形。並用畫筆中所指定的顏色作為線條顏色,筆刷的顏色作為填充顏色。
TextOut(x,y:Integer;Text:String);
以(x,y)為原點繪制參數Text所指定的文字。
TextHeight(Text:String);
返回在當前字體設置下,Text所指定的字符串的高度。
TextWidth(Text:String);
返回在當前字體設置下,Text所指定的字符串的寬高度。
除了這些基本繪圖方法外,Canvas類中還有一些重要的屬性,它們是:
Pen(畫筆)
這個屬性包含很多項目,其中Color指定了畫筆的顏色,Weight指定了畫筆的寬度,PenMode指定了畫筆繪圖的方式。
Brush(筆刷)
這個屬性主要決定了圖形的填充方式。Color指定了填充顏色,BrushStyle決定了填充方式。
Font(字體)
它決定了在Canvas中,使用TestOut命令畫出的文字的字體和字號。
Pixels(象素數組)
這個數組包含了Canvas中每一個象素的顏色值。
在一般的編程中,我們在需要進行象素級的圖像調整時,一般不使用Pixels屬性。在Bitmap(位圖)類中提供了一個ScanLine屬性,使用它我們可以快速地進行象素讀取和設置。這在後面的章節中有詳細的說明。
Canvas類中所提供的繪圖方法遠遠不止上面提到的這些,本文檔所羅列的只是我認為最常用的方法,更多的信息可以參考Delphi的幫助系統。
探究Delphi的圖形處理 之五 -- 使用Canvas類繪圖
作者:何詠 發布日期:(2005-4-12 21:03:21)
使用Canvas類繪圖
我們知道,在Canvas類中可以完成各種繪圖操作。仔細觀察,會發現在Delphi提供的許多組件中,都有Canvas類。這是因為這些組件都繼承自TGraphicControl基類,這個基類就提供了Canvas類。
但我們並不滿足於直接使用它們的Canvas來繪圖,這是沒有效率的。因為TGraphicControl是一個可視化控件,當我們在這些控件上繪圖時,繪制的圖形會即時地翻印到前台(即用戶的屏幕)上,而很多時候,我們希望在繪圖結束後才將圖像翻到前台,這樣可以大大提高工作效率。這裡就使用到了一個緩沖的思想。即在內存中開一塊空間,在這塊空間上繪圖,繪圖完後,再將這塊空間中的圖像翻印到前台。
這裡,我們可以使用Delphi為我們提供的TBitmap(位圖)類。這個類也提供了Canvas類,我們同樣可以在這個Canvas類上繪圖。繪制完後,我們用 控件名.Canvas.Draw(0,0,Bitmap)把這個位圖翻到前台。
下面的例子可以在PaintBox上繪制一個漸變顏色的矩形。
程序2.1
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TfrmMain = class(TForm)
PaintBox1: TPaintBox;
btnDraw: TButton;
procedure btnDrawClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.btnDrawClick(Sender: TObject);
var Bit:TBitmap;
i:Integer;
begin
Bit := TBitmap.Create;
try
Bit.Height := 300;
Bit.Width := 387;
For i := 0 to 200 do begin
Bit.Canvas.MoveTo(50,i+50);
Bit.Canvas.Pen.Color := RGB(0,0,Round((1-(i)/200) * 255));
Bit.Canvas.LineTo(350,i+50);
end;
PaintBox1.Canvas.Draw(0,0,Bit);
finally
Bit.Free;
end;
end;
end.