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图形图像处理
见例子
画矩形
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中的图像灰度化代码看基本图像处理
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 这是求加权平均值的公式。
Delphi图像处理之图像二值化
Delphi图像处理之图像⼆值化-----------开发环境D7---效果图-------只提供参考----------------unit开始1unit Unit1;23interface45uses6 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,7 Dialogs, ExtCtrls, StdCtrls, ExtDlgs;89type10 ThresholdValueArray=array of array of Byte ;11 TForm1 = class(TForm)12 Button1: TButton;13 Button2: TButton;14 Image1: TImage;15 Image2: TImage;16 OpenPictureDialog1: TOpenPictureDialog;17 Label1: TLabel;18 Button4: TButton;19 Label2: TLabel;20 EditX: TEdit;21 EditY: TEdit;22 Label3: TLabel;23 Label4: TLabel;24 Label5: TLabel;25 Label6: TLabel;26 Label7: TLabel;27procedure Button1Click(Sender: TObject);28procedure Button2Click(Sender: TObject);29procedure Button4Click(Sender: TObject);30procedure EditXChange(Sender: TObject);31private32function GetThresholdValue(sBmp: TBitmap; sX,sY: Byte): ThresholdValueArray;33function GetThresholdArrayGray(const sArray:ThresholdValueArray; sStartX, sEndX, sStartY, sEndY: word): Byte; 34{ Private declarations }35public36{ Public declarations }37end;3839var40 Form1: TForm1;4142implementation4344{$R *.dfm}4546procedure TForm1.Button1Click(Sender: TObject);47begin48if OpenPictureDialog1.Execute then49begin50 Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);51 Label1.Caption:='图⽚宽x⾼:'+inttostr(Image1.Picture.Width)+'x'+inttostr(Image1.Picture.Height);52end;53end;5455procedure TForm1.Button2Click(Sender: TObject);56const57 vThresholdValue:Byte=128;58var59 vP:PByteArray;60 x,y:Integer;61 vBmp:TBitmap;62 vGray:Integer;63begin64if Image1.Picture.Graphic =nil then65begin66 ShowMessage('没有图⽚!');67 Exit;68end;69 vBmp:=TBitmap.Create;70 vBmp.Assign(Image1.Picture.Bitmap);71 vBmp.PixelFormat:=pf24bit;72for y:=0to vBmp.Height-1do73begin74 vP:=vBmp.ScanLine[y];75for x:=0to vBmp.Width-1do76begin77 vGray:=(77*vP[3*x+2] + 149*vP[3*x+1] + 29*vP[3*x]) shr8;78if vGray>vThresholdValue then79begin80 vP[3*x+2]:=255;81 vP[3*x+1]:=255;82 vP[3*x]:=255;83end84else85begin86 vP[3*x+2]:=0;87 vP[3*x+1]:=0;88 vP[3*x]:=0;89end;90end;91end;92 Image2.Picture.Assign(vBmp);93 vBmp.Free;94end;9596function TForm1.GetThresholdArrayGray(const sArray: ThresholdValueArray; sStartX,97 sEndX, sStartY, sEndY: word): Byte;98var99 vGraySum:DWORD;100 i,j:Word;101begin102 Result:=128;//默认返回128103if sArray=nil then104 Exit;105 vGraySum:=0;106for i:=sStartX-1to sEndX-1do107begin108for j:=sStartY-1to sEndY-1do109begin110 vGraySum:=vGraySum+sArray[i,j];111end;112end;113 Result:=Round(vGraySum/((sEndX-sStartX+1)*(sEndY-sStartY+1)));114end;115116function TForm1.GetThresholdValue(sBmp: TBitmap; sX,117 sY: Byte): ThresholdValueArray;118119var120 i,j,x,y,vGray:Word;121 vLengthX,vLengthY,vModX,vModY:Word;122 vP:PByteArray;123 vBitmapGrayArray:ThresholdValueArray;124 vResultGrayArray:ThresholdValueArray;125begin126 Result:=nil;127if sBmp=nil then128 Exit;129if sX=0then130 sX:=1;131if sY=0then132 sY:=1;133 setlength(vBitmapGrayArray,sBmp.Width);134for i:=0to sBmp.Width-1do135begin136 setlength(vBitmapGrayArray[i],sBmp.Height);137end;138 SetLength(vResultGrayArray,sX);139for i:=0to sX-1do140begin141 SetLength(vResultGrayArray[i],sY);142end;143144for y:=0to sBmp.Height-1do145begin146 vP:=sBmp.ScanLine[y];147for x:=0to sBmp.Width-1do148begin149 vGray:=(77*vP[3*x+2] + 149*vP[3*x+1] + 29*vP[3*x]) shr8;150 vBitmapGrayArray[x,y]:=vGray;151end;152end;153 vLengthX:=sBmp.width div sX;154 vLengthY:=sBmp.Height div sY;155 vModX:=sBmp.width mod sX;156 vMody:=sBmp.Height mod sY;157for i:=0to sX-1do//⼩块158begin159for j:=0to sY-1do//⼩块160begin161if i<>sX-1then162begin163 vResultGrayArray[i,j]:=GetThresholdArrayGray(vBitmapGrayArray,vLengthX*i+1,vLengthX*i+vLengthX,vLengthY*j+1,vLengthY*j+vLengthY);164end165else//最后⼀列166begin167 vResultGrayArray[i,j]:=GetThresholdArrayGray(vBitmapGrayArray,vLengthX*i+1,vLengthX*i+vLengthX+vModX,vLengthY*j+1,vLengthY*j+vLengthY+vModY); 168end;169173 Result:=vResultGrayArray;174//数组释放175for i:=0to sBmp.Width-1do176begin177 setlength(vBitmapGrayArray[i],0);178end;179 setlength(vBitmapGrayArray,0);180end;181182procedure TForm1.Button4Click(Sender: TObject);183var184 vP:PByteArray;185 x,y:Integer;186 vBmp:TBitmap;187 vGray:Integer;188 vLengthX, vLengthY, vModX, vModY,vRowMod,vColMod: Word;189 vX,vY:Byte;190 vGrayArray:ThresholdValueArray;191 vRow,vCol:byte;192begin193if Image1.Picture.Graphic =nil then194begin195 ShowMessage('没有图⽚!');196 Exit;197end;198 vX:=StrToIntDef(editX.Text ,3);199 vY:=StrToIntDef(editY.Text ,3);200201//暂时最多分成255*255块202if (vX<1) or (vX>255) or (vY<1) or (vY>255) then203begin204 MessageBox(Handle,PChar('X和Y的范围:1到255; 请输⼊在这个范围内的数字!'),PChar(Application.Title),MB_ICONEXCLAMATION); 205 Exit;206end;207 Label6.Caption:='总块数:'+inttostr(vX*vY);208 vBmp:=TBitmap.Create;209 vBmp.Assign(Image1.Picture.Bitmap);210 vBmp.PixelFormat:=pf24bit;211212 vGrayArray:=GetThresholdValue(vBmp,vX,vY);213for y:=0to vBmp.Height-1do214begin215 vP:=vBmp.ScanLine[y];216 vRow:=y div vLengthY;217 vRowMod:=y div vLengthY;218if vRow<vY then219begin220if vRowMod>0then221 vRow:=vRow+1;222end;223for x:=0to vBmp.Width-1do224begin225 vCol:=x div vLengthx;226 vColMod:=x div vLengthx;227if vCol<vX then228begin229if vColMod>0then230 vCol:=vCol+1;231end;232 vGray:=(77*vP[3*x+2] + 149*vP[3*x+1] + 29*vP[3*x]) shr8;233if vGray>vGrayArray[vCol,vRow] then234begin235 vP[3*x+2]:=255;236 vP[3*x+1]:=255;237 vP[3*x]:=255;238end239else240begin241 vP[3*x+2]:=0;242 vP[3*x+1]:=0;243 vP[3*x]:=0;244end;245end;246end;247 Image2.Picture.Assign(vBmp);248 vBmp.Free;249end;250251procedure TForm1.EditXChange(Sender: TObject);252begin253 Label6.Caption:='总块数:'+inttostr(StrToIntDef(EditX.Text ,0)*strtointDef(EditY.Text,0));--------unit结束--------Form开始1object Form1: TForm12 Left = 5133 Top = 3264 Width = 9105 Height = 5286 Caption = 'Form1'7 Color = clBtnFace8 Font.Charset = DEFAULT_CHARSET9 Font.Color = clWindowText10 Font.Height = -1111 = 'MS Sans Serif'12 Font.Style = []13 OldCreateOrder = False14 PixelsPerInch = 9615 TextHeight = 1316object Image1: TImage17 Left = 818 Top = 1619 Width = 42520 Height = 33721 Center = True22 Proportional = True23 Stretch = True24end25object Image2: TImage26 Left = 44827 Top = 1628 Width = 42529 Height = 33730 Center = True31 Proportional = True32 Stretch = True33end34object Label1: TLabel35 Left = 1636 Top = 36037 Width = 38538 Height = 2539 AutoSize = False40 Caption = '图⽚宽x⾼:'41end42object Label2: TLabel43 Left = 52844 Top = 36045 Width = 27346 Height = 1347 Alignment = taCenter48 AutoSize = False49 Caption = '按块求出阈值'50end51object Label3: TLabel52 Left = 45753 Top = 38154 Width = 7355 Height = 1356 Caption = '输⼊X x Y块:'57end58object Label4: TLabel59 Left = 53360 Top = 38161 Width = 2462 Height = 1363 Alignment = taRightJustify64 AutoSize = False65 Caption = 'X:'66end67object Label5: TLabel68 Left = 62069 Top = 38070 Width = 2171 Height = 1772 Alignment = taRightJustify73 AutoSize = False74 Caption = 'Y:'75end76object Label6: TLabel77 Left = 70478 Top = 38379 Width = 18580 Height = 1381 AutoSize = False82 Caption = '总块数:'83end84object Label7: TLabel85 Left = 51286 Top = 44087 Width = 37788 Height = 4589 AutoSize = False90 Caption = '理应是块数分的越多,越准确!本⼈这个呈抛物线的感觉,'#13#10'有⼀个最优的块数,算了先不找原因了,抛砖引⽟,哈哈哈'91 WordWrap = True92end93object Button1: TButton94 Left = 1695 Top = 41696 Width = 16197 Height = 2598 Caption = 'Button1_加载图⽚'99 TabOrder = 0100 OnClick = Button1Click101end102object Button2: TButton103 Left = 232104 Top = 416105 Width = 177106 Height = 25107 Caption = 'Button2_⼆值化_默认阈值'108 TabOrder = 1109 OnClick = Button2Click110end111object Button4: TButton112 Left = 560113 Top = 407114 Width = 297115 Height = 25116 Caption = 'Button4_分块求平均阈值,按块⼆值化'117 TabOrder = 2118 OnClick = Button4Click119end120object EditX: TEdit121 Left = 567122 Top = 378123 Width = 49124 Height = 21125 ImeName = '中⽂(简体) - 搜狗拼⾳输⼊法'126 TabOrder = 3127 Text = 'EditX'128 OnChange = EditXChange129end130object EditY: TEdit131 Left = 649132 Top = 379133 Width = 47134 Height = 21135 ImeName = '中⽂(简体) - 搜狗拼⾳输⼊法'136 TabOrder = 4137 Text = 'EditY'138 OnChange = EditXChange139end140object OpenPictureDialog1: TOpenPictureDialog141 Filter = 'Bitmaps (*.bmp)|*.bmp'142 Left = 72143 Top = 368144end145end------------Form结束。
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 tpngimage 用法
delphi tpngimage 用法TPNGImage 是 Delphi 中用于处理 PNG 图像的类,提供了一系列方法和属性来加载、保存和操作 PNG 图像。
下面是一些常用的 TpngImage 的用法示例:1. 加载 PNG 图像文件:```delphivarPngImage: TPngImage;beginPngImage := TPngImage.Create;tryPngImage.LoadFromFile('image.png');// 处理图像finallyPngImage.Free;end;end;```2. 保存 PNG 图像文件:```delphivarPngImage: TPngImage;beginPngImage := TPngImage.Create;try// 创建或加载图像// PngImage.LoadFromFile('image.png'); // 处理图像PngImage.SaveToFile('output.png');finallyPngImage.Free;end;end;```3. 访问图像宽度和高度:```delphivarPngImage: TPngImage;Width, Height: Integer;beginPngImage := TPngImage.Create;tryPngImage.LoadFromFile('image.png'); Width := PngImage.Width;Height := PngImage.Height;finallyPngImage.Free;end;end;```4. 处理图像的像素数据:```delphivarPngImage: TPngImage;X, Y: Integer;PixelColor: TColor;beginPngImage := TPngImage.Create;tryPngImage.LoadFromFile('image.png');for Y := 0 to PngImage.Height - 1 dobeginfor X := 0 to PngImage.Width - 1 dobegin// 获取像素颜色PixelColor := PngImage.Canvas.Pixels[X, Y];// 处理像素数据end;end;finallyPngImage.Free;end;end;```以上是一些 TPngImage 的常用用法示例,根据具体需求可以调用其他方法和属性来实现更多功能的操作。
delphi copyrect copymode -回复
delphi copyrect copymode -回复Delphi是一种采用面向对象编程语言的集成开发环境(IDE),它旨在简化开发过程并提供丰富的工具和库来帮助开发人员建立强大的应用程序。
Delphi的重要特性之一是其对绘图和图像处理的支持,其中包括CopyRect和CopyMode两个函数。
本文将详细介绍CopyRect和CopyMode函数以及它们在Delphi中的用法。
在开始深入研究CopyRect和CopyMode函数之前,让我们先了解一下绘图和图像处理的基本概念。
在Delphi中,绘图是指在屏幕或画布上创建图像的过程。
图像处理是指对图像进行操作、编辑、转换或增强以满足特定需求的过程。
CopyRect和CopyMode函数是用来处理图像的重要工具,它们提供了一种简便的方式来复制和绘制图像。
CopyRect函数用于复制源矩形中的图像到目标矩形。
它的语法如下:CopyRect(Dest: TRect; Canvas: TCanvas; Source: TRect);其中,Dest代表目标矩形,Canvas代表目标画布,Source代表源矩形。
该函数将源矩形中的图像复制到目标矩形中,并在目标画布上绘制。
以下是一个使用CopyRect函数的示例:delphivarSourceRect, DestRect: TRect;beginSourceRect := Rect(0, 0, 100, 100); 源矩形,左上角坐标为(0,0),宽高为100DestRect := Rect(200, 200, 300, 300); 目标矩形,左上角坐标为(200,200),宽高为100Canvas.CopyRect(DestRect, SourceImage.Canvas, SourceRect); 将源矩形中的图像复制到目标矩形中end;在上面的示例中,首先定义了源矩形和目标矩形的位置和大小。
然后使用CopyRect函数将源矩形中的图像复制到目标矩形中。
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—绘制字符串 例:滚动显示文本
基于Delphi的JPEG图像处理
procedure TForm1.Button1Click(Sender: TObject)?
Var
jpg1.compressD
Jpg1: TJPEGImageD
jpg1.SaveTofile(' c:\jpg.jpg' )D
Bmp2: TBitmapD
finally
Begin
jpg1.free;
Bmp2:= TBitmap.CreateD
3 结束语
J2EE 提供了简单、实用、标准化、分布式的 WEB 编程 方法,掌握这些方法会使程序开发者事半功倍。
参考文献 [1] 何桥,李肃义. Java 程序设计简明教程[M]. 北京:中国
水利水电出版社,2004. [2] 蔡剑,景楠. Java web 应用开发- J2EE 和 Tomcat[M]. 北
的 PicturePath 字段上,并可通过组件查看 Image1 在用户界
面中显示所选图像。
Image1.Picture.LoadFromFile(filename)? Adotable1.fieldbyname(' PicturePath' ).AsString:=filename?
(2)显示图像,首先从 picture 表中 PicturePath 字段
(7)Web 服务技术:是通过互联网进行远程应用服务
收稿日期:2007- 07- 05 * 刘建培 广东商学院教育技术中心实验师(广州 510320)
ing 设置为真,解压缩才能递增显示。 1.2 TJPEGImage 的主要方法
(1)Assign 方法。拷贝 JPEG 图像对象并且使它与内部 JPEG 数据源对象建立联系。如果要显示 JPEG 图像,可以调 用 Assign 方法把 JPEG 图像赋值给位图,然后显示。
delphi tpngimage 用法
delphi tpngimage 用法摘要:1.Delphi Tpngimage 简介2.Delphi Tpngimage 用法详解3.Delphi Tpngimage 的优点与不足正文:【Delphi Tpngimage 简介】Delphi Tpngimage 是一款由Borland 公司开发的图像处理组件,主要用于在Delphi 和C++Builder 开发环境下进行图片操作。
该组件提供了丰富的图像处理功能,如图像显示、保存、转换、裁剪、缩放、旋转等,极大地简化了开发者在图像处理领域的开发难度。
【Delphi Tpngimage 用法详解】Delphi Tpngimage 的使用方法主要包括以下几个步骤:1.首先,需要在项目中引入Tpngimage 组件。
打开Delphi 项目,在“Component”(组件)窗口中,找到Tpngimage 并拖拽到窗体上。
2.对Tpngimage 组件进行属性设置。
Tpngimage 组件有许多可设置的属性,如Image(图片)、SaveToFile(保存到文件)、LoadFromFile(从文件加载)等。
通过设置这些属性,可以实现对图片的各种操作。
3.为Tpngimage 组件编写事件处理程序。
Tpngimage 组件提供了一系列事件,如OnLoad(加载)、OnSave(保存)、OnPaint(绘制)等。
通过编写事件处理程序,可以响应组件的各种操作。
以保存图片为例,以下是使用Delphi Tpngimage 的详细步骤:1.在窗体上添加一个Tpngimage 组件。
2.设置Tpngimage 组件的Image 属性,加载需要保存的图片。
3.为Tpngimage 组件添加一个SaveToFile 事件处理程序。
4.在SaveToFile 事件处理程序中,使用Tpngimage 组件的SaveToFile 方法,将图片保存到指定的文件路径。
【Delphi Tpngimage 的优点与不足】Delphi Tpngimage 组件的优点主要体现在以下几个方面:1.功能丰富:Tpngimage 组件提供了丰富的图像处理功能,可以满足大部分开发者的需求。
基于DELPHI的图象压缩处理
JPEG的编码流程图: JPG的解码流程图: JPEG的解码流程图: 的解码流程图
BMP转换为JPEG: BMP转换为JPEG: 转换为
先设计好闪现窗体(窗体名字为flashform), 先设计好闪现窗体(窗体名字为flashform),但是保 flashform),但是保 存单元文件时,我用的是Flash,并运行, Flash,并运行 存单元文件时,我用的是Flash,并运行,直至看到了 效果 然后将Form1修改为Main,将单元文件由Unit1.pas 然后将Form1修改为Main,将单元文件由Unit1.pas修 Form1修改为Main,将单元文件由Unit1.pas修 Radar.pas,再运行 看到效果后,可以运行一下, 再运行, 改为 Radar.pas,再运行,看到效果后,可以运行一下, 再看看有没有闪现窗体和刚才设计的各种组件。 再看看有没有闪现窗体和刚才设计的各种组件。雷 达图像处理===图标为雷达图===成功!===== ===图标为雷达图===成功!=====我为各 达图像处理===图标为雷达图===成功!=====我为各 个菜单加了图标, panel设计的工具栏 设计的工具栏, 个菜单加了图标,用panel设计的工具栏,不加状态栏 了==== 接着就设计About对话框,然后运行看效果( 接着就设计About对话框,然后运行看效果(当然要 About对话框 在主窗体的相关按钮上添加相应的代码) 在主窗体的相关按钮上添加相应的代码),另外还要 在该对话框上添加关闭的代码
2. 霍夫曼编码压缩 3. LZW压缩方法 LZW压缩方法 4. 算术压缩方法
DCT压缩算法分析与实现 DCT压缩算法分析与实现
系统模块总图: 系统模块总图:
DCT压缩算法: DCT压缩算法: 压缩算法
Delphi扫描线的快速图像处理
B r n 公 司推出 的 Widw 编 程工具 D lh 以其高度优 ol d a nos ep i 化 的编译器 、强大 的面 向特 性而越 来越受 到广 大编程 爱好 者 青 睐 ,在许多大型项 目如大型数 据库系统设计 、纹织 C D等 A 企业级解决方案上有独特 的优势 。D lh 开发 图像处理软件一 ep i 般有两 种基本方法 : 第一种方 法是利 用 D lh 已经封装好 了的 e i p
摘 要 : 统 的 图像 处 理 一 般 采 用 像 素 点 赋 值 的 方 法 ,处 理 速 度 极 慢 , 于大 型 图像 几 乎 无 能 为 力 ,而 D lh 扫 描 线 传 对 e i p
方法是对 图像 的每一行进行扫描 ,获得各像素的 内存地 址。这种 内存操作 比常规 的像 素点赋值效率 高很 多,从 而可
以 大 大提 高 大 型位 图 图像 的 处 理 速 度 。
关键 词 : 内存操 作 ; 图像 处 理 ;扫描 线
F s ma e P o e sn a e n S a l e o l h at I g r c s i g B s d o c n i fDep i n
速 。经 测试 ,S al e的速度 为 C n a. xl x 【]方法 的 cni n a vs ie 】 Y P s【 y
2 0倍 以 上 。D lh 的 Sa l e包 含 了 像 素 点 的 数 据 , 在 访 问 e i p cni n 但
像 素数 据以前 ,必须 知道 在内存中 Pxlo t i F r 属性 对 S al e e ma c n n i
t pe d o ma e pr c s ig h s b e r a l mpr e . he s e fi g o e sn a e n g e ty i ov d K e o ds y w r :me r pe ai n; i g r ce sn mo y o r to ma e p o si g; s a lne c ni
delphi使用流实现jpg文件的处理(转)
一、原理介绍--流式数据的类型及其应用在Dephi中提供了TStream来支持对流式数据的操作。
TStream是万流之源。
但由于它是一个抽象类,故不能被直接使用;而要使用其相应的子类,如:TFileStream 、TStringStream、TMemoryStream、TBlobStream、TWinSocketStream和TOleStream。
TStream提供了统一、简洁的方法来进行数据的读写。
1.)SaveToStream(Stream: TStream ); 作用:将类中的数据写到Stream的当前位置中2.)LoadFromStream(Stream: TStream); 作用:从当前位置读入Stream里的数据实际使用时我们基本上只要使用上面两个函数就可以了。
二、所遇到的问题及相应的解决方法为了节省图像的存储空间和使用更加方便,决定采用JPEG这种图像格式。
(一)所遇到的问题第一、在Delphi 5中进行画图所用到的组件是TImage,所生成的图像的格式为BMP格式,而为了节省图像的存储空间,图像在数据库里存储的格式须为JPEG格式,这样就产生了图像格式转化的需求;而TImage本身并不直接提供这两种图像格式之间的转化。
第二、怎样将存储在Microsoft Access数据库中的图像取出并且显示出来:在Delphi 5 中,能提供这种功能的组件是TDBImage,但该组件却存在着一个很大的缺陷:它所能显示的图像类型只能是一些图标文件,元文件和BMP文件,而不能支持JPEG格式的图像在该组件中的显示;但根据实际需要,在Microsoft Access数据库中所存储的图像数据却是以JPEG格式保存的。
(二)相应的解决方法为了解决上述两个问题,可以采用目前数据库中一种名为大二分对象(BLOB--Binary Large Object),它是用来处理某些特殊格式的数据的。
BLOB在数据库的表中实际上是以二进制数据的形式存放的。
Delphi中图像的像素级操作
Delphi中图像的像素级操作Delphi中图像的像素级操作华软源码一般的可视性编程语言,如VB本身只具有图像的一般显示功能, 加上简单的图像伸缩处理, 在进行一些图像复杂的特技显示时必须借助于Windows的有关API 函数。
但Delphi为用户提供了更为完善的图像处理能力, 依靠它本身的功能完全可以实现图像的像素级操作?疚慕樯芰薉elphi中像素级图像操作的基本原理、应用和实例。
一、基本原理在Delphi中有很多控件具有CANVAS属性, 即所谓的画布, 利用这一属性可以在控件的表面进行图形图像处理工作, 其中有一个CopyRect命令, 具体参数格式:Copyrect(Dest:TRect;Canvas:Tcanvas;Source:TRect);其中:Dest:目标画布矩形 Canvas:源画布 Source:源矩形,其功能是把图像从一个源矩形RECT内,复制到目标矩形RECT内, 复制的图像具有自动伸缩性质。
从这个命令的表面看只能进行图像的全部或部分复制功能,其实如果把矩形RECT定义成只有一个像素大小, 即可以从源图像中取出一个像素点, 即进行图像的像素级操作, 比如:Rect(0,0,1,1)可指定某图像源的左上角第一个像素。
二、像素级操作的应用图像的像素级操作可广泛应用在图像的特技显示效果制作工作中, 并且可以实现较为复杂的图像处理工作, 举例如下:1.图像的旋转: 在Delphi中利用其他方法显示图像时,比如利用图像框IMAGE 或者DRAW命令, 只能按原图的方向显示, 进行图像的旋转显示必须以像素为单位进行处理,重新安排像素的排列位置, 比如按先横向后纵向的方式读取原图像,然后按先纵向后横向的方式写像素,最终将形成旋转90度的图像,按同样的原理可形成旋转180度或270度的图像。
2.图像尺寸的改变: 图像尺寸的改变在Windows 中好象并不需要像素级操作, 利用图像框的伸缩性可以简单地完成这一工作, 但利用像素操作改变图像尺寸是图像放大或缩小操作的根本, 并且可以具有更高的精确和更高的灵活性?热绾嶙菹蚓扛粢坏闳∫幌袼? 连续写在目标画布上, 即可使图像缩小到原来的四分之一;而读出一点像素后, 在目标画布上连续写两点以上, 即可实现图像的放大显示。
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,累积权数大于或等于这个数的组的值就是中位数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图像处理基本知识彩色变灰度
把一图由彩色变成灰度,也就是把每个像素的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 do
begin
p := bmp.ScanLine[j];
for i := 0 to Bmp.Width - 1 do
begin
gray1 :=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的取反。