Delphi7 图形图像编程
- 格式:ppt
- 大小:627.50 KB
- 文档页数:29
TShape组件的属性,事件和方法TImage组件的属性,事件和方法Paintbox组件的属性,事件和方法使用鼠标事件的绘图第 9章图像图形应用编程9.1 图形应用编程本章主要是讲解图形图像对象的概念以及如何在程序运行时绘制图形图像等内容,主要是通过一些例子来讲解 Delphi 7.0 对图形图像强大的处理功能。
在 Delphi 7.0中,专门定义了一组对象和部件用以绘制图形,完成一些简单的图像功能。
利用这些对象、部件的方法,可以方便地绘制各种常用图形;通过设置它们的属性,得到不同风格的图形。
另外,通过鼠标事件的定义,可以方便地设计图形绘制程序。
9.1.1 画布对象属性在图形应用编程中,最常用到的是 canvas类,就是常说的画布。
它可以将某些组件的表面作为一张画布,允许编程者利用有关的命令在其上任意地作图。
很多组件都支持画布这个属性,同时画布本身又是一个对象,它也有自己的属性,但是这些属性必须要在程序执行时才可以来进行设置。
常用的属性有以下几个。
( 1)图形像素数组( PixArray)属性PixArray属性确定用于像素颜色的读取和像素颜色的设置。
( 2)画笔( Pen)属性Pen属性确定画布用做画线及轮廓线的画笔。
9.1.1 画布对象属性 (1)( 3)画刷( Brush)属性Brush属性确定画布用于填充图像及背景色的颜色及图案。
( 4)字体( Font)属性Font属性确定画布的字体。
1,像素像素是构成图形的最基本的单位,画布上每一个点都有对应的像素,用来代表构成一个图形的某一点的颜色。
像素的处理一般包括像素颜色的读取和像素颜色的设置。
最常用的是利用画布的 Pixels属性,来绘制函数曲线。
【例 9-1】用 Pixels属性来画 Y=X的函数曲线。
运行后的界面如图 9-1所示。
图 9-1 用像素来画图主要的功能如下:单击显示按钮,在屏幕上就可以画出 Y=X的函数图。
主要的程序代码如下:图 9-1 用像素来画图9.1.1 画布对象属性 (2)procedure TForm1.Button1Click(Sender,TObject);VAR xt,yt,t:integer; //xt,yt是用来决定像素的位置,t用来控制循环次数。
Delphi中怎么编写图像解析组件Delphi中怎么编写图像解析组件Delphi作为一个强大的RAD研发工具,在应用软件的研发方面一直有着他的独特优势。
这种优势同样体目前图像相关软件的研发上。
如果你要在桌面上放置一张图像,只需要简单的在桌面上放置一个Image控件,然后就能通过其Image属性任意的加载BMP、WMF、EMF等格式的图像。
如果还想增加对JPEG的支持,只需要添加一个JPEG单元即可。
甚至在Image中加载一张JPEG后,Delphi会自动添加一个JPEG单元。
一切做起来就是这么的简单。
基本格式都已封装在了VCL中,那么Delphi对类似JPEG这样图像格式的支持是怎么实现的呢?其实从TPicture中非常容易看出其中的实现过程,他能理解为所有图像对象的容器。
如JPEG.pas中有如下两句代码:TPicture.RegisterFileFormat(jpeg, sJPEGImageFile, TJPEGImage);TPicture.RegisterFileFormat(jpg, sJPEGImageFile, TJPEGImage);(sJPEGImageFile = JPEG Image File,见JConsts.pas)什么意思呢?能理解为将TJPEGImage注册为jpeg、jpg两种后缀图像文件的类。
其实质就是将后缀,图像描述,具体图像解析类等信息保存到了FileFormats。
具体见如下代码:var FileFormats: TFileFormatsList = nil;class procedure TPicture.RegisterFileFormat(const AExtension,ADescription: string; AGraphicClass: TGraphicClass);beginGetFileFormats.Add(AExtension, ADescription, 0, AGraphicClass);end;function GetFileFormats: TFileFormatsList;beginif FileFormats = nil then FileFormats := TFileFormatsList.Create;Result := FileFormats;end;而TPicture默认支持四种图像格式是因为TFileFormatsList的构造函数中已进行了添加。
delphi7编程技巧与实例精解之图形图像(修正重绘变形)unit Unit1;interfaceusesWin do ws, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, ComCtrls, ExtCtrls, StdCtrls;typeTForm1 = class(TForm)img1: TImage;btn1: TButton;btn2: TButton;tmr1: TTimer;tb1: TTrackBar;dlgOpen1: TOpenDialog;rg1: TRadioGroup;procedure FormCreate(Sender: TObject);procedure tb1Change(Sender: TObject);procedure btn1Click(Sender: TObject);procedure tmr1Timer(Sender: TObject);procedure btn2Click(Sender: TObject);private{ Private declarations }public{ Public declarations }end;varForm1: TForm1;i: Integer;L,T,R,B: Integer;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject); beginT:= Img1.Top;l:= img1.Left;b:= img1.Top+ img1.Height;r:= img1.Left+ img1.Width;end;procedure TForm1.tb1Change(Sender: TObject); begintmr1.Interval:= tb1.Position;end;procedure TForm1.btn1Click(Sender: TObject); vark: Integer;beginCanvas.Pen.Color:= Form1.Color;if rg1.ItemIndex<2 then beginfor k:= 0 to b do beginCanvas.MoveTo(0,k);Canvas.LineTo(r,k);end;end else if rg1.ItemIndex=2 then beginfor k:=0 to b+4 do beginCanvas.MoveTo(0,k);Canvas.LineTo(r,k);end;end;tmr1.Enabled:= True;i:= 0;end;procedure TForm1.tmr1Timer(Sender: TObject);varx,y: Integer;beginif rg1.ItemIndex=0 then beginSelf.Canvas.CopyRect(Rect(l,t+i,r,t+i+1),img1.Canvas,Rec t(0,0+i,img1.Width,0+i+1));Self.Canvas.CopyRect(Rect(l,b-i,r,b-i+1),img1.Canvas,Rect(0,img1.Height-i,img1.Width,img1.Height-i+1));i:= i+1;if i>b/2-1 then tmr1.Enabled:= False;end else if rg1.ItemIndex=1 then beginSelf.Canvas.CopyRect(Rect(l,t+i*4,r,t+i*4+2),img1.Canvas ,Rect(0,0+i*4,img1.Width,0+i*4+2));Self.Canvas.CopyRect(Rect(l,b-i*4-2,r,b-I*4),img1.Canvas,Rect(0,img1.Height-i*4-2,img1.Width,img1.Height-i*4));i:= i+1;if i>img1.Height/4 then tmr1.Enabled:= False;end else if rg1.ItemIndex=2 then beginfor x:= 0 to (img1.Width div 8 ) do beginfor y:= 0 to (img1.Height div 8 ) do begincase i of0:Self.Canvas.CopyRect(Rect(l+x*8,t+y*8,l+x*8+4,t+y*8+4),im g1.Canvas,Rect(0+x*8,0+y*8,0+x*8+4,0+y*8+4));1:Self.Canvas.CopyRect(Rect(l+x*8+4,t+y*8+4,l+x*8+8,t+y*8+ 8),img1.Canvas,Rect(0+x*8+4,0+y*8+4,0+x*8+8,0+y*8+8));2:Self.Canvas.CopyRect(Rect(L+x*8,t+y*8+4,l+x*8+4,t+y*8+8) ,img1.Canvas,Rect(0+x*8,0+y*8+4,0+x*8+4,0+y*8+8));3:Self.Canvas.CopyRect(Rect(l+x*8+4,t+y*8,l+x*8+8,t+y*8+4), img1.Canvas,Rect(0+x*8+4,0+y*8,0+x*8+8,0+y*8+4));end;end;end;i:= i+1;if i>3 then tmr1.Enabled:= False;end;end;procedure TForm1.btn2Click(Sender: TObject);beginif not dlgOpen1.Execute then Exit;img1.Picture.LoadFromFile(dlgOpen1.FileName);T:= Img1.Top;l:= img1.Left;b:= img1.Top+ img1.Height;r:= img1.Left+ img1.Width;end;end.。
本文实例汇总了Delphi基本图像处理方法。
分享给大家供大家参考。
具体分析如下: //浮雕 procedureEmboss(SrcBmp,DestBmp:TBitmap;AzimuthChange:integer;overload; var i, j, Gray, Azimuthvalue, R, G, B: integer; SrcRGB, SrcRGB1, SrcRGB2, DestRGB: pRGBTriple; begin for i := 0 to SrcBmp.Height - 1 do begin SrcRGB := SrcBmp.ScanLine[i]; DestRGB := DestBmp.ScanLine[i]; if (AzimuthChange >= -180 and (AzimuthChange < -135 then begin if i > 0 then SrcRGB1 := SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB; Inc(SrcRGB1; SrcRGB2 := SrcRGB; Inc(SrcRGB2; end else if (AzimuthChange >= -135 and (AzimuthChange < -90 then begin if i > 0 thenSrcRGB1 := SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; Inc(SrcRGB2; end else if (AzimuthChange >= -90 and (AzimuthChange < -45 then begin if i > 0 then SrcRGB1 := SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; end else if (AzimuthChange >= -45 and (AzimuthChange < 0 then begin SrcRGB1 := SrcRGB; if i > 0 then SrcRGB2 := SrcBmp.ScanLine[i-1] else SrcRGB2 := SrcRGB; end else if (AzimuthChange >= 0 and (AzimuthChange < 45 then begin SrcRGB2 := SrcRGB; if (i < SrcBmp.Height - 1 then SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB; end else if (AzimuthChange >= 45 and (AzimuthChange < 90 then begin if (i < SrcBmp.Height - 1 then SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; end else if (AzimuthChange >= 90 and (AzimuthChange < 135 then begin if (i < SrcBmp.Height - 1 then SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; Inc(SrcRGB1; end else if (AzimuthChange >= 135 and (AzimuthChange <= 180 then begin if (i < SrcBmp.Height - 1 then SrcRGB2 := SrcBmp.ScanLine[i+1] else SrcRGB2 := SrcRGB; Inc(SrcRGB2; SrcRGB1 := SrcRGB; Inc(SrcRGB1; end; for j := 0 to SrcBmp.Width - 1 do begin if (AzimuthChange >= -180 and (AzimuthChange < -135 then begin Azimuthvalue := AzimuthChange + 180; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= -135 and (AzimuthChange < -90 then begin Azimuthvalue := AzimuthChange + 135; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= -90 and (AzimuthChange < -45 then begin if j=1 then Inc(SrcRGB1,-1; Azimuthvalue := AzimuthChange + 90;R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= -45 and (AzimuthChange < 0 then begin if j=1 then begin Inc(SrcRGB1,-1; Inc(SrcRGB2,-1; end; Azimuthvalue := AzimuthChange + 45; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= 0 and (AzimuthChange < 45 then begin if j=1 then begin Inc(SrcRGB1,-1; Inc(SrcRGB2,-1; end; Azimuthvalue := AzimuthChange; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= 45and (AzimuthChange < 90 then begin if j=1 then Inc(SrcRGB2,-1; Azimuthvalue := AzimuthChange - 45; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= 90 and (AzimuthChange < 135 then begin Azimuthvalue := AzimuthChange - 90;R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end else if (AzimuthChange >= 135 and (AzimuthChange <= 180 then begin Azimuthvalue := AzimuthChange - 135;R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed*Azimuthvalue div 45-((SrcRGB2.rgbtRed*(45-Azimuthvalue div 45+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen*Azimuthvalue div 45-((SrcRGB2.rgbtGreen*(45-Azimuthvalue div 45+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue*Azimuthvalue div 45-((SrcRGB2.rgbtBlue*(45-Azimuthvalue div 45+78; end; R:=Min(R,255; R:=Max(R,0; G:=Min(G,255; G:=Max(G,0; B:=Min(B,255; B:=Max(B,0; Gray := (R shr 2 + (R shr 4 + (G shr 1 + (G shr 4 + (B shr 3; DestRGB.rgbtRed:=Gray; DestRGB.rgbtGreen:=Gray; DestRGB.rgbtBlue:=Gray; if (j=-180 and (AzimuthChange<-135 or ((AzimuthChange>=90 and (AzimuthChange<=180 then begin Inc(SrcRGB1; end; if (j=135 and (AzimuthChange<180 or ((AzimuthChange>=-180 and (AzimuthChange<=-90 then begin Inc(SrcRGB2; end;Inc(SrcRGB; Inc(DestRGB; end; end; end; procedureEmboss(Bmp:TBitmap;AzimuthChange:integer;ElevationChange:integer;WeightChange: integer;overload; var DestBmp:TBitmap; begin DestBmp:=TBitmap.Create; DestBmp.Assign(Bmp;Emboss(Bmp,DestBmp,AzimuthChange,ElevationChange,WeightChange;Bmp.Assign(DestBmp; end; //反色 procedure Negative(Bmp:TBitmap; var i, j: Integer; PRGB: pRGBTriple; begin Bmp.PixelFormat:=pf24Bit; for i := 0 to Bmp.Height - 1 do begin PRGB := Bmp.ScanLine[i]; for j := 0 to Bmp.Width - 1 do beginPRGB^.rgbtRed :=not PRGB^.rgbtRed ; PRGB^.rgbtGreen :=not PRGB^.rgbtGreen; PRGB^.rgbtBlue :=not PRGB^.rgbtBlue; Inc(PRGB; end; end; end; //曝光 procedure Exposure(Bmp:TBitmap; var i, j: integer; PRGB: pRGBTriple; beginBmp.PixelFormat:=pf24Bit; for i := 0 to Bmp.Height - 1 do begin PRGB :=Bmp.ScanLine[i]; for j := 0 to Bmp.Width - 1 do begin if PRGB^.rgbtRed<128 then PRGB^.rgbtRed :=not PRGB^.rgbtRed ; if PRGB^.rgbtGreen<128 thenPRGB^.rgbtGreen :=not PRGB^.rgbtGreen; if PRGB^.rgbtBlue<128 thenPRGB^.rgbtBlue :=not PRGB^.rgbtBlue; Inc(PRGB; end; end; end; //模糊 procedure Blur(SrcBmp:TBitmap; var i, j:Integer; SrcRGB:pRGBTriple; SrcNextRGB:pRGBTriple; SrcPreRGB:pRGBTriple; Value:Integer; procedure IncRGB; begin Inc(SrcPreRGB;Inc(SrcRGB; Inc(SrcNextRGB; end; procedure DecRGB; begin Inc(SrcPreRGB,-1;Inc(SrcRGB,-1; Inc(SrcNextRGB,-1; end; begin SrcBmp.PixelFormat:=pf24Bit; for i := 0 to SrcBmp.Height - 1 do begin if i > 0 then SrcPreRGB:=SrcBmp.ScanLine[i-1] else SrcPreRGB := SrcBmp.ScanLine[i]; SrcRGB := SrcBmp.ScanLine[i]; if i <SrcBmp.Height - 1 then SrcNextRGB:=SrcBmp.ScanLine[i+1] elseSrcNextRGB:=SrcBmp.ScanLine[i]; for j := 0 to SrcBmp.Width - 1 do begin if j > 0 then DecRGB; Value:=SrcPreRGB.rgbtRed+SrcRGB.rgbtRed+SrcNextRGB.rgbtRed; if j > 0 then IncRGB;Value:=Value+SrcPreRGB.rgbtRed+SrcRGB.rgbtRed+SrcNextRGB.rgbtRed; if j < SrcBmp.Width - 1 then IncRGB;Value:=(Value+SrcPreRGB.rgbtRed+SrcRGB.rgbtRed+SrcNextRGB.rgbtRed div 9; DecRGB; SrcRGB.rgbtRed:=value;if j > 0 then DecRGB;Value:=SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen; if j > 0 thenIncRGB;Value:=Value+SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen; if j < SrcBmp.Width - 1 then IncRGB;Value:=(Value+SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen div 9; DecRGB; SrcRGB.rgbtGreen:=value; if j > 0 then DecRGB;Value:=SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue; if j > 0 then IncRGB; Value:=Value+SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue; if j < SrcBmp.Width - 1 then IncRGB;Value:=(Value+SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue div 9; DecRGB; SrcRGB.rgbtBlue:=value; IncRGB; end; end; end; //锐化 procedureSharpen(SrcBmp:TBitmap; var i, j: integer; SrcRGB: pRGBTriple; SrcPreRGB: pRGBTriple; Value: integer; begin SrcBmp.PixelFormat:=pf24Bit; for i := 0 to SrcBmp.Height - 1 do begin SrcRGB := SrcBmp.ScanLine[i]; if i > 0 then SrcPreRGB:=SrcBmp.ScanLine[i-1] else SrcPreRGB:=SrcBmp.ScanLine[i]; for j := 0 to SrcBmp.Width - 1 do begin if j = 1 then Dec(SrcPreRGB;Value:=SrcRGB.rgbtRed+(SrcRGB.rgbtRed-SrcPreRGB.rgbtRed div 2;Value:=Max(0,Value; Value:=Min(255,Value; SrcRGB.rgbtRed:=value;Value:=SrcRGB.rgbtGreen+(SrcRGB.rgbtGreen-SrcPreRGB.rgbtGreen div 2;Value:=Max(0,Value; Value:=Min(255,Value; SrcRGB.rgbtGreen:=value;Value:=SrcRGB.rgbtBlue+(SrcRGB.rgbtBlue-SrcPreRGB.rgbtBlue div 2;Value:=Max(0,Value; Value:=Min(255,Value; SrcRGB.rgbtBlue:=value; Inc(SrcRGB; Inc(SrcPreRGB; end; end; end; [图像的旋转和翻转] 以下代码用ScanLine配合指针移动实现,用于24位色! //旋转90度 procedure Rotate90(const Bitmap:TBitmap; var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap; Width,Height:Integer; begin Bmp:=TBitmap.Create; Bmp.Width := Bitmap.Height; Bmp.Height := Bitmap.Width; Bmp.PixelFormat := pf24bit; Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do begin rowIn := Bitmap.ScanLine[j]; for i := 0 to Width do beginrowOut := Bmp.ScanLine[i]; Inc(rowOut,Height - j; rowOut^ := rowIn^; Inc(rowIn; end;end; Bitmap.Assign(Bmp; end; //旋转180度 procedure Rotate180(constBitmap:TBitmap; var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap;Width,Height:Integer; begin Bmp:=TBitmap.Create; Bmp.Width := Bitmap.Width; Bmp.Height := Bitmap.Height; Bmp.PixelFormat := pf24bit; Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do begin rowIn := Bitmap.ScanLine[j]; for i := 0 to Width do begin rowOut := Bmp.ScanLine[Height - j]; Inc(rowOut,Width - i; rowOut^ := rowIn^; Inc(rowIn; end; end; Bitmap.Assign(Bmp; end; //旋转270度procedure Rotate270(const Bitmap:TBitmap; var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap; Width,Height:Integer; begin Bmp:=TBitmap.Create; Bmp.Width := Bitmap.Height; Bmp.Height := Bitmap.Width; Bmp.PixelFormat :=pf24bit; Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do begin rowIn := Bitmap.ScanLine[j]; for i := 0 to Width do begin rowOut :=Bmp.ScanLine[Width - i]; Inc(rowOut,j; rowOut^ := rowIn^; Inc(rowIn; end; end; Bitmap.Assign(Bmp; end; //任意角度 functionRotateBitmap(Bitmap:TBitmap;Angle:Integer;BackColor:TColor:TBitmap; vari,j,iOriginal,jOriginal,CosPoint,SinPoint : integer; RowOriginal,RowRotated : pRGBTriple; SinTheta,CosTheta : Extended; AngleAdd : integer; beginResult:=TBitmap.Create; Result.PixelFormat := pf24bit;Result.Canvas.Brush.Color:=BackColor; Angle:=Angle Mod 360; if Angle<0 then Angle:=360-Abs(Angle; if Angle=0 then Result.Assign(Bitmap else if Angle=90 then begin Result.Assign(Bitmap; Rotate90(Result;//如果是旋转90度,直接调用上面的代码 end else if (Angle>90 and (Angle<180 then begin AngleAdd:=90; Angle:=Angle-AngleAdd; end else if Angle=180 then begin Result.Assign(Bitmap; Rotate180(Result;//如果是旋转180度,直接调用上面的过程 end else if (Angle>180 and (Angle<270 then begin AngleAdd:=180; Angle:=Angle-AngleAdd; end else if Angle=270 then begin Result.Assign(Bitmap; Rotate270(Result;//如果是旋转270度,直接调用上面的过程end else if (Angle>270 and (Angle<360 then begin AngleAdd:=270; Angle:=Angle-AngleAdd; end else AngleAdd:=0; if (Angle>0 and (Angle<90 then begin SinCos((Angle+ AngleAdd * Pi / 180, SinTheta, CosTheta; if (SinTheta * CosTheta < 0 then begin Result.Width := Round(Abs(Bitmap.Width * CosTheta - Bitmap.Height * SinTheta; Result.Height := Round(Abs(Bitmap.Width * SinTheta - Bitmap.Height * CosTheta; end else begin Result.Width := Round(Abs(Bitmap.Width * CosTheta + Bitmap.Height * SinTheta; Result.Height := Round(Abs(Bitmap.Width * SinTheta + Bitmap.Height * CosTheta; end; CosTheta:=Abs(CosTheta; SinTheta:=Abs(SinTheta; if (AngleAdd=0 or (AngleAdd=180 then begin CosPoint:=Round(Bitmap.Height*CosTheta;SinPoint:=Round(Bitmap.Height*SinTheta; end else beginSinPoint:=Round(Bitmap.Width*CosTheta; CosPoint:=Round(Bitmap.Width*SinTheta; end; for j := 0 to Result.Height-1 do begin RowRotated := Result.Scanline[j]; for i := 0 to Result.Width-1 do begin Case AngleAdd of 0: begin jOriginal := Round((j+1*CosTheta-(i+1-SinPoint*SinTheta-1; iOriginal := Round((i+1*CosTheta-(CosPoint-j-1*SinTheta-1; end; 90: begin iOriginal := Round((j+1*SinTheta-(i+1-SinPoint*CosTheta-1; jOriginal := Bitmap.Height-Round((i+1*SinTheta-(CosPoint-j-1*CosTheta; end; 180: begin jOriginal := Bitmap.Height-Round((j+1*CosTheta-(i+1-SinPoint*SinTheta; iOriginal := Bitmap.Width-Round((i+1*CosTheta-(CosPoint-j-1*SinTheta; end; 270: begin iOriginal := Bitmap.Width-Round((j+1*SinTheta-(i+1-SinPoint*CosTheta; jOriginal := Round((i+1*SinTheta-(CosPoint-j-1*CosTheta-1; end; end; if (iOriginal >= 0 and (iOriginal <= Bitmap.Width-1and (jOriginal >= 0 and (jOriginal <=Bitmap.Height-1 then begin RowOriginal := Bitmap.Scanline[jOriginal];Inc(RowOriginal,iOriginal; RowRotated^ := RowOriginal^; Inc(RowRotated; end else begin Inc(RowRotated; end; end; end; end; end; //水平翻转 procedure FlipHorz(const Bitmap:TBitmap; var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap;Width,Height:Integer; begin Bmp:=TBitmap.Create; Bmp.Width := Bitmap.Width; Bmp.Height := Bitmap.Height; Bmp.PixelFormat := pf24bit; Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do begin rowIn := Bitmap.ScanLine[j]; for i := 0 to Width do begin rowOut := Bmp.ScanLine[j]; Inc(rowOut,Width - i; rowOut^ := rowIn^; Inc(rowIn; end; end; Bitmap.Assign(Bmp; end; //垂直翻转 procedureFlipVert(const Bitmap:TBitmap; var i,j:Integer; rowIn,rowOut:pRGBTriple;Bmp:TBitmap; Width,Height:Integer; begin Bmp:=TBitmap.Create; Bmp.Width := Bitmap.Height; Bmp.Height := Bitmap.Width; Bmp.PixelFormat := pf24bit;Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do beginrowIn := Bitmap.ScanLine[j]; for i := 0 to Width do begin rowOut :=Bmp.ScanLine[Height - j]; Inc(rowOut,i; rowOut^ := rowIn^; Inc(rowIn; end; end; Bitmap.Assign(Bmp; end; [亮度、对比度、饱和度的调整] 以下代码用ScanLine配合指针移动实现! function Min(a, b: integer: integer; begin if a < b then result := a else result := b; end; function Max(a, b: integer: integer; begin if a > b then result := a else result := b; end; //亮度调整 procedure BrightnessChange(constSrcBmp,DestBmp:TBitmap;ValueChange:integer; var i, j: integer; SrcRGB, DestRGB: pRGBTriple; begin for i := 0 to SrcBmp.Height - 1 do begin SrcRGB :=SrcBmp.ScanLine[i]; DestRGB := DestBmp.ScanLine[i]; for j := 0 to SrcBmp.Width - 1 do begin if ValueChange > 0 then begin DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + ValueChange; DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange; DestRGB.rgbtBlue := Min(255, SrcRGB.rgbtBlue + ValueChange; end else begin DestRGB.rgbtRed := Max(0, SrcRGB.rgbtRed + ValueChange; DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + ValueChange; DestRGB.rgbtBlue := Max(0,SrcRGB.rgbtBlue + ValueChange; end; Inc(SrcRGB; Inc(DestRGB; end; end; end; //对比度调整 procedure ContrastChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer; var i, j: integer; SrcRGB, DestRGB: pRGBTriple; begin for i := 0 to SrcBmp.Height - 1 do begin SrcRGB := SrcBmp.ScanLine[i]; DestRGB := DestBmp.ScanLine[i]; for j := 0 to SrcBmp.Width - 1 do begin if ValueChange>=0 then begin if SrcRGB.rgbtRed >= 128 then DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + ValueChange else DestRGB.rgbtRed := Max(0, SrcRGB.rgbtRed - ValueChange; if SrcRGB.rgbtGreen >= 128 then DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange else DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen - ValueChange; ifSrcRGB.rgbtBlue >= 128 then DestRGB.rgbtBlue := Min(255, SrcRGB.rgbtBlue + ValueChange else DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue - ValueChange; end else begin if SrcRGB.rgbtRed >= 128 then DestRGB.rgbtRed := Max(128,SrcRGB.rgbtRed + ValueChange else DestRGB.rgbtRed := Min(128, SrcRGB.rgbtRed - ValueChange; if SrcRGB.rgbtGreen >= 128 then DestRGB.rgbtGreen := Max(128, SrcRGB.rgbtGreen + ValueChange else DestRGB.rgbtGreen := Min(128,SrcRGB.rgbtGreen - ValueChange; if SrcRGB.rgbtBlue >= 128 thenDestRGB.rgbtBlue := Max(128, SrcRGB.rgbtBlue + ValueChange elseDestRGB.rgbtBlue := Min(128, SrcRGB.rgbtBlue - ValueChange; end; Inc(SrcRGB; Inc(DestRGB; end; end; end; //饱和度调整 procedure SaturationChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer; var Grays: array[0..767] of Integer; Alpha: array[0..255] of Word; Gray, x, y: Integer; SrcRGB,DestRGB: pRGBTriple; i: Byte; begin ValueChange:=ValueChange+255; for i := 0 to 255 do Alpha[i] := (i * ValueChange Shr 8; x := 0; for i := 0 to 255 do begin Gray := i - Alpha[i]; Grays[x] := Gray; Inc(x; Grays[x] := Gray; Inc(x; Grays[x] := Gray; Inc(x; end; for y := 0 to SrcBmp.Height - 1 do begin SrcRGB := SrcBmp.ScanLine[Y]; DestRGB := DestBmp.ScanLine[Y]; for x := 0 to SrcBmp.Width - 1 do begin Gray :=Grays[SrcRGB.rgbtRed + SrcRGB.rgbtGreen + SrcRGB.rgbtBlue]; if Gray +Alpha[SrcRGB.rgbtRed]>0 then DestRGB.rgbtRed := Min(255,Gray +Alpha[SrcRGB.rgbtRed] else DestRGB.rgbtRed := 0; if Gray +Alpha[SrcRGB.rgbtGreen]>0 then DestRGB.rgbtGreen := Min(255,Gray +Alpha[SrcRGB.rgbtGreen] else DestRGB.rgbtGreen := 0; if Gray +Alpha[SrcRGB.rgbtBlue]>0 then DestRGB.rgbtBlue := Min(255,Gray +Alpha[SrcRGB.rgbtBlue] else DestRGB.rgbtBlue := 0; Inc(SrcRGB; Inc(DestRGB; end; end; end; //RGB调整 procedureRGBChange(SrcBmp,DestBmp:TBitmap;RedChange,GreenChange,BlueChange:integer; var SrcRGB, DestRGB: pRGBTriple; i,j:integer; begin for i := 0 to SrcBmp.Height- 1 dobegin SrcRGB := SrcBmp.ScanLine[i]; DestRGB :=DestBmp.ScanLine[i]; for j := 0 to SrcBmp.Width - 1 do begin if RedChange> 0 then DestRGB.rgbtRed:= Min(255, SrcRGB.rgbtRed + RedChange else DestRGB.rgbtRed := Max(0, SrcRGB.rgbtRed + RedChange; if GreenChange> 0 then DestRGB.rgbtGreen :=Min(255, SrcRGB.rgbtGreen + GreenChange else DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + GreenChange; if BlueChange> 0 then DestRGB.rgbtBlue :=Min(255, SrcRGB.rgbtBlue + BlueChange else DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue + BlueChange; Inc(SrcRGB; Inc(DestRGB; end; end; end; [颜色调整] //RGB<=>BGR procedure RGB2BGR(const Bitmap:TBitmap; var X: Integer; Y: Integer; PRGB: pRGBTriple; Color: Byte; begin for Y := 0 to (Bitmap.Height - 1 do begin forX := 0 to (Bitmap.Width - 1 do begin Color := PRGB^.rgbtRed; PRGB^.rgbtRed := PRGB^.rgbtBlue; PRGB^.rgbtBlue := Color; Inc(PRGB; end; end end; end; //灰度化(加权 procedure Grayscale(const Bitmap:TBitmap; var X: Integer; Y: Integer; PRGB: pRGBTriple; Gray: Byte; begin for Y := 0 to (Bitmap.Height - 1 do begin PRGB := Bitmap.ScanLine[Y]; for X := 0 to (Bitmap.Width - 1 do begin Gray := (77 * Red + 151 * Green + 28 * Blue shr 8; PRGB^.rgbtRed:=Gray; PRGB^.rgbtGreen:=Gray;PRGB^.rgbtBlue:=Gray; Inc(PRGB; end; end; end; 绘图区-即窗口显示图像的区域,亦可为全屏幕(在全屏幕下绘图的效果比一般窗口下好)中心点-即要绘图区显示的中心点在原始图像的坐标(声明:这个概念特别重要)先说说图像的放大,要放大一张图片,我们一般的做法是直接放大图像,但本文介绍的方法仅放大我们能够看到的部分,放大分两种情况,一种是放大后比绘图区还要小,这种情况没什么好说,当然是显示全部的图像;第二种是放大后的图像比绘图区大,这才是我们今天要讨论的重点话题,这种情况下我们先要确定图像放大后的大小,然后根据“中心点”计算在原始图像的位置和大小,最后把截取的图像放大到绘图区。
{这一课我会教您如何使用三种不同的纹理滤波方式。
教您如何使用键盘来移动场景中的对象,还会教您在OpenGL场景中应用简单的光照。
这一课包含了很多内容,如果您对前面的课程有疑问的话,先回头复习一下。
进入后面的代码之前,很好的理解基础知识十分重要。
我们还是在第一课的代码上加以修改。
跟以前不一样的是,只要有任何大的改动,我都会写出整段代码。
首先我们还要加进SysUtils单元和Glaux单元。
}UsesSysUtils,opengl,windows,Messages,Glaux In '..\..\GLAUX\Glaux.pas';//下面几行是增加新的变量。
//我们增加三个布尔变量。
// light 变量跟踪光照是否打开。
//变量lp和fp用来存储'L' 和'F'键是否按下的状态。
//后面我会解释这些变量的重要性。
现在,先放在一边吧。
light : Boolean; // 光源的开/关lp : Boolean; // L键按下了么?fp : Boolean; // F键按下了么?//现在设置5个变量来控制绕x轴和y轴旋转角度的步长,//以及绕x轴和y轴的旋转速度。
//另外还创建了一个z变量来控制进入屏幕深处的距离。
xrot : GLfloat; // X 旋转yrot : GLfloat; // Y 旋转xspeed : GLfloat; // X 旋转速度yspeed : GLfloat; // Y 旋转速度z : GLfloat = -5.0 f; // 深入屏幕的距离//接着设置用来创建光源的数组。
//我们将使用两种不同的光。
//第一种称为环境光。
环境光来自于四面八方。
//所有场景中的对象都处于环境光的照射中。
//第二种类型的光源叫做漫射光。
//漫射光由特定的光源产生,并在您的场景中的对象表面上产生反射。
//处于漫射光直接照射下的任何对象表面都变得很亮,//而几乎未被照射到的区域就显得要暗一些。
在Delphi中,专门定义了一组对象和部件用以绘制图形,完成一些简单的图像功能。
利用这些对象、部件的方法,可以方便地绘制各种常用图形;通过设置它们的属性,能得到不同风格的图形。
另外,通过对鼠标事件的定义,可以方便的设计图形绘制程序。
本章将介绍以下内容:1. TCanvas,TPen,TBrush,TColor对象的方法及属性;2. 绘图功能的实现;3. TImage,TPicture,TBitBtn,TBitmap部件的方法及属性;4. 图像观测及处理。
Graphex.dpr是一个简单的图形图像应用程序,是对以上这些对象和组件的具体应用。
本章将结合此程序进行讲述。
5.1 图形对象概述5.1.1 TCanvas Object(画布对象)TCanvas对象是一个用于绘图的表面,在这个区域上,程序可实现各种绘图功能,很多部件(如TIMage,TMemo)的Canvas属性就是TCanvas对象。
在部件上绘制图形就是在部件的画布上绘制。
TCanvas的Brush,Pen,Font属性分别是TBrush,TPen,TFont对象,它们用于定义绘制图形的风格。
关于TBrush,TPen对象,下节中将详细介绍。
画布的笔的位置定义在PenPos属性中,可用MoveTo方法来移动笔。
如果要在画布上输出文本,可用Textout方法。
TCanvas有对象很多方法,可完成常用的绘图功能,现将方法及功能简介如表5.1:表5.1 TCanvas对象的方法━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━方法名称形式及说明───────────────────────────────────────Arc Arc(x1,y1,x2,y2,x3,y3,x4,y4 : Integer);Arc方法在椭圆上画一段弧,椭圆由(x1,y1),(x2,y2) 两点所确定的椭圆所决定。
弧的起点是椭圆圆周和椭圆中心与(x3,y3)连线的交点。
Delphi7图片格式转换例程本例将制作一个应用程序,用来转换图片的格式,运行界面如图:图 1点击“打开图像”按钮,可以从弹出的对话框中选择合适的图像打开。
如果打开的图像是bmp格式的图片,点击“BMP转灰度”按钮,可以将原来彩色的BMP图像转换成灰色度的图像,并弹出保存对话框,以便保存转换后的图像。
如图2所示。
点击“BmpToJpeg”按钮,将BMP格式转换成JPG格式,同时弹出保存对话框,保存转换后的图像。
如果打开的图像是JPG格式的图片,“BMP转灰度”按钮和“BmpToJpeg”按钮无效。
点击“JpegToBmp”按钮,将JPG格式转换成BMP格式,同时弹出保存对话框,保存转换后的图像。
点击“退出程序”按钮,关闭此应用程序。
设计思想本例用到的控件主要是Image控件,Panel控件,OpenPictureDialog控件,SavePictureDialog控件,Button控件,Label控件等。
BMP格式是Windows系统中标准的图像文件格式,具有极强的通用性。
但其突出的缺点是文件过于庞大。
目前Jpg格式的图片得到了广泛的应用,它的大小仅为BMP格式文件的1/10左右,而且图像品质并没有明显的损失。
在许多情况下,我们需要在BMP和JPG 两种图像格式之间进行转换。
图 2 BMP转灰度后的图像BMP格式的图像是由像素组成的,一副彩色的图像包含了许多个像素点,每个像素都包含了三原色R,G,B。
如果将单一的灰色赋值给彩色图像的各个像素,彩色图像就变成了灰色的黑白图像。
本程序主要分为以下几个步骤实现:(1)、在窗口上放置各个控件,并设置它们的属性;(2)、实现打开图像的功能,利用OpenPictureDialog控件的相关事件来实现;(3)、实现彩色bmp格式的图像转换成黑白图像,需要自定义相关函数实现;(4)、实现BMP与JPG两中格式之间的转换是最关键的问题。
打开图像文件后,针对图像的不同格式进行相关事件的响应,需要用到LowerCase(s) ,ExtractFileExt()等相关函数。