Die Beispiele in diesem Artikel fassen die grundlegenden Bildverarbeitungsmethoden von Delphi zusammen. Teilen Sie es als Referenz mit allen. Die spezifische Analyse lautet wie folgt:
//Emboss-Prozedur Emboss(SrcBmp,DestBmp:TBitmap;AzimuthChange:integer);overload;var i, j, Gray, Azimuthvalue, R, G, B: integer; SrcRGB, SrcRGB1, SrcRGB2, DestRGB: pRGBTriple;begin for i: = 0 bis SrcBmp.Height - 1 beginnt mit SrcRGB := SrcBmp.ScanLine[i]; DestBmp.ScanLine[i]; if (AzimuthChange >= -180) and (AzimuthChange < -135) then begin if i > 0 then SrcRGB1 := SrcBmp.ScanLine[i-1] sonst SrcRGB1 := SrcRGB; Inc(SrcRGB1); := SrcRGB; Inc(SrcRGB2); end else if (AzimuthChange >= -135) and (AzimuthChange < -90) then begin if i > 0 then SrcRGB1 := SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; Inc(SrcRGB2); end else if (AzimuthChange >= -90) und (AzimuthChange < -45) dann beginnen, wenn i > 0, dann SrcRGB1 := SrcBmp.ScanLine[i-1] sonst SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; end sonst, wenn (AzimuthChange >= -45) und (AzimuthChange < 0) beginnen dann mit 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) dann SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB; end else if (AzimuthChange >= 45) und (AzimuthChange < 90) then begin if (i < SrcBmp.Height - 1) then SrcRGB1 := SrcBmp.ScanLine[i +1] sonst 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) und (AzimuthChange <= 180) then begin if (i < SrcBmp.Height - 1) then SrcRGB2 := SrcBmp.ScanLine[i+1] else SrcRGB2 := SrcRGB2; = SrcRGB; Inc(SrcRGB1); für j := 0 bis 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) div 45)+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45- Azimutwert)div 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; end else if (AzimuthChange >= -135) und (AzimuthChange < -90) dann beginnen Azimuthvalue := AzimuthChange + 135; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45-Azimuthvalue) div 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue) *Azimutwert 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) *Azimutwert 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(SrcRGB2,-1); end; 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- Azimutwert)div 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; end else if (AzimuthChange >= 0) und (AzimuthChange < 45) dann beginnen, wenn j=1, dann beginnen Inc(SrcRGB1,-1); end; 45-Azimutwert)div 45)+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45-Azimuthvalue) div 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue) *Azimutwert div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; end else if (AzimuthChange >= 45) and (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) *Azimutwert 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 Wenn (AzimuthChange >= 90) und (AzimuthChange < 135), dann beginne Azimuthvalue := AzimuthChange - 90; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue div 45)-((SrcRGB2.rgbtRed)*(45 -Azimutwert) div 45)+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Azimuthvalue div 45)-((SrcRGB2.rgbtGreen)*(45-Azimuthvalue) div 45)+78; B:=SrcRGB.rgbtBlue-( (SrcRGB1.rgbtBlue)*Azimutwert 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) *Azimutwert div 45)-((SrcRGB2.rgbtGreen)*(45-Azimutwert) div 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimutwert div 45)-((SrcRGB2.rgbtBlue)*(45- Azimutwert) div 45)+78; R:=Min(R,255); G:=Min(G,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.rgbtBlue:=Gray; wenn (j=-180) und (AzimuthChange<-135)) oder ((AzimuthChange>=90) und (AzimuthChange<=180). ))) then begin Inc(SrcRGB1); end if (j=135) und (AzimuthChange<180)) oder ((AzimuthChange>=-180) und (AzimuthChange<=-90))) dann begin Inc(SrcRGB2); end; Ende; Ende; Ende; Verfahren Emboss(Bmp:TBitmap;AzimuthChange:integer;ElevationChange:integer;WeightChange:integer);overload;var DestBmp:TBitmap;begin DestBmp:=TBitmap.Assign(Bmp); Emboss(Bmp,DestBmp,AzimuthChange,ElevationChange ,Gewichtsänderung); Bmp.Assign(DestBmp);end;//Inverse 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 begin PRGB^.rgbtRed :=not PRGB^.rgbtGreen :=not PRGB^.rgbtBlue;end;end; Belichtungsverfahren Exposure(Bmp:TBitmap);var i, j: integer; PRGB: pRGBTriple;begin Bmp.PixelFormat:=pf24Bit; für i := 0 bis Bmp.Height - 1 beginnen PRGB := Bmp.ScanLine[i]; für j := 0 bis Bmp.Width - 1 beginnen, wenn PRGB^.rgbtRed<128 dann PRGB^.rgbtRed :=nicht PRGB^.rgbtRed ; wenn PRGB^.rgbtGreen<128 then PRGB^.rgbtGreen :=not PRGB^.rgbtGreen; if PRGB^.rgbtBlue :=not PRGB^.rgbtBlue; end;end;//blur procedure Blur( SrcBmp:TBitmap);var i, j:Integer; SrcRGB:pRGBTriple; SrcNextRGB:pRGBTriple; Value:Integer; begin Inc(SrcNextRGB); end; 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]; SrcBmp.ScanLine[i]; wenn i < SrcBmp.Height - 1 then SrcNextRGB:=SrcBmp.ScanLine[i+1] else SrcNextRGB:=SrcBmp.ScanLine[i]; for j := 0 to SrcBmp.Width - 1 do begin if j > 0 then DecRGB; Value:=SrcPreRGB.rgbtRed+ SrcRGB .rgbtRed+SrcNextRGB.rgbtRed; wenn j > 0 dann IncRGB; Wert:=(Wert+SrcPreRGB.rgbtRed+SrcRGB.rgbtRed+SrcNextRGB.rgbtRed) div 9; DecRGB; SrcRGB.rgbtRed:=value; if j > 0 then DecRGB; if j > 0 then DecRGB; Wert:=Wert+SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen; wenn j < SrcBmp.Width - 1, dann IncRGB; Wert:=(Wert+SrcPreRGB.rgbtGreen+SrcNextRGB.rgbtGreen) div 9; ; SrcRGB.rgbtGreen:=Wert; wenn j>0, dann DecRGB; Wert:=SrcPreRGB.rgbtBlue+SrcNextRGB.rgbtBlue; wenn j>0, dann IncRGB; Wert:=Wert+SrcPreRGB.rgbtBlue+SrcNextRGB .rgbtBlue; wenn j < SrcBmp.Width - 1 then IncRGB; Value:=(Value+SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue) div 9; DecRGB; SrcRGB.rgbtBlue:=value; end;end;//sharpening procedure Sharpen(SrcBmp:TBitmap);var i, j: integer; SrcRGB: pRGBTriple; Wert: integer;begin SrcBmp.PixelFormat:=pf24Bit; for i := 0 to SrcBmp.Height - 1 do begin SrcRGB := SrcBmp.ScanLine[i]; 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; Wert:=Max(0,Wert); Wert:=Min(255,Wert); Wert:=SrcRGB.rgbtGreen+(SrcRGB.rgbtGreen) div 2; Wert:= Max(0,Wert); Wert:=Min(255,Wert); SrcRGB.rgbtGreen:=Wert; Wert:=SrcRGB.rgbtBlue+(SrcRGB.rgbtBlue) div 2; Wert:=Max(0,Wert); Wert:=Min(255,Wert); value; Inc(SrcRGB); end;end; [Bilddrehung und Spiegelung] Der folgende Code wird mithilfe von ScanLine mit Zeigerbewegung für 24-Bit-Farbe implementiert! //Um 90 Grad drehen Prozedur Rotate90(const Bitmap:TBitmap);var i,j:Integer; rowIn,rowOut:pRGBTriple;Bmp:=TBitmap.Create; Bitmap.Height; Bmp.Height := Bitmap.Width; Bmp.PixelFormat := pf24bit; Breite:=Bitmap.Height-1; für j := 0 bis Höhe beginnen rowIn := Bitmap.ScanLine[j]; = Bmp.ScanLine[i]; Inc(rowOut,Height - j); rowIn^ := rowIn^ end; Bitmap.Assign(Bmp);end;//Rotate 180-Grad-Prozedur Rotate180(const Bitmap:TBitmap);var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap;Width,Height:Integer;begin Bmp:= TBitmap.Create; Bmp.Width := Bitmap.Width; Bitmap.Height; Bmp.PixelFormat := pf24bit; Height:=Bitmap.Height-1; for j := 0 to Height do begin rowIn := Bitmap.ScanLine[j]; := 0 bis Breite do begin rowOut := Bmp.ScanLine[Height - j]; rowOut^ := rowIn^; end; pRGBTriple; Bmp:TBitmap;Width,Height:Integer;begin Bmp:=TBitmap.Create; := Bitmap.Height := Bitmap.Width; Bmp.PixelFormat := pf24bit; Height:=Bitmap.Height-1; := Bitmap.ScanLine[j]; for i := 0 to Width do begin rowOut := Bmp.ScanLine[Width - i]; rowOut^ := rowIn^;end;//Any angle function RotateBitmap; TBitmap;Angle:Integer;BackColor:TColor):TBitmap;var i,j,iOriginal,jOriginal,CosPoint,SinPoint: integer; RowOriginal,RowRotated : pRGBTriple; AngleAdd : integer;begin Result:=TBitmap.PixelFormat := pf24bit; ; wenn Winkel<0 dann Angle:=360-Abs(Angle); if Angle=0 then Result.Assign(Bitmap) else if Angle=90 then begin Result.Assign(Bitmap);//Wenn es um 90 Grad gedreht ist, rufen Sie auf es direkt Der obige Code end else if (Angle>90) and (Angle<180) then begin AngleAdd:=90; Angle:=Angle-AngleAdd; end else if Angle=180 then begin Result.Assign(Rotate180(Result);//Wenn es um 180 Grad gedreht wird, rufen Sie den obigen Prozess direkt aufend else if (Angle>180) und ( Angle<270) then begin AngleAdd:=180; Angle:=Angle-AngleAdd; else if Angle=270 then begin Result.Assign(Bitmap); Rotate270(Result);//Wenn es um 270 Grad gedreht wird, rufen Sie den obigen Prozess direkt auf 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)); = 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)); ; CosTheta:=Abs(CosTheta); SinTheta:=Abs(SinTheta); (AngleAdd=0) oder (AngleAdd=180) then begin CosPoint:=Round(Bitmap.Height*CosTheta); end else begin SinPoint:=Round(Bitmap.Width*CosTheta). ); CosPoint:=Round(Bitmap.Width*SinTheta); für j := 0 bis 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-SinTheta)*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-SinTheta)*SinTheta); (CosPoint-j-1)*SinTheta); 270: begin iOriginal := Bitmap.Width-Round((j+1)*SinTheta-(i+1-SinPoint)*CosTheta); jOriginal := Round((i+1)*SinTheta-(CosPoint-j-1)*CosTheta)-1 ; Ende; Ende; wenn (iOriginal >= 0) und (iOriginal <= Bitmap.Width-1) und (jOriginal >= 0) (jOriginal <= Bitmap.Height-1) then begin RowOriginal := Bitmap.Scanline[jOriginal]; ; end; end; end;//Horizontales Flip-Verfahren FlipHorz(const Bitmap:TBitmap);var i,j:Integer; rowIn,rowOut:pRGBTriple;Bmp:TBitmap;begin Bmp:=TBitmap.Width := Bitmap.Height; PixelFormat := pf24bit; Breite:=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]; ,Width - i); rowOut^ := rowIn^; Bitmap.Assign(Bmp);end;//vertikale Flip-Prozedur FlipVert(const Bitmap:TBitmap);var i,j:Integer; rowIn,rowOut:pRGBTriple;Bmp:TBitmap.Create;Bmp.Height; Höhe := Bitmap.Width; Bmp.PixelFormat := pf24bit; Breite:=Bitmap.Width-1; Höhe:=Bitmap.Height-1; für j := 0 bis Höhe beginnen rowIn := Bitmap.ScanLine[j]; für i := 0 bis Breite beginnen rowOut := Bmp .ScanLine[Height - j]; rowOut^ := rowIn^; Bitmap.Assign(Bmp);end;[Anpassung von Helligkeit, Kontrast und Sättigung] Der folgende Code wird mithilfe von ScanLine mit Zeigerbewegung implementiert! Funktion 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;//Verfahren zur Helligkeitsanpassung BrightnessChange(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]; 1 beginnen, wenn ValueChange > 0, dann beginnen Sie mit DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + ValueChange); DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange); DestRGB.rgbtBlue := Min(255, SrcRGB.rgbtBlue + ValueChange); =Max(0, SrcRGB.rgbtRed + ValueChange); DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtBlue); ;Ende;Ende;//Kontrastanpassungsverfahren 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]; := 0 bis SrcBmp.Width - 1 beginnen, wenn ValueChange>=0, dann beginnen, wenn SrcRGB.rgbtRed >= 128, dann DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + ValueChange) sonst DestRGB.rgbtRed := Max(0 , SrcRGB.rgbtRed - ValueChange); if SrcRGB.rgbtGreen >= 128, dann DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange) sonst DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen - ValueChange); wenn SrcRGB.rgbtBlue >= 128, dann DestRGB.rgbtBlue := Min(255, SrcRGB.rgbtBlue + ValueChange) else DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue - ValueChange); + ValueChange) sonst DestRGB.rgbtRed := Min(128, SrcRGB.rgbtRed - ValueChange); wenn SrcRGB.rgbtGreen >= 128, dann DestRGB.rgbtGreen := Max(128, SrcRGB.rgbtGreen + ValueChange) sonst DestRGB.rgbtGreen := Min(128, SrcRGB .rgbtGreen - ValueChange); Inc(DestRGB); end; end;end;//Sättigungsanpassungsverfahren 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; Byte;beginValueChange:=ValueChange+255;for i := 0 to 255 do Alpha[i] := (i * ValueChange) Shr 8;x := 0;for i := 0 to 255 dobegin Gray := i - Alpha [i]; Grays[x] := Gray; Grays[x] := Grays[x]; Inc(x);end; für y := 0 bis SrcBmp.Height - 1 dobegin SrcRGB := SrcBmp.ScanLine[Y]; für x := 0 bis SrcBmp.Width - 1 beginne Gray := Grays[SrcRGB.rgbtRed + SrcRGB.rgbtGreen + SrcRGB.rgbtBlue]; wenn Gray + Alpha[SrcRGB.rgbtRed]>0, dann DestRGB.rgbtRed := Min(255,Gray + Alpha[SrcRGB.rgbtRed]) sonst DestRGB.rgbtRed := 0; rgbtGreen]>0 dann DestRGB.rgbtGreen := Min(255,Gray + Alpha[SrcRGB.rgbtGreen]) else DestRGB.rgbtGreen := 0; wenn Gray + Alpha[SrcRGB.rgbtBlue]>0 dann DestRGB.rgbtBlue := Min(255,Gray + Alpha[SrcRGB.rgbtBlue] ) else DestRGB.rgbtBlue := 0; Inc(DestRGB); end;end; end;//RGB-Anpassungsprozedur RGBChange(SrcBmp,DestBmp:TBitmap;RedChange,GreenChange,BlueChange:integer);var SrcRGB, DestRGB: i,j:integer;begin for i : = 0 bis SrcBmp.Height- 1 beginnt mit 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) sonst DestRGB.rgbtRed := Max(0, SrcRGB.rgbtRed + RedChange); wenn GreenChange> 0, dann DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + GreenChange) sonst DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + GreenChange); wenn BlueChange> 0 dann DestRGB .rgbtBlue := Min(255, SrcRGB.rgbtBlue + BlueChange) else DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue + BlueChange); Inc(DestRGB);[Farbanpassung]//RGB<=>BGRprocedure RGB2BGR(const Bitmap:TBitmap);var X: Integer; Y: Integer; pRGBTriple; Color: Byte;begin for Y := 0 to (Bitmap.Height - 1) do begin for X := 0 to (Bitmap.Width - 1) do begin Color := PRGB^.rgbtRed : = PRGB^.rgbtBlue; PRGB^.rgbtBlue := Color Inc(PRGB end); end;end;//Grayscale (weighted) procedure Grayscale(const Bitmap:TBitmap);var do begin PRGB := Bitmap.ScanLine[Y]; for X := 0 to (Bitmap.Width - 1) do begin Gray := (77 * Rot + 151 * Grün + 28 * Blau) shr 8; PRGB^.rgbtGreen:=Gray; PRGB^.rgbtBlue:=Gray;end; ;
Theorie:
Schlüsselwörter:
Zeichenbereich – das ist der Bereich, in dem das Fenster das Bild anzeigt, der auch der Vollbildmodus sein kann (der Zeicheneffekt ist im Vollbildmodus besser als im allgemeinen Fenster).
Mittelpunkt – das sind die Koordinaten des Mittelpunkts, der im Zeichenbereich im Originalbild angezeigt werden soll (Haftungsausschluss: Dieses Konzept ist besonders wichtig)
Lassen Sie uns zunächst über die Bildvergrößerung sprechen. Unser allgemeiner Ansatz besteht darin, das Bild direkt zu vergrößern. Die in diesem Artikel vorgestellte Methode vergrößert jedoch nur den Teil, den wir sehen können Die Vergrößerung ist größer als die Zeichenfläche. Zu dieser Situation gibt es natürlich nichts zu sagen. Das zweite ist, dass das vergrößerte Bild größer ist als der Zeichenbereich. Dies ist das Schlüsselthema, das wir heute besprechen werden. In diesem Fall müssen wir zuerst die Größe des vergrößerten Bildes bestimmen und dann die Größe des Bildes berechnen Originalbild basierend auf der Position und Größe des „Mittelpunkts“ und schließlich das aufgenommene Bild auf den Zeichenbereich vergrößern.
Lassen Sie uns über das Bild-Roaming sprechen. Wenn das angezeigte Bild den Zeichenbereich überschreitet, müssen wir das Bild durchstreifen, um das gesamte Bild zu sehen. Das Prinzip ist: Wenn die Maus in den Zeichenbereich klickt, beginnt sie zu wandern, zeichnet zuerst die Klickposition der Maus auf, erkennt dann die Bewegung der Maus und berechnet den „Mittelpunkt“ basierend auf der Maus und der letzten Verschiebung ( Die Bildschirmkoordinaten müssen in Originalbildkoordinaten umgewandelt werden. Nehmen Sie den anzuzeigenden Teil gemäß dem oben genannten Vergrößerungsprinzip aus dem Originalbild heraus, vergrößern Sie ihn und zeigen Sie ihn im Zeichenbereich an.
Algorithmusimplementierung:
1. Bildvergrößerung
Variablendefinition:
PZoom: Vergrößerungsrate (Ganzzahl: 100 ist 100 %, 100 kann bei Bedarf in 10000 oder größer geändert werden, Gleitkommazahlen werden jedoch nicht empfohlen)
a, b: Mittelpunkt
w, h: Breite und Höhe des aufzunehmenden Originalbildes
x, y: die abzufangende Position (obere linke Ecke)
sw,sh: Breite und Höhe des Originalbildes
p1, p2: Vergrößerungsverhältnis
aw,ah: die Größe des vergrößerten Bildes
pw,ph: Zeichenbereichsgröße
vx,vy: die im Zeichenbereich angezeigte Position (obere linke Ecke)
vw, vh: Die im Zeichenbereich angezeigte Größe
ptx, pty: temporäre Variablen
Bekannte Variablen: PZoom, (a, b), (sw, sh), (p1, p2), (aw, ah), (pw, ph)
Zu berechnende Variablen: (x,y),(w,h),(vx,vy),(vw,vh)
Beginnen Sie mit der Berechnung:
aw=Round(PZoom*sw/100);ah=Round(PZoom*sh/100);p1=aw/pwp2=ah/ph// Hinweis: Round wird zum Runden verwendet, z. B. Int(), Fix in anderen Sprachen ()usw. wenn p1>1 dann w=Round(sw/p1) sonst w=swif p2>1 dann h=Round(sh/p2) sonst h=sh// Hinweis: shr ist der rechte Verschiebungsoperator. Sie können „>>1“, „div 2“, „/2“ oder „Round(w/2)“ anstelle von x=aw shr 1y=bh verwenden shr 1 // Hinweis: div ist der ganzzahlige Divisionsoperator ptx=(w*PZoom) div 100pty=(h*PZoom) div 100// Im Folgenden wird die Größe und Position des im Zeichenbereich angezeigten Bildes berechnet
Variable
Pencent:double; // Zoomverhältnis wx:double; // Hohes Zoomverhältnis // Zoomverhältnis wx:=pw/ptx ermitteln, wenn wx>hx, dann Pencent: =hx else Pencent:=wx; // Die endgültige Größe des Bildes ermitteln vw:=Round(Pencent*ptx); Berechnen Sie die Position des Bildes vx:=(pw-vw) div 2; vy:=(ph-vh) div 2;// -------------------- - ---------------
Okay, zwei wichtige Aufgaben wurden abgeschlossen (x, y), (w, h), (vx, vy), (vw, vh). Die folgende Arbeit wird angezeigt. Wir wählen die Windows-API, um den Vorgang auszuführen
Variable
sDC ist das Gerätehandle (DC) des Originalbildes. tDC ist das temporäre Gerätehandle ,STRETCH_DELETESCANS);StretchBlt(dDC ,0,0,vw,vh,tDC,0,0,w,h,SRCCOPY);
Zeichnen Sie abschließend in den angezeigten Bereich:
Zum Beispiel:
BitBlt(GetDC(0),vx,vy,vx+vw,xy+vh,dDC,0,0,SRCCOPY);
2. Bild-Roaming
Definieren Sie zunächst drei globale Variablen:
FBeginDragPoint :TPoint; // Zeichnen Sie die Position auf, an der die Maus mit dem Ziehen beginnt. FBeginDrag :boolean; // Ob „Ziehen“ von a, b begonnen hat: integer; " Standort
Wenn Sie mit der linken Maustaste klicken, zeichnen Sie die Position der Maus und die Position des „Mittelpunkts“ auf und setzen Sie FBeginDrag auf true.
Wenn die rechte Maustaste erscheint, setzen Sie FBeginDrag auf „false“.
Wenn die Maus bewegt wird, wird FBeginDrag beurteilt. Wenn es falsch ist, wird keine Verarbeitung durchgeführt. Wenn es wahr ist, wird die folgende Verarbeitung durchgeführt:
Nehmen Sie an, dass X und Y die aktuelle Position der Maus sind
a=FBeginDragPoint.X-((X-FBeginDragPoint.X)*100) div PZoomb=FBeginDragPoint.Y-((Y-FBeginDragPoint.Y)*100) div PZoom
Verwenden Sie abschließend das oben eingeführte Bild, um das Bild zu vergrößern und anzuzeigen
Tipps:
1. Wenn das Bild groß ist, tritt bei Verwendung des Bitmap-Objekts von Delphi ein Speicherüberlauffehler auf. In diesem Fall können Sie die folgenden Einstellungen vornehmen:
bitImage:=TBitmap.Create; bitImage.PixelFormat:=pf24bit;
2. Wenn Sie möchten, dass sich das Bild automatisch an die Größe des Fensters anpasst, verwenden Sie den folgenden Code:
var p1,p2 :double;begin p1:=pw/sw; if p1>p2 then PZoom:=Round(p2*100) else PZoom:=Round(p1*100); 0 dann PZoom:=100;end;
Delphi-Graustufenbild-Pixel-Farbhelligkeitsverarbeitung
Bei der Bildverarbeitung kommt es auf Geschwindigkeit an. Daher müssen wir TBitmap erneut verarbeiten, um TVczhBitmap zu erhalten. Das liegt nur daran, dass GetPixels und SetPixels zu langsam sind, sodass wir eine andere Methode verwenden müssen.
Unit untBitmapProc; Schnittstelle verwendet Graphics, SysUtils; private Data:PByteArray; Funktion GetBytePointer(X,Y:Integer;Value). :Byte); function GetBytes(X,Y:Integer):Byte; protected public construction; öffentliche Eigenschaft Bytes[X,Y:Integer]:Byte read SetBytes; procedure LoadFromFile; begin HandleType:=pf24bit; TVczhBitmap.GetBytePointer(X,Y:Integer):PByte; begin if Line<>Y then begin Line:=Y; Data:=ScanLine[Y]; end; Longint(Data)+X; begin X,Y)^:=Value; function TVczhBitmap.GetBytes(X,Y:Integer):Byte begin result:=GetBytePointer(X,Y)^; begin inherited SetFormat; begin inherited LoadFromFile(FileName); ; Line:=-1; procedure TVczhBitmap.ToGray; B:Byte; begin für Y:=0 bis Height-1 do für X:=0 bis width-1 do begin R:=0; für B:=0 bis 2 do R:=R+GetBytes(X*3+ B,Y); für B:=0 bis 2 do SetBytes(X*3+B,Y,R div 3); end;
Danach müssen wir mehrere Formulare erstellen. Das erste Formular dient der Anzeige von Bildern und das zweite Formular dient der Verarbeitung von Bildern. Alle anderen Formulare erben vom zweiten Formular und enthalten die eigentlichen Verarbeitungsmethoden.
Schauen wir uns zunächst das zweite Fenster an:
Unit untProc; Schnittstelle verwendet Windows, Nachrichten, Grafiken, Steuerelemente, Formulare, Dialoge, ExtCtrls; Typ TfrmProcessor = class(TForm) pbBar: TGroupBox; Button1: TButton; Prozedur FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button1Click(Sender: TObject); ..255]of Byte;TVczhBitmap; procedure DrawBar end; Implementierung {$R *.dfm} nutzt untViewer; procedure TfrmProcessor.DrawBar; var I:Integer; I:=1 bis 255 do Bar.Canvas.LineTo(I,255-BarData[I]); end; TfrmProcessor.FormCreate(Sender: TObject); begin Bar:=TVczhBitmap.Create; Bar.Height:=256; Bar.Canvas.Brush.Style: =bsSolid; end; procedure TfrmProcessor.FormDestroy(Sender: TObject); end; procedure TfrmProcessor.FormShow(Sender: TObject); var I:Integer; begin for I:=0 bis 255 do BarData[I]:=I; end; .Canvas.Draw(0,0,Bar); end; procedure TfrmProcessor.Button1Click(Sender: TObject); var X,Y:Integer; begin for Y:=0 to Buffer.Height-1 do for X,Y]]; frmViewer.FormPaint(frmViewer); end.
Erstellen Sie anschließend ein Fenster, das davon erbt, passen Sie dann BarData[] an und klicken Sie auf „Übernehmen“, um das Ergebnis anzuzeigen.
Beginnen Sie nun mit der Bearbeitung des Bildes. Spezifische Effekte finden Sie im Beispielprogramm.
1. Farbumkehr.
Die Farben von Graustufenbildern reichen von 0 bis 255. Um die Farbe zu invertieren, können wir den Farbwert von 255 subtrahieren, um die invertierte Farbe zu erhalten.
var I:Integer; begin inherited; for I:=0 to 255 do BarData[I]:=255-I;//Subtract the color value from 255 DrawBar;
2. Verengen Sie den Farbbereich, um die Helligkeit zu verstärken oder abzuschwächen
Die Farbe liegt ursprünglich zwischen 0 und 255. Wenn Sie den Bereich anpassen, beispielsweise von 0 bis 16, wird das Bild deutlich dunkler. Wir können den Startwert auf a und den Endwert auf b setzen, dann ist der neue Farbwert Neu=a+(b-1)*Alt/255. Dadurch wird die Helligkeit verändert, ohne die ursprüngliche Farbfolge zu zerstören. Der Code lautet wie folgt
var I:Integer; begin for I:=0 bis 255 do BarData[I]:=(255-sbMin.Position)+Round((sbMin.Position-sbMax.Position)/255*I); ); Button1Click(Button1);
Die sbMin.Position und die sbMaxPosition sind hier beide invertiert. Verwenden Sie daher 255 zum Subtrahieren
3. Erhöhen Sie den Farbbereich innerhalb eines bestimmten Bereichs
Wenn das Bild selbst einen kleinen Farbbereich aufweist, können Sie mit dieser Methode den Kontrast des Bildes erhöhen, was sich positiv auf die Bildanalyse auswirkt. Spezifische Methoden:
Wählen Sie einen Wert a als Startwert, einen Wert b als Endwert und verformen Sie ihn dann gemäß der folgenden Formel:
|. 0 (X<=a)
f(X)= |. 255/(ba)*(Xa)
|. 255(X>=b)
var I:Integer; begin for I:=0 bis 255 do begin if I<=sbMin.Position then BarData[I]:=0 else if I>=sbMax.Position then BarData[I]:=255 else BarData[I ]:=Round(255/(sbMax.Position-sbMin.Position)*(I-sbMin.Position)); pbBarPaint(pbBar); Button1Click(Button1);
4. Konvertieren Sie in Schwarzweißbilder
Wenn Sie die dritte Funktion verwenden, werden Sie feststellen, dass bei b <= a die Farben im Bild außer Schwarz weiß sind. Der Nutzen dieser Operation lässt sich nicht direkt darstellen. Dies wird nur dann effektiv sein, wenn es um eine fortgeschrittenere Bildverarbeitung wie die Kantenerkennung geht. Dieses Beispiel kann mit der Formel der dritten Methode transformiert werden und wird daher nicht im Detail erläutert.
5. Exponentielle Helligkeitsanpassung
Wir gehen davon aus, dass die Domäne dieses Diagramms [0,1] ist und der Wertebereich ebenfalls [0,1] ist. Definieren Sie dann die Funktion f(x)=x^c, dann hat das Bild von f(x) einen Abschnitt wie oben gezeigt. Wenn wir die Maus verwenden, um wieder zu arbeiten, können wir einen Punkt p (a, b) darauf einnehmen und dann f (x) den Punkt P durchlaufen lassen, dann c = ln (b)/ln (a). Mit C können wir mit Farbe arbeiten:
Neu = (alt/255)^c*255 = exp (ln (alt/255)*c)*255 var ea, EB, EC: Extended; /255; Bardata [i]: = rund (ln ((i/255)*ec)*255)
Wenn Sie dies tun, passt die Helligkeit des Bildes an.
Tipps zur Anzeige von Spezialeffekten in Delphi -Grafiken
Überblick
---- In vielen Lernsoftware- und Game-CDs können Sie derzeit oft verschiedene sehen
Die grafische Display -Technologie beruht auf grafischen Bewegungen, Interlacing, Regentropfenform, Jalousien, Baustücken und anderen Display -Methoden, um das Bild lebhafter und attraktiver für das Publikum zu gestalten. In diesem Artikel wird untersucht, wie verschiedene grafische Anzeigetechniken in Delphi implementiert werden.
Grundprinzipien
---- In Delphi ist es sehr einfach, ein Bild anzuzeigen. und die ausgewählte Datei wird in der Timage -Komponente angezeigt. Dies zeigt jedoch nur die Grafiken direkt in der Form an, und es gibt überhaupt keine Fähigkeiten. Um das grafische Display einen eindeutigen Effekt zu haben, können Sie die folgenden Schritte ausführen:
---- Definieren Sie eine Timage-Komponente und laden Sie die Grafiken zuerst in die Timage-Komponente, dh den Grafikinhalt von der Festplatte als Grafik-Cache in den Speicher.
---- Erstellen Sie ein neues Bitmap-Objekt mit der gleichen Größe wie die Grafik in der Timage-Komponente.
---- verwenden
Konvertieren Sie den Dateiinhalt in eine Bitmap und anzeigen Sie die Bitmap im Formular an.
---- Implementierungsmethode
Verschiedene grafische Anzeigetechniken werden nachstehend eingeführt:
1. Push-Pull-Effekt
Ziehen Sie die Grafiken, die von oben, links und rechts in den Bildschirm angezeigt werden sollen, und vertuschen gleichzeitig die ursprünglichen alten Grafiken auf dem Bildschirm. Ziehen Sie nach links und ziehen Sie nach rechts.
Prinzip: Bewegen Sie zuerst die erste horizontale Linie in der temporären Grafik auf die letzte in der zu angezeigten Bitmap und bewegen Sie die ersten beiden horizontalen Linien in der temporären Grafik auf die letzten beiden zu angezeigten Bitmaps Bewegen Sie dann die ersten drei und vier Zeilen, bis alle grafischen Daten verschoben sind. Während des Umzugsprozesses können Sie feststellen, dass die angezeigte Bitmap von unten nach oben schwimmt und einen Pull-up-Effekt erzielt.
Programmalgorithmus:
procedure tform1.button1click (Absender: tbmape); : = Image1.Height; i: = 0 bis bmpheight beginnen neubmp.canvas.copyct (rect (0, bmpheight-i, bmpwidth, bmpheight), Image1.canvas, rechteweise (0,0, Bmpwidth, i)); , neubmp);
2. Vertikaler gestaffelter Effekt
Prinzip: Teilen Sie die Grafiken in zwei Teile auf. Auf dem Bildschirm können Sie sehen, dass sich die leichteren Grafiken, die am oberen und unteren Enden erscheinen, in Richtung der Mitte des Bildschirms bewegt werden, bis sie vollständig klar sind.
Programmalgorithmus:
procedure tform1.button4click (Absender: Tobjekt); ; i: = 0; BMPHELT-I+J-1, BMPWIDTH, BMPHELT-I+J)); (0, bmpheight-J, bmpwidth, bmpheight-J+1), Image1.Canvas, RECT (0, IJ, BMPWIDTH, I-J+1); (120.100 Uhr, NeueBmp);
3.. Horizontal gestaffeltes Effekt
Prinzip: Das gleiche Prinzip wie der vertikale Interlacing -Effekt, mit der Ausnahme, dass die in zwei Gruppen unterteilten Grafiken vom linken bzw. rechten Enden in den Bildschirm verschoben werden.
Programmalgorithmus:
procedure tform1.button5click (Absender: TOBJECT); ; I: = 0; I+J-1,0, BMPWIDTH-I+J, BMPHELT)); (BMPWIDTH-J, 0, BMPWIDTH-J+1, BMPHEILT), Image1.Canvas, RECT (IJ, 0, I-J+1, BMPheight)); (120.100 Uhr, NeueBmp);
4. Regentropfeneffekt
Prinzip: Verschieben Sie die letzte Scan -Linie der temporären Grafik in die erste auf die letzte Scan -Linie der sichtbaren Bitmap nacheinander, sodass diese Scan -Linie ihre Spur auf dem Bildschirm hinterlassen kann. Anschließend wird die vorletzte Scan -Linie der temporären Grafik in die vorletzte Scan -Linien der sichtbaren Bitmap nacheinander verschoben. Und so weiter für die verbleibenden Scanlinien.
Programmalgorithmus:
procedure tform1.button3click (Absender: TObject); ; für i: = bmpheight bis 1 do für j: = 1 bis ich mit newbmp.canvas.copyct (rechte (0, J-1, Bmpwidth, J), Image1.canvas, rect (0, i-1, bmpwidth, i));
5. Glouvres -Effekt
Prinzip: Teilen Sie die in der temporären Grafik platzierten Daten in mehrere Gruppen und bewegen Sie sie dann nacheinander von der ersten Gruppe in die letzte Gruppe. Zeit bewegen Sie die zweite Scan -Linie und bewegen Sie dann die dritte und vierte Scan -Linien.
Programmalgorithmus:
procedure tform1.button6click (Absender: TOBJECT); Höhe: = Image1.Height; bmpwidth: = image1.width; -1, bmpwidth, xcount*j+i), Image1.canvas, RECT (0, XCount*J+I-1, BMPWIDTH, XCOUNT*J+I);
6. Bausteineffekt
Prinzip: Es ist eine Variation des Regentropfeneffekts.
Programmalgorithmus:
procedure tform1.button7click (Absender: TObject); ; I: = BMPHELTS; Bmpwidth, i)); Ende;
Abschluss
Die oben genannten grafischen Display -Effekte wurden alle auf den Computer übergeben. Es funktioniert großartig.
Implementierung der Bildmarkierung mit Delphi
Fügen Sie dem Formular zwei Timage -Komponenten hinzu. Eine andere Timage -Komponente hat ihre Namenseigenschaft auf Image2 festgelegt, in der das vergrößerte Bild angezeigt wird.
Der Kern dieses Beispiels ist die Stretchblt -Funktion.
Prozedur tform1.image1MousEmove (Absender: Tobject; Shift: TShiftState; X, Y: Integer); 20,40,40, srccopy); Screen.cursors [1]: = loadCursorFromFile ('Magnify.cur');
Das Programm ruft zunächst die StretchBlt -Funktion auf, verwenden die aktuelle Position der Maus als Mittelpunkt, wählen Sie das partielle Bild auf der Image1 -Komponente mit einer Seitenlänge von 40 aus und vergrößern das partielle Bild in die Image2 -Komponente. Aktualisieren Sie dann die Anzeige der Image2 -Komponente, indem Sie die Aktualisierungsmethode der Image2 -Komponente aufrufen. Stellen Sie den Mauszeiger schließlich auf die neue Form.
Der Programmcode lautet wie folgt:
Einheit 1; InterfaceSeSewows, Nachrichten, Systeme, Varianten, Klassen, Grafiken, Steuerelemente, Formulare, Dialoge, extctrls, stdctrls; type tform1 = class (tform) Bild1: Timage: Timage; ; X, y: Ganzzahl); FormMousemove (Absender: Tobject; Verschiebung: TShiftstate; Verschiebung: tShiftstate; x, y: Ganzzahl); BeginnstretchBlt (Image2.Canvas.Handle, 0,0, Image2.Width, Image2.Height, Image1.Canvas.Handle, X-20, Y-20,40,40, Srccopy); ]: = LoadCursOrfromFile ('Magnify.cur'); Self.Cursor: = 1; Ende; Verfahren tform1.Formmousemove (Absender: Tobject; Shift: TShiftState; x, y: Integer); .
Speichern Sie die Datei und drücken Sie dann die F9 -Taste, um das Programm auszuführen, und das Programm wird ausgeführt.
Die Vergrößerung von Bildern ist eine wesentliche Funktion einer exzellenten Bild -Anzeige -Software.
Ich hoffe, dass dieser Artikel für alle bei der Delphi-Programmierung hilfreich sein wird.