由Delphi中的图像灰度化代码看基本图像处理
Delphi中改变图片(bitmap)的亮度、对比度、饱和度
Delphi中改变图⽚(bitmap)的亮度、对⽐度、饱和度最近在做视频处理相关的⼯作,遇到⼀些图⽚处理的问题,从别处找到解决的代码。
其中对⽐度调节的代码处理结果看起来不太舒服,暂时没时间仔细研究,先放在这⾥。
// 改亮度function ChangeBrightness(bmp: TBitmap; s: Integer): Boolean;varp: PByteArray;x, y: Integer;begintry//24位真彩⾊Bmp.PixelFormat := pf24Bit;bmp.Canvas.Lock;for y := 0 to Bmp.Height - 1 dobeginp := Bmp.scanline[y];for x := 0 to Bmp.Width - 1 dobegin//每个象素点的R、G、B分量进⾏调节beginif s > 0 thenbeginp[x * 3] := Min(255, p[x * 3] + s); //不能越界,限制在0~255p[x * 3 + 1] := Min(255, p[x * 3 + 1] + s);p[x * 3 + 2] := Min(255, p[x * 3 + 2] + s);endelsebeginp[x * 3] := max(0, p[x * 3] + s); //不能越界,限制在-255~0p[x * 3 + 1] := max(0, p[x * 3 + 1] + s);p[x * 3 + 2] := max(0, p[x * 3 + 2] + s);end;end;end;end;bmp.Canvas.Unlock;Result := true;exceptResult := false;end;end;// 改对⽐度function ChangeContrast(bmp: TBitmap; s: Integer): Boolean;constCMid = 128;CMin = 10;CMax = 246;varp: PByteArray;x, y: Integer;begintry//24位真彩⾊Bmp.PixelFormat := pf24Bit;bmp.Canvas.Lock;for y := 0 to Bmp.Height - 1 dobeginp := Bmp.ScanLine[y];for x := 0 to Bmp.Width - 1 dobegin//确定阀值为128if (p[x*3] > CMid) and (p[x*3] <= CMax)and (p[x*3+1] > CMid) and (p[x*3+1] <= CMax)and (p[x*3+2] > CMid) and (p[x*3+2] <= CMax) thenbeginp[x*3] := Min(255, p[x*3] + s * p[x*3] div (p[x*3]+p[x*3+1]+p[x*3+2]));p[x*3+1]:= Min(255, p[x*3+1]+ s * p[x*3+1] div (p[x*3]+p[x*3+1]+p[x*3+2]));p[x*3+2]:= Min(255, p[x*3+2]+ s * p[x*3+2] div (p[x*3]+p[x*3+1]+p[x*3+2]));end;if (p[x*3] > CMin) and (p[x*3] <= CMid)and (p[x*3+1] > CMin) and (p[x*3+1] <= CMid)and (p[x*3+2] > CMin) and (p[x*3+2] <= CMid) thenbeginp[x*3] := Max(0, p[x*3] - s * p[x*3] div (p[x*3]+p[x*3+1]+p[x*3+2]));p[x*3+1]:= Max(0, p[x*3+1]- s * p[x*3+1] div (p[x*3]+p[x*3+1]+p[x*3+2])); p[x*3+2]:= Max(0, p[x*3+2]- s * p[x*3+2] div (p[x*3]+p[x*3+1]+p[x*3+2])); end;end;end;bmp.Canvas.Unlock;Result := true;exceptResult := false;end;end;// 改饱和度function ChangeSaturation(bmp: TBitmap; ValueChange: Integer): Boolean; constCMax = 255;varGrays: array[0..767] of Integer;Alpha: array[0..255] of Word;Gray, x, y: Integer;SrcRGB: PRGBTriple;i: Byte;beginValueChange := ValueChange + 255;for i := 0 to CMax dobeginAlpha[i] := (i * ValueChange) shr 8;end;x := 0;for i := 0 to CMax dobeginGray := i - Alpha[i];Grays[x] := Gray;Inc(x);Grays[x] := Gray;inc(x);Grays[x] := Gray;Inc(x);end;for y := 0 to bmp.Height - 1 dobeginSrcRGB := bmp.ScanLine[y];for x := 0 to bmp.Width - 1 dobeginGray := Grays[SrcRGB.rgbtRed + SrcRGB.rgbtBlue + SrcRGB.rgbtGreen]; if Gray + Alpha[SrcRGB.rgbtRed] > 0 thenSrcRGB.rgbtRed := Min(CMax, Gray + Alpha[SrcRGB.rgbtRed])elseSrcRGB.rgbtRed := 0;if Gray + Alpha[SrcRGB.rgbtGreen] > 0 thenSrcRGB.rgbtGreen := Min(CMax, Gray + Alpha[SrcRGB.rgbtGreen])elseSrcRGB.rgbtGreen := 0;if Gray + Alpha[SrcRGB.rgbtBlue] > 0 thenSrcRGB.rgbtBlue := Min(CMax, Gray + Alpha[SrcRGB.rgbtBlue])elseSrcRGB.rgbtBlue := 0;Inc(SrcRGB);end;end;end;。
Delphi实现计算机视觉常用图像处理算法
第 2 卷 第 5期 6
20 0 7年 5月
实 验
室 研
究 与 探
索
V0 . 6 No 5 12 . Ma 0 7 v2 0
R E ES ARCH AND E L XP ORAT ON I AB I N L ORA OR T Y
下:
( 2 ) 2 6 0 0 — al oe l @ cu teu c 0 3 6 4 13 ;图形 , 成一 些简 单 的 图像功 能。利 用这些 对 完 象、 部件 的方法 , 以方便地绘制各种常用图形 ; 可 通过 设置 它们 的属性 , 能得 到不 同风 格 的 图形 。另外 , 过 通 对鼠标事件的定义 , 可以方便地设计 图形绘制程序。
D lh 中的各 图像编 程 对象 见 图 1 epi 。
( fc f a 、a dE up e t d iirt n h n qn n .o ot a dT lcm, h n qn 0 0 5 hn ) O f eo L b n q im n m ns a o ,C o g igU i f s n e o C og ig4 0 6 ,C ia i A t i v P s e
Ab t a t ma e p o e sn n ov sl t fp o r mmi g.He c o t e e ta p o r mmi o lwi i lct n s r c :I g r c s i g i v le o s o r g a n n e h w o s lc r g a ng t o t smp iiy a d h h g f ce c e a n u a od b e p o l m n c mp e — s d d g tli g o e sn . Fo ee e c i h e i n y b c me a n v i a l r b e i o utrba e i i ma e pr c s i g i a r r fr n e,t s a t l hi ri e c i l me t d t e i g r c s i l o ih n c mmo s t l h . mp e n e h ma e p o e sng ag rt ms i o n u e wi De p i h Ke r y wo ds:c mpue iin;d gtli g r c s i g;De p i o trv so iia ma e p o e sn l h
Delphi图形图像处理
见例子
画矩形
StretchDraw StretchDraw(Const Rect : TRcct : Graphic : TGraphic); 此方法在Rect参数指定的矩形内画一图像。图像 延伸改变大小以适应矩形。 Rectangle Rectangle(X1,y1,x2,y2 : Integer); Rectangle方法在画布上用当前画刷绘制矩形, (x1,y1)是矩形的左上角,(x2,y2)是矩形的右下 角。
三.图像对象概述 3.1. TGraphic对象
TGraphic对象是 TBitmap ,TIcon,Tmetafile对象的基类。 如果知道图像的具体类型( 如位图, 图标 元文件) , 则应将图像贮存在相应类型的 对象中( 如TBitmap,TIcon,Tmetafile), 否则应该使用可贮存任何图像类型的 TPicture对象。
把点连成线
Polygon Polygon(Points : array of TPrint); Polygon方法在画布上绘制一系列的点,各点依 次连成线,最后将首尾两点相接形成一个区域, 并用当前笔刷填充此区域。 Polyline Polyline(Ports : array of TPort); Polyline方法在画布上用当前画笔绘制一系列的 点,各点依次连成线。
Tbrush对象方法
(1)Assign:向另一个对象赋值 (2)Create:创建一个TBrush对象实例。 (3)Destroy:释放一个TBrush对象实例。 (4)OwnHandle:用来确保对更基本的Qbrush 类实例的权限。当需要接受QBrush handle使用 或销毁权限时需要用到这个过程。 (5)ReleaseHandle:用来把TBrush 从 QBrush handle中分离出来,当需要把TBrush handle 给一段程序或一个类时,用到这个函数。
Delphi基本图像处理方法.
本文实例汇总了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; 绘图区-即窗口显示图像的区域,亦可为全屏幕(在全屏幕下绘图的效果比一般窗口下好)中心点-即要绘图区显示的中心点在原始图像的坐标(声明:这个概念特别重要)先说说图像的放大,要放大一张图片,我们一般的做法是直接放大图像,但本文介绍的方法仅放大我们能够看到的部分,放大分两种情况,一种是放大后比绘图区还要小,这种情况没什么好说,当然是显示全部的图像;第二种是放大后的图像比绘图区大,这才是我们今天要讨论的重点话题,这种情况下我们先要确定图像放大后的大小,然后根据“中心点”计算在原始图像的位置和大小,最后把截取的图像放大到绘图区。
Delphi中GDI+实现图像二值化
Delphi中GDI+实现图像⼆值化// 灰度或者⼆值化彩⾊图像procedure GrayImage(Image: TGpImage; Threshold: Single = 0.0);constColorMatrix: TColorMatrix =((0.3, 0.3, 0.3, 0.0, 0.0),(0.59, 0.59, 0.59, 0.0, 0.0),(0.11, 0.11, 0.11, 0.0, 0.0),(0.0, 0.0, 0.0, 1.0, 0.0),(0.0, 0.0, 0.0, 0.0, 1.0));varTmp: TGpImage;attr: TGpImageAttributes;g: TGpGraphics;beginTmp := Image.Clone;g := TGpGraphics.Create(Image);attr := TGpImageAttributes.Create;tryattr.SetColorMatrix(ColorMatrix); // 灰度化if Threshold > 0.0then // 如果给出了阀值,在灰度图基础上⼆值化attr.SetThreshold(Threshold);g.DrawImage(Tmp, GpRect(0, 0, Image.Width, Image.Height),0, 0, Tmp.Width, Tmp.Height, utPixel, attr);finallyg.Free;attr.Free;Tmp.Free;end;end;procedure TForm1.Button1Click(Sender: TObject);varImage: TGpImage;g: TGpGraphics;beginImage := TGpImage.Create('..mediaFRUIT.jpg');g := TGpGraphics.Create(Handle, False);g.DrawImage(Image, 10, 10, Image.Width, Image.Height);GrayImage(Image, 0.5);g.DrawImage(Image, 220, 10, Image.Width, Image.Height);g.Free;image.Free;end;从例⼦可以看出,彩⾊图像⼆值化,就是在其灰度化基础上给定⼀个0 - 1之间的阀值,所谓阀值就是每种颜⾊成分的分界点。
Delphi的图形处理
Delphi的图形处理Delphi的图形处理......................................................................................................- 1 - 第一章图像处理在可视化编程中的作用及其应用价值.................................- 2 - 第二章图像处理函数.......................................................................................- 2 -2.1 为什么选择Delphi..............................................................................- 2 -2.2 Delphi中用于图形处理的类...............................................................- 2 -2.3 GDI及Canvas类简介.........................................................................- 4 -第三章基本图像处理算法.............................................................................- 13 -3.1柔化和锐化处理.........................................................................................- 13 -3.2 图像混合(透明度)效果..............................................................................- 19 -3.3 转为灰度图像............................................................................................- 22 -3.4 对比度调整和反色处理.............................................................................- 23 -3.5 亮度的调整................................................................................................- 25 -3.6 浮雕效果....................................................................................................- 28 -3.7 马赛克效果................................................................................................- 31 -第一章图像处理在可视化编程中的作用及其应用价值图像处理,是可视化编程的基础内容。
delphi中的图像处理
图像处理基本知识彩色变灰度把一图由彩色变成灰度,也就是把每个像素的RGB各分量变为相同的,就成了灰度图像了pf24bit 模式下用BMP 的ScanLine 可以读取每一行的RGB数据.得到的是一个指针字节顺序是B,G,R亮度Y = 0.229R + 0.587G + 0.114B这个公式相当重要.以后很多图像处理都要用到它.方法1:方法一很简单,把RGB各分量相加,计算平均值,再设为新的RGB方法2:找出RGB 各分量中最大的.再设成新的RGB 值方法3:根据工式: Y = 0.229R + 0.587G + 0.114B算出亮度.新的RGB 各分量都为这个值.(个人认为第三种方法比较科学)代码:(方法一. 其它方法类似)bmp := TBitmap.Create;Bmp.Assign(Image1.Picture.Bitmap);bmp.HandleType :=bmDIB;bmp.PixelFormat := pf24bit;for j := 0 to bmp.Height -1 dobeginp := bmp.ScanLine[j];for i := 0 to Bmp.Width - 1 dobegingray1 :=Byte( (p[i*3] + p[i*3+1] + p[i*3+2]) div 3);p[i*3] := gray1;p[i*3+1]:= gray1;p[i*3+2] := gray1;end;end;Image2.Picture.Bitmap.Assign(bmp);bmp.free;==============================二值化:与灰度不同,二值化只有两种颜色.一般在做一些识别时用得比较多.方法:1, 计算出像素的亮度, 定义一个亮度阈值.2. 亮度大于这个阈值的像素,颜色为白,小于这个阈值的像素,颜色为黑.=======================================亮度调节取各个像素的RGB值,按比例加/减一个增量.也许用亮度公式来算出这个比例,比较科学.按一定比例,把部分的RGB 提升,一部分下降.================================-====Gamma校正(不太明白用在哪里.)分别把RGB 设为Min(255, round(255 * Power((OldValue / 256), 0.45))); NewValue := 255 乘(OldValue /256) 的 0.45 次方======================反色各分量取反.======================爆光小于128的取反。
基于Delphi语言的数字图像处理实验系统设计
基于Delphi语言的数字图像处理实验系统设计刘书杰;周晓峰【摘要】介绍了一种利用Object Pascal面向对象语言Delphi 7.0软件开发平台,并结合Bussiness Skin Form界面控件,实现基本的图像处理,并可以对学生信息的添加、修改、保存、删除、按条件对学生信息进行查询管理的实验系统。
【期刊名称】《长春大学学报》【年(卷),期】2012(022)008【总页数】4页(P945-948)【关键词】数字图像处理;实验系统;Delphi;7.0【作者】刘书杰;周晓峰【作者单位】长春中医药大学附属医院,长春130117【正文语种】中文【中图分类】TP317.4数字图像处理作为一门学科大约形成于20世纪60年代初期。
早期图像处理的目的是改善图像的质量,它以人为对象,以改善人的视觉效果为目的。
随着计算机技术的发展,图像处理技术已经运用到了工业、军事、医学等很多方面。
而图像处理也变成了一个复杂而繁琐的过程,常常一项简单的图像处理过程需要多个图像处理算法共同完成。
如果临时编写算法的话不仅算法的正确性难以保证,而且对于不熟悉编程的人来说是件困难的事。
本文给出一种基于Dlephi语言的数字图像处理系统。
给学生提供一个不受时间地点、实验设备限制的实验环境,还能提供多种算法,对数字图像进行效果的美化加工。
\[11\]数字图像管理实验系统是图像处理实验系统与管理实验系统相结合的数据库应用程序。
根据数字图像处理实验系统的具体实现情况,实验系统的主要功能应包括:\[5\]\[7\](1)登录功能:分教师登录与学生登录;(2)管理功能:教师登录后能管理学生信息,可评分;(3)程序基本功能:打开、关闭、保存、另存为、退出;(4)处理数字图像功能:图像编辑:图像的单步撤销和重做;整幅图的复制,剪切,粘贴,清除;图像调整:位图变换(90度旋转,水平翻转,垂直翻转),取反色,取黑白两色,灰度图变换。
可以用滑动工具条改变参数的有对比度,亮度,饱和度,RGB;图像滤镜:曝光效果,浮雕效果。
Delphi编程_图形处理
7.2 画布的属性
Pen PenPos Brush Font Pixels CopyMode
7.2.1 Pen
绘图所用的画笔 主要控制绘图时的线条颜色、线型、粗细 主要属性
• Color
确定画笔的颜色
• Width
确定画笔的线条的宽度
• Mode
确定画笔的颜色和画布颜色组合的模式
9.1.1 画布的属性 一、Pen 表9-1 画笔的Mode 例:Draw_pmNot Draw_pmNot 二、PenPos 画笔当前的位置
三、Brush 画刷,填充画布上的区域和图形。 画刷的Style属性。 例:Brush 四、Font 五、Pixels
六、CopyMode 一个画布从另一个画布复制。 CopyMode的效果由三个因素决定: 1)原图像中的象素 2)目标图象中的象素 3)目标画刷的图案 例:CopyMode
9.1.2 画布常用的方法 Arc—画弧 Chord—画弓形 PolyLine— PolyLine—画折线 Polygone—画多边形 Rectangle—画矩形 FillRect—填充一个矩形 CopyRect—复制另一画布中的矩形区
9.3 绘制和刷新
Windows的绘制和刷新机制 例:Draw_pmNot Draw_pmNot 1)移动窗口 2)最大化窗口 3)最小化窗口再打开 4)用其他窗口遮盖本窗口的一部分
在窗口改变、移动或是被覆盖时,系统 会发送WM_PAINT消息,要求窗口刷新, 窗体调用OnPaint事件处理程序。 另一方面,窗口只重绘无效的部分。 例:DrawRefresh 1)Update:通知窗口重绘无效区 2)Invalidate 3)Update Rect:设定无效区
TextOut—绘制字符串 例:滚动显示文本
Delphi7 图形图像编程
(2)Brush属性
①Color属性 用来设置填充色,取值及含义与Pen的Color属性一样。 ②Style属性 该属性用来设置填充样式。图12-1是Brush颜色值为 clBlack时的Style属性值及其代表的样式。
图12-1 Brush对象的Style属性值及其代表的填充样式
(3)Pixels属性
图12-7 程序设计界面
图12-8 程序运行界面(一)
图12-9 程序运行界面(二)
12.2.2 典型实例二:照片自动展示程序
【实例题目】 制作一个照片自动展示程序,程序启动后将循环 显示照片,每张照片在屏幕上停留0.5秒。当用户单击 图片时将显示一个提示框,询问用户是否停止展示, 如果用户回答【是】将停止展示,回答【否】将接着 展示。程序的设计界面如图12-10所示,程序的运行 界面如图12-11所示。程序的运行界面如图12-11所示。 运行时如果单击照片,将会出现如图12-12所示的退 出提示框,在该提示框窗口上选中【Yes】按钮将退 出图片展示程序,单击【No】将继续展示。
图12-4 程序设计界面
图12-5 程序运行界面
2.TImage组件
TImage组件主要用于显示和处理图像,能够显示 BMP、JPEG、ICO、WMF、EMF等多种格式的图片。 它的主要属性如下: (1)Canvas属性 (2)Picture属性 例如,有下列语句: Image1.Picture.LoadFromFile('D:\A1.JPG'); 该语句的作用是把“D:\A1.JPG”图像文件显示在 TImage组件中。
该属性的声明如下: property C1ipRect:TRect;
(6)CopyMode属性
该属性用于设置从其他画布拷贝图像的方式
DELPHI基础教程:Delphi图形图像编程(二)[2]
DELPHI基础教程:Delphi图形图像编程(二)[2]另外一个问题是我们希望得到的是鼠标按钮按下和松开这两点所形成的图形但OnMouseMove却把鼠标轨迹上各点与起始点所形成的所有图形画在屏幕上这同样是我们不希望看到的为了解决这些问题程序定义了鼠标的三个事件procedure TForm FormMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X Y: Integer)beginDrawing := True;Image Canvas MoveTo(X Y)Origin := Point(X Y)MovePt := Origin;OriginPanel Caption := Format( Origin: (%d %d) [X Y])end;procedure TForm FormMouseUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X Y: Integer)beginif Drawing thenDrawShape(Origin Point(X Y) pmCopy)Drawing := False;end;procedure TForm FormMouseMove(Sender: TObject; Shift: TShiftState; XY: Integer)beginif Drawing thenbeginDrawShape(Origin MovePt pmNotXor)MovePt := Point(X Y)DrawShape(Origin MovePt pmNotXor)end;MovePt用来记录鼠标当前位置当下次鼠标移动时就能在上次鼠标绘制的图形上画一个形状大小一样的图形并把画笔颜色设置成PmNotXor 使上次绘制的图形颜色变成了屏幕颜色从而达到橡皮擦的效果将画笔画刷的Style属性设置成用户希望的值可实现对画笔和画刷风格的选择procedure TForm SetBrushStyle(Sender: TObject)beginwith Image Canvas Brush dobeginif Sender = SolidBrush then Style := bsSolidelse if Sender = ClearBrush then Style := bsClearelse if Sender = HorizontalBrush then Style := bsHorizontal else if Sender = VerticalBrush then Style := bsVerticalelse if Sender = FDiagonalBrush then Style := bsFDiagonal else if Sender = BDiagonalBrush then Style := bsBDiagonal else if Sender = CrossBrush then Style := bsCrosselse if Sender = DiagCrossBrush then Style := bsDiagCross;end;procedure TForm SetPenStyle(Sender: TObject)beginwith Image Canvas Pen dobeginif Sender = SolidPen then Style := psSolidelse if Sender = DashPen then Style := psDashelse if Sender = DotPen then Style := psDotelse if Sender = DashDotPen then Style := psDashDotelse if Sender = DashDotDotPen then Style := psDashDotDot else if Sender = ClearPen then Style := psClear;end;end;图像对象概述TGraphic对象TGraphic对象是TBitmap TIcon Tmetafile对象的基类如果知道图像的具体类型(如位图图标元文件)则应将图像贮存在相应类型的对象中(如TBitmap TIcon Tmetafile)否则应该使用可贮存任何图像类型的TPicture对象TPicture对象TPicture对象可以保存位图图标或元文件 Graphic属性中包括图像的类型图像的高度和宽度分别定义在Height Width属性中调用LoadFromFile方法可以从文件中装载一幅图像procedure TForm FormCreate(Sender: TObject)beginBitBtn Glyph LoadFromFile( TARTAN BMP )end;要保存一个位图则要用SaveToFile方法要把图像复制到剪切板可以调用TClipboard对象的Assign方法TImage部件TImage部件用以在窗体中显示图像它的Picture 属性保存着要显示的图像这是一个TPicture对象AutoSize Stretch属性是用来调节部件与图像的大小的当AutoSize 为真值时TImage部件将根据它所包含的图像的大小来调整自身的大小当AutoSize为假值时不论图像有多大部件将保持设计时的大小如果部件比图像小那么只有一部分图像是可见的当Stretch为真值时位图像将根据部件的大小调整自身的大小当部件大小改变时元文件也做相应变化 Stretch属性对图标没有作用TBitmap Object(位图对象)位图对象包含一个位图图像有HBITMAP HPALETE句柄可自动管理调色板位图对象也有画布属性位图的Palette属性用来控制位图的颜色映射它包括种可显示的颜色如果应用程序用前景色绘制位图Palette 属性的颜色将被加入Windows系统调色板其它颜色被映射到系统调色板已存在的颜色如果应用程序用自己的颜色绘制位图而其它程序已占有系统调色板位图的颜色将被映射到系统调色板中如果Monochrome属性设置成假位图将显示成彩色反之显示成黑白色调用Draw和StretchDraw方法可在画布上绘制位图图像对象的应用本章例程中单击(文件|浏览)菜单项将弹出一个图像浏览窗体如果用户在窗体中选择文件列表框的图形文件窗体右上角的图像部件上将出现此文件所代表的图像若选择雕刻效果按钮中检查框窗体中的加速按钮和位图按钮上将出现位图以下代码是将图像文件装载至图像部件上procedure TImageForm FileListBox Click(Sender: TObject)varFileExt: string[ ];beginFileExt := UpperCase(ExtractFileExt(FileListBox Filename))if (FileExt = BMP ) or (FileExt = ICO ) or (FileExt = WMF )thenbeginImage Picture LoadFromFile(FileListBox Filename)Label Caption := ExtractFilename(FileListBox Filename)if (FileExt = BMP ) thenbeginLabel Caption := Label Caption +Format((%d x %d) [Image Picture Height Image PictureWidth])ViewForm Image Picture Bitmap := Image Picture Bitmap;ViewAsGlyph(FileExt)end;if FileExt = ICO then Icon := Image Picture Icon;if FileExt = WMF thenViewForm Image Picture Metafile := Image Picture Metafile;end;end;这个过程首先判断文件类型如果是图像文件则将图像装载至图像部件上并在标签上列出文件名称如果是位图文件还将显示其大小lishixinzhi/Article/program/Delphi/201311/25244。
Delphi实现计算机视觉常用图像处理算法
Delphi实现计算机视觉常用图像处理算法
张鹏;柏咏菊;穆仁龙
【期刊名称】《实验室研究与探索》
【年(卷),期】2007(026)005
【摘要】由于图像处理涉及到了大量的程序编制工作,因此,如何合理选择一种简洁高效的编程工具,减少研究工作中的复杂性,就成为了计算机数字图像处理中不可回避的问题.本文就利用Delphi实现对计算机视觉中常用图像处理方法.
【总页数】3页(P61-63)
【作者】张鹏;柏咏菊;穆仁龙
【作者单位】重庆邮电大学,实验及设备管理处,重庆,400065;重庆邮电大学,实验及设备管理处,重庆,400065;重庆邮电大学,实验及设备管理处,重庆,400065
【正文语种】中文
【中图分类】TP391
【相关文献】
1.WINDOWS系统中几种常用的进程通讯方式及其DELPHI实现 [J], 王电钢;吴思远
2.用Delphi结合ADO开发Excel数据服务器应用技术(三)——Delphi构建多层数据库应用的技术与实现 [J], 闫海忠
3.第2章 Delphi网络与通信编程实例——例题11 利用Delphi实现通用多线程网络端口扫描器 [J], 王波
4.Delphi常用网络功能实现小技巧 [J], 方淑英
5.基于Matlab GUI的常见图像处理算法实现 [J], 刘付桂兰
因版权原因,仅展示原文概要,查看原文内容请购买。
Delphi的图形处理(一)
Delphi的图形处理(一)Delphi的图形处理之一 -- 图像处理在可视化编程中的作用及其应用价值 作者:何咏发布日期:(2005-4-12 21:07:49)声明:本文著作权属于何咏,如要转载请声明作者及出处。
第一章图像处理在可视化编程中的作用及其应用价值图像处理,是可视化编程的基础内容。
在Windows操作系统中,一切要输出到屏幕上的东西都是通过图形处理这部分的内容来实现的。
比如一个程序使用了标签控件,它看起来似乎并没有用到什么图形处理,但实际上标签控件就是通过使用GDI库中的图形处理函数来实现的。
可见图形处理在编程中的重要性。
图像处理在实际的应用中也极具价值。
平面制作、动画制作等都离不开它。
这一部分的内容十分繁多。
我本次研究的内容,只是其中最基础的、最重要一部分。
探究Delphi的图形处理之二 -- 基本图像处理函数 作者:何咏发布日期:(2005-4-12 21:06:29)声明:本文著作权属于何咏,如要转载请声明作者及出处。
第二章图像处理函数2.1 为什么选择Delphi所有的可视化编程语言都能够进行图像处理。
但由于这些语言的定位不同,它们在进行图形处理的效率和便捷程度上也各不相同。
实际上,Visual C 的图像处理效率是最高的,这是由于GDI类库本身就是用C++写的。
但是使用VC来编程并不是一件方便的事,因为这个语言本身就较为繁杂难懂,所以我没有选择它。
Visual Basic(VB)也是一个常用的语言,但它在图形处理方面能力较差。
首先是它的坐标系统是以t wip为单位的浮点坐标系统,在调用GDI类库时,必须对坐标系统进行转换,浪费了大量的资源,编程起来较为麻烦。
在多方面因素的影响下,我觉得Delphi是一个理想的语言。
Delphi已经把绝大多数GDI绘图函数都封装成可直接调用的类,使用它进行图形处理操作十分方便,而且Delphi 是Pascal演变而来的,Pascal具有严谨易读的特点,因此很容易上手。
由图像的灰度化看基本图像处理
由图像的灰度化看基本图像处理(1) ehom(原作)首先看一段实现24位色图像灰度化转换的代码procedure Grayscale(const Bitmap:TBitmap);varX: Integer;Y: Integer;R,G,B,Gray: Byte;Color: TColor;beginfor Y := 0 to (Bitmap.Height - 1) dobeginfor X := 0 to (Bitmap.Width - 1) dobeginColor := Bitmap.Canvas.Pixels[X,Y];R := Color and $FF;G := (Color and $FF00) shr 8;B := (Color and $FF0000) shr 16;Gray := Trunc(0.3 * R + 0.59 * G + 0.11 * B);Bitmap.Canvas.Pixels[X,Y] := Gray shl 16 or Gray shl 8 or Gray;endendend;{这段代码效率是非常低的,但可以方便我们理解同时一些问题}Delphi的帮助中对TColor已经有了详细的描述,这可以方便我们理解上面的代码!首先看:R := Color and $FF;G := (Color and $FF00) shr 8;B := (Color and $FF0000) shr 16;这是段常见的从TColor中提取三原色的代码,但它是什么意思呢?首先应该知道and是与(.)运算,0.1=0,0.0=0,1.1=1,以取绿色为例:$FF00实际上就是$00FF00,它与一个TColor类型数按位进行与运算后,表示红色和绿色的位都变为了$00,而表示绿色的部分不变(0,1和1进行与运算值都不变),再右移8位,自然就获得了绿色值的8位表示!再获得三原色的值后,就是计算灰度值,0.3 * Red + 0.59 * Green + 0.11 * Blue 这是求加权平均值的公式。
织物检测中图像预处理的Delphi实现
F 1厂 TO 9 - . 8 . 5] Y R . 9 - 1 0 1 2 04 6
根据 R、 B的值 求 出 Y值 后 , R、 B值都 赋值 成 G、 将 G、
Y. 能 表 示 出灰 度 图 来 。 就
对 一幅灰 阶图像 。 信号 的差 异是通 过对 比度来 体
现 的 。 对 比度 表 示 图像 上 两 个 不 同点 的 相 对 亮 度 差 高
O 2 5范 围 。 锐 化 常 用 的 模 板 如 下 , 文 用 的 是 第 一 ~5 本 个模板 。
ye =d M
. { 罟xMn偶 x + f奇 .f ,号】为数 吾 l f 1 【
对 二 维 序 列 f i 进 行 中 值 滤 波 时 , 波 窗 口 也 i Xl 滤
九 RG 之 间 有 着 如 下 的 对 应 关 系 : B 期
M D R C M U E 06 O E N O P T R 20. 7
维普资讯
图 形 图 像
X≤ ≤)≤ …≤ x 则 2 【 4 ,
素 的操作 , 或者 直接进 行 边界 像素 的拷 贝 , 还有 一个 问题 即是越界 问题 , 必须保证 中心像 素 点的各 分量 在
别较 大 , 使织 物经 线 、 为 纬线 交织 的细 节信 息更 加 清 晰 。可适 当增 强 图像 的对 比度 。在 D lh 程 序设计 e i p
中 , 用 像 素 值 调 节 的 办 法 , 首 先设 定 一 个 阈 值 , 采 即 通
过程 主要包 括灰度 化 、 滤波 、 图像锐 化及 二值化 等 。 如 图 1所 示 。本 文 利用 D lh 编程 实现 图像 预 处理 的 ep i
椒 盐 噪 声 及 图 像 扫 描 噪 声 最 为 有 效 , 抑 制 随 机 噪 声 在
Delphi中使用DirectDraw技术进行图形处理
Delphi中使用DirectDraw技术进行图形处理DirectDraw是一套名为DirectX复杂工具的一部分,DirectX是由许多不同的技术组成,比如:DirectDraw、Direct3D、DirectSound、DirectPlay、DirectInput和DirectSetup等。
其中的每一种技术都是集中了几种处多媒体的技术或游戏的技术,像声音播放、3D图形、网络播放、硬件设备如鼠标和强制反馈等等。
不过,在本章中将只介绍DirectDraw,并且这个主题很容易就会占用一章或更多的章节关于DirectX的其他技术内容,读者可以去参阅其他关于DirectX的书籍。
DirectDraw程序要求用户的系统必须有DirectDraw运行时的DLL,这些运行时文件(实际只是DLL的集合,可能许多机器已经安装了),还可以从Micorsoft的Web站点获取;该站点有各种各样的产品,包括游戏、Windows 98、将来的操作系统Windows NT 5等。
如果读者正在使用的是Windows NT 4,那么至少要用Service Pack 3(SP3)去升级,之后才能够访问作为SP3一部分的DirectDraw 3。
不要试图直接在Windows NT系统下安装运行时的DirectDraw,而应该安装最新的补丁(Service Pack),直接安装运行时的DirectDraw是针对Windows 95/98系统而言的。
确定一个系统是否安装了DirectDraw的一个方法是查看Windows/System或Winnt/System32目录是否存在DDRAW.DLL和DSOUND.DLL,如果有,则说明系统已经安装了DirectDraw。
在可能的情况下,读者应该从Microsoft获取DirectDraw SDK,通常它可以从Microsoft 的Web站点下载得到,不过请注意,它至少有30M。
安装了SDK后,它在硬盘上创建一个名为DXSDK的目录,在这个目录之下是SDK目录,其中包含有各种各样的文档、用C/C++编写的示例文件和帮助文件。
Delphi图像处理中的中值滤波灰度分组统计法
《Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。
《C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。
尽可能保持二者内容一致,可相互对照。
本文代码必须包括文章《Delphi图像处理 -- 数据类型及公用过程》中的ImageData.pas单元。
这是《Delphi图像处理 -- 中值滤波》一文的改进版。
亦可参见《C++图像处理 -- 中值滤波》。
中值滤波是图像处理中常用的一种噪声滤波方法。
传统的图像中值滤波代码采用排序方法实现,处理速度主要取决于排序算法,但无论什么排序算法,总离不开大量的元素比较、交换或移动,而这些恰好是当前计算机处理的“弱项”(有经验的程序员都知道,计算机数据处理中,比较、转移、交换和频繁的数据移动比直接的算术运算和逻辑运算耗时多了),再加上没有一种好的排序算法能同时适应不同滤波半径的数据排序速度,所以在传统中值滤波实现代码中多使用选择排序、冒泡排序或者直接排序等简单排序算法,高级点的如快速排序法用在中值滤波代码中往往会使处理速度更慢。
对于半径为1的中值滤波倒是有一种较好的排序算法,我在《Delphi图像处理 -- 中值滤波》一文中实现过,处理速度还是较快的。
既然排序过程是图像中值滤波处理的瓶颈,能不能抛开它,用其它手段实现呢?这就是本文要探讨的问题。
有朋友可能会有疑问,不排序怎么获取中间值呢,是否采用网上有些文章介绍的近似值来代替?不,本文介绍的方法决不是近似中间值,而是的的确确的“精确”中间值。
图像中值滤波中的中间值。
在统计学中叫做中位数,是平均数指标的一种。
平均数指标按统计的复杂程度可分为简单平均数和加权平均数,所谓简单平均数就是对统计总体的每个个体进行累计计算后求得;而加权平均数则是先对统计总体的所有个体进行分组,然后以各个组的大小作为权数后进行累计计算所得。
中位数既然是平均数指标的一种,当然也存在两种计算方法。
加权中位数和加权算术平均数的区别在于后者是对各个分组用权数相乘进行累积后除以总体个数,而前者只需要对各组权数进行累积后除以2,累积权数大于或等于这个数的组的值就是中位数。
Deleh2.0下的图像处理
Deleh2.0下的图像处理
郑胜;王正觉
【期刊名称】《电脑编程技巧与维护》
【年(卷),期】1997(000)008
【摘要】图像处理的任务是将原图像的灰度分布作某种变换,使图像中的某部分信息更加突出,以使其适应某种需要。
最常见的处理莫过于图像的亮度(灰度)变换和对比度变换。
本文介绍在Delphi 2.0下的图象亮度和对比度的变换方法。
计算机中的图像是数字图象。
数字图像是以位图(bitmap)的形式存在于计算机中的。
位图是一个矩形点阵,上面的每一个点称之为像素(Pixel),是由m×n个明暗不等的像素组成的。
数字图像中各个像素所具有的明暗程度是由一个灰度值的数字所标识的。
【总页数】4页(P49-51,54)
【作者】郑胜;王正觉
【作者单位】湖北三峡学院医学院;湖北三峡学院医学院
【正文语种】中文
【中图分类】TP391.41
【相关文献】
1.数字图像处理技术基础:第五讲基本数字图像处理(下) [J], 邱天爽;徐哲尧
2.图像处理技术下的植物叶片分割方法 [J], 田霞;邹霄贝;丁浩淇
3.新工科背景下基于项目驱动的数字图像处理教学方法探析 [J], 宋伟;谢欣怡;杨青;刘磊;王浩
4.新工科背景下案例化教学在《数字图像处理》课程中的研究与实践 [J], 王峰;赵
小刚;汪鼎文
5.建构探究型模式下《医学图像处理》雨课堂的智慧教学研究与实践 [J], 刘雅楠;李靖宇;赵添羽;郝利国;孙跃
因版权原因,仅展示原文概要,查看原文内容请购买。
中图像处理的相关技巧
Delphi 中图像的处理Delphi的绘图功能十分强大,而它的绘图功能大部分都集成在Canvas中了,Canvas 是一个对象,在这个对象中,几乎拥有了Windows GDI的所有功能,在Delphi中,所有的图形函数实际上均隶属于Canvas对象,而不是属于表单。
这意味着只要包含Canvas对象的资源均可用于绘图,例如TDrawGrid、TShape、TImage等组件。
可利用Canvas的成员函数来实现图形的特殊显示效果。
实现一幅图像的下拉效果,方法是将一幅图像分成n等份(n个大小相等的矩形),然后分成n步,一次拷贝一个矩形到要显示的位图上,这样就实现了图像的下拉显示效果。
有关Canvas的函数在Delphi中调用Canvas的矩形拷贝函数,函数原型如下:procedure CopyRect(Dest:TRect;Canvas:TCanvas;Source:TRect);该函数可以实现两个图像之间任意矩形块的拷贝,参数说明如下:Dest:指定目标图像矩形块的位置及大小Canvas:指定源图像的CanvasSource:指定源图像矩形块的位置及大小其中,矩形区域定义可通过函数:Rect(ALeft,ATop,ARight,ABottom:Integer)获得。
拷贝的方式通过Canvas的另一个属性CopyMode实现,CopyMode共有3个属性值:cmSrcCopy:不加任何改变的从源位图拷贝到目标位图cmBlackness:将目的位图以黑色填充cmWhiteness:将目的位图以白色填充新建表单Form1,在表单上放置两个和源图像大小相同的TImage组件image1和image2,用image2的picture调入图像,并将Visible属性值设为False;再放置一个TTimer组件Timer1,根据图像显示快慢设置Interval值,本程序设置为300。
程序代码示例(本程序将图像分5个矩形块)*添加私有成员private{ Private declarations }DestCanvas:TCanvas;SrcCanvas:TCanvas;DestRect:TRect;*添加变量kvarForm1: TForm1;k:Integer;//在.pas的开头处添加代码*初始化变量k=0procedure TForm1.FormCreate(Sender: TObject);begink:=0;end;* Timer的事件处理过程procedure TForm1.Timer1Timer(Sender: TObject);vari,j,j0:integer;arect1,arect2:Trect;begini:=image2.Width; //变量赋初值j:=image2.Height;j0:=Trunc(image2.Height/5);with DestCanvas dobeginarect2:=Rect(0,j0*k,i,j0*k+j0); //源矩形块的位置及大小arect1:=Rect(0,j0*k,i,j0*k+j0); //目标矩形块的位置及大小Self.DestCanvas:=Image1.Canvas; //指定目标图像的CanvasSelf.SrcCanvas:=Image2.Canvas; //指定源图像的CanvasSrcCanvas.CopyMode:=cmSrcCopy; //设置拷贝方式DestCanvas.CopyRect(arect1,SrcCanvas,arect2); //实现块拷贝endk:=k+1;if k=5 then Timer1.Enabled:=FALSE;end;end;本程序只是一个简单的图像显示例子,其它图像显示方法,如:百叶窗式、马赛克式等、均可以由算法实现。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
CSDN - 专家门诊 - Delphi 图形处理/多媒体问题推荐 | 保存 | 关闭窗口主题:由Delphi中的图像灰度化代码看基本图像处理~~~作者: ehom (?!)等级:信誉值: 190所属论坛: Delphi 图形处理/多媒体问题点数: 33回复次数: 23发表时间: 2003-02-27 12:48:11Z[基础篇]首先看一段实现24位色图像灰度化转换的代码procedure Grayscale(const Bitmap:TBitmap);varX: Integer;Y: Integer;R,G,B,Gray: Byte;Color: TColor;beginfor Y := 0 to (Bitmap.Height - 1) dobeginfor X := 0 to (Bitmap.Width - 1) dobeginColor := Bitmap.Canvas.Pixels[X,Y];R := Color and $FF;G := (Color and $FF00) shr 8;B := (Color and $FF0000) shr 16;Gray := Trunc(0.3 * R + 0.59 * G + 0.11 * B);Bitmap.Canvas.Pixels[X,Y] := Gray shl 16 or Gray shl 8 or Gray; endendend;{这段代码效率是非常低的,但可以方便我们理解同时一些问题}Delphi的帮助中对TColor已经有了详细的描述,这可以方便我们理解上面的代码!首先看:R := Color and $FF;G := (Color and $FF00) shr 8;B := (Color and $FF0000) shr 16;这是段常见的从TColor中提取三原色的代码,但它是什么意思呢?首先应该知道and是与(.)运算,0.1=0,0.0=0,1.1=1,以取绿色为例:$FF00实际上就是$00FF00,它与一个TColor类型数按位进行与运算后,表示红色和绿色的位都变为了$00,而表示绿色的部分不变(0,1和1进行与运算值都不变),再右移8位,自然就获得了绿色值的8位表示!再获得三原色的值后,就是计算灰度值,0.3 * Red + 0.59 * Green + 0.11 * Blue 这是求加权平均值的公式。
(因为人眼对颜色的敏感度不同,所以权值不同,就像在pf16bit中用了6位表示绿色,其它两种颜色只用了5位,这问题以后另写文章说明)然后就是像素颜色信息的写回,刚才是右移,现在自然就是左移,而或(+)运算就是(0+1=1,0+0=0,1+1=1),举个简单例子就是:($FF shl 16 = $FF0000) or ($FF shl 8 = $FF00) or $FF = $FFFFFF ,其实这里的或运算当然也可以用 + 代替。
虽然上面的代码实现了24位色图像的灰度化,但当图像比较大时,速度非常慢,为什么?查看相关VCL代码可知调用Bitmap.Canvas.Pixels获取,写入像素的颜色信息实际上是利用了API GetPixel、SetPixel,这种方法是非常低效的!(唯一的好处是在进行一些和颜色无关的操作,如图像的旋转,翻转时不需要因为PixelFormat的不同而修改代码)所以应该换一种更高效的访问像素点数据的方法,如用API GetDIBits、SetDIBits,但这种方法比较复杂,好在Delphi3以后版本的TBitmap 中提供了Scanline。
利用Scanline可以快速对像素进行访问!还是以24位色(PixelFormats=pf24bit)为例,可改写为:procedure Grayscale(const Bitmap:TBitmap);constPixelCountMax = 32768;typepRGBTripleArray = ^TRGBTripleArray;TRGBTripleArray = ARRAY[0..PixelCountMax-1] OF TRGBTriple;varRow: pRGBTripleArray;X: Integer;Y: Integer;Gray: Byte;beginfor Y := 0 to (Bitmap.Height - 1) dobeginRow := Bitmap.ScanLine[Y];for X := 0 to (Bitmap.Width - 1) dobeginGray := Trunc(0.3 * Row^[X].rgbtRed + 0.59 * Row^[X].rgbtGreen + 0.11 *Row^[X].rgbtBlue);Row^[X].rgbtRed:=Gray;Row^[X].rgbtGreen:=Gray;Row^[X].rgbtBlue:=Gray;end;end;end;上面的例子用了一个TRGBTriple数组PRGBTriple = ^TRGBTriple;tagRGBTRIPLE = packed recordrgbtBlue: Byte;rgbtGreen: Byte;rgbtRed: Byte;end;TRGBTriple = tagRGBTRIPLE;这种方法会限制位图的大小,但一般不用理会,直接用TBitmap可处理不了那么大的位图当然也可用指针的移动实现,实测结果这样更快~~~procedure Grayscale(const Bitmap:TBitmap);varX: Integer;Y: Integer;PRGB: pRGBTriple;Gray: Byte;beginfor Y := 0 to (Bitmap.Height - 1) dobeginPRGB := Bitmap.ScanLine[Y];for X := 0 to (Bitmap.Width - 1) dobeginGray := Trunc(0.3 * PRGB^.rgbtRed + 0.59 * PRGB^.rgbtGreen + 0.11 * PRGB^.rgbtBlue); PRGB^.rgbtRed:=Gray;PRGB^.rgbtGreen:=Gray;PRGB^.rgbtBlue:=Gray;Inc(PRGB);end;end;end;[颜色篇]在上面提到了,那灰度化代码只能适用于24位色(PixelFormats=pf24bit),为什么?看看记录类型tagRGBTRIPLE,正好24位,所以这样只能处理24位色图!那怎么处理其他的位图呢?先对这各种类型的位图做些简单的介绍~~~pf1bit:每个像素只需要用一位表示,如调色板定义的是黑白两种颜色(0为黑,1为白),这时只能用位操作访问像素信息!如定义var P:PBytefor Y := 0 to (Bitmap.Height - 1) dobeginp := Bitmap.ScanLine[Y];for X := 0 to (Bitmap.width - 1) DIV 8 + 1 dobeginp^:=1 or 2 or 4 or 8 or 16 or 32 or 64 or 128;Inc(PRGB,3);end;end;p^:=1 or 2 or 4 or 8 or 16 or 32 or 64 or 128;这行代码什么意思呢?1=1(二进制),2=10(二进制),4=100(二进制),8=1000(二进制)...结合上篇中解释了的或运算,很容易理解就以八个字位为单位,给其赋上颜色信息!pf4bit:和pf1bit位图一样,操作pf4bit位图也需要用位操作。
pf8bit:可直接利用Byte、TByteArray,但用Scanline取的值表示的只是调色板上颜色的索引。
pf15bit和pf16bit:这两种位图都是16位的,pf15bit是第一位为0,后15位的每5位分别表示红、绿、蓝。
而pf16bit 中绿色占6位,其它两种颜色占用5位(人眼对绿色比较敏感)!pf24bit位图转pf15bit位图代码varRow24:pRGBTriple;Row15:PWord;for j := 0 TO Bitmap.Height-1 DObeginRow15 := Bitmap15.Scanline[j];Row24 := Bitmap24.Scanline[j];for i := 0 TO Bitmap.Width-1 DObeginwith Row24^ doRow15^ := (rgbtRed Shr 3) Shl 10 or (rgbtGreen Shr 3) Shl 5 or (rgbtBlue Shr 3);Inc(Row24);Inc(Row15);endend;pf24bit和pf32bit:pf24bit上面的已多次用到,就不多说了。
而pf32bit和pf24bit一样,用24位(前24位)来记录三原色的颜色信息!PRGBQuad = ^TRGBQuad;tagRGBQUAD = packed recordrgbBlue: Byte;rgbGreen: Byte;rgbRed: Byte;rgbReserved: Byte;end;TRGBQuad = tagRGBQUAD;如果要修改上面的程序,就是简单的PRGBQuad替换PRGBTriple,TRGBQuad替换TRGBTriple的过程~测试表明在pf32bit中利用Scanline处理图像要比pf24bit快。
所以除了单色图(PixelFormats=pf1bit)外(没必要),其它都可转外32位色实现灰度化。
这也是一种比较可行的方法![优化篇]还以上篇中给出的灰度化代码为例procedure Grayscale(const Bitmap:TBitmap);varX: Integer;Y: Integer;PRGB: pRGBTriple;Gray: Byte;beginfor Y := 0 to (Bitmap.Height - 1) dobeginPRGB := Bitmap.ScanLine[Y];for X := 0 to (Bitmap.Width - 1) dobeginGray := Trunc(0.3 * PRGB^.rgbtRed + 0.59 * PRGB^.rgbtGreen + 0.11 * PRGB^.rgbtBlue); PRGB^.rgbtRed:=Gray;PRGB^.rgbtGreen:=Gray;PRGB^.rgbtBlue:=Gray;Inc(PRGB);end;end;end;实际应用中,这种方法已经很快了,但实际上还存在可以优化的余地,什么呢?Gray := Trunc(0.3 * Red + 0.59 * Green + 0.11 * Blue);//这句用的是浮点运算在图像处理中,速度就是生命,能不用浮点运算,就最好不要用!Gray := (30 * Red + 59 * Green + 11 * Blue) div 100;虽然这样一改,运算次数多了一次,但在我的雷鸟1.1G上,处理速度大概能提高5%左右!而同主频下(或略低,如Athlon 1600+相当于P4 1.6G)AMD的CPU浮点运算能力比Intel的较强,整数运算能力较弱,所以用Intel的CPU在这里更能体现出优势!注:x div 100 和 Trunc(x/100)的效果是相同的,但查看其汇编代码可知一个用的指令是div,而另一个是fdiv(即进行浮点运算),还要调用函数Trunc,其处理速度差距非常大,所以能用 x div 100 的时候就不要用 Trunc(x/100)。