The examples in this article summarize the basic image processing methods of Delphi. Share it with everyone for your reference. The specific analysis is as follows:
//Emboss procedure 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 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 then SrcRGB1 := 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) 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 < -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 >= 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) *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;procedure Emboss(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;//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^.rgbtRed ; PRGB^.rgbtGreen :=not PRGB^.rgbtGreen; PRGB^.rgbtBlue :=not PRGB^.rgbtBlue; Inc(PRGB); end; end;end;// Exposure procedure Exposure(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 if PRGB^.rgbtRed<128 then PRGB^.rgbtRed :=not PRGB^.rgbtRed ; if PRGB^.rgbtGreen<128 then PRGB^.rgbtGreen :=not PRGB^.rgbtGreen; if PRGB^.rgbtBlue<128 then PRGB^.rgbtBlue :=not PRGB^.rgbtBlue; Inc(PRGB); end; end;end;//blur 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; 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] 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; if j > 0 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 then IncRGB; 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;//sharpening procedure Sharpen(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; [Image rotation and flipping] The following code is implemented using ScanLine with pointer movement, for 24-bit color! //Rotate 90 degrees 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 begin rowOut : = Bmp.ScanLine[i]; Inc(rowOut,Height - j); rowOut^ := rowIn^; Inc(rowIn); end; end; Bitmap.Assign(Bmp);end;//Rotate 180 degrees procedure Rotate180(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[Height - j]; Inc(rowOut,Width - i); rowOut^ := rowIn^; Inc(rowIn); end; end; Bitmap.Assign(Bmp);end;//Rotate 270 degrees 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;//Any angle function RotateBitmap(Bitmap: TBitmap;Angle:Integer;BackColor:TColor):TBitmap;var i,j,iOriginal,jOriginal,CosPoint,SinPoint: integer; RowOriginal,RowRotated : pRGBTriple; SinTheta,CosTheta : Extended; AngleAdd : integer;begin Result:=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);//If it is rotated 90 degrees, call it directly The above 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(Bitmap); Rotate180(Result);//If it is rotated 180 degrees, call the above process directlyend 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);//If it is rotated 270 degrees, directly call the above process 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 begin SinPoint:=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-1)and (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;//Horizontal flip 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;//vertical flip procedure FlipVert(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[Height - j]; Inc(rowOut,i); rowOut^ := rowIn^; Inc(rowIn); end; end; Bitmap.Assign(Bmp);end;[Brightness, contrast, and saturation adjustment] The following code is implemented using ScanLine with pointer movement! 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;//Brightness adjustment procedure 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]; 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;//contrast adjustment 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); if SrcRGB.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 then DestRGB.rgbtBlue := Max(128, SrcRGB.rgbtBlue + ValueChange) else DestRGB.rgbtBlue := Min(128, SrcRGB.rgbtBlue - ValueChange); end; Inc(SrcRGB); Inc(DestRGB); end; end;end;//Saturation adjustment 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;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; Inc(x); Grays[x] := Gray; Inc(x); Grays[x] := Gray; Inc(x);end; for y := 0 to SrcBmp.Height - 1 dobegin 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 adjustment procedure RGBChange(SrcBmp,DestBmp:TBitmap;RedChange,GreenChange,BlueChange:integer);var SrcRGB, DestRGB: pRGBTriple; i,j:integer;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 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;[Color adjustment]//RGB<=>BGRprocedure RGB2BGR(const Bitmap:TBitmap);var X: Integer; Y: Integer; PRGB: 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^.rgbtRed : = PRGB^.rgbtBlue; PRGB^.rgbtBlue := Color; Inc(PRGB); end; end end;end;//Grayscale (weighted) 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 ;
Theory:
Keywords:
Drawing area - that is, the area where the window displays the image, which can also be the full screen (the drawing effect is better in the full screen than in the general window)
Center point - that is, the coordinates of the center point to be displayed in the drawing area in the original image (disclaimer: this concept is particularly important)
Let’s talk about image enlargement first. To enlarge a picture, our general approach is to enlarge the image directly, but the method introduced in this article only enlarges the part we can see. There are two situations of enlargement. One is that the area after enlargement is larger than the drawing area. It’s even smaller. There’s nothing much to say about this situation. Of course, it’s all displayed. Image; the second is that the enlarged image is larger than the drawing area. This is the key topic we are going to discuss today. In this case, we must first determine the size of the enlarged image, and then calculate the size of the original image based on the "center point" position and size, and finally enlarge the captured image to the drawing area.
Let’s talk about image roaming. When the displayed image exceeds the drawing area, we need to roam the image in order to see the entire image. The principle is: when the mouse clicks in the drawing area, it starts roaming, first records the click position of the mouse, then detects the movement of the mouse, and calculates the "center point" based on the mouse and the last displacement (the screen coordinates need to be Convert to original image coordinates), take out the part to be displayed from the original image according to the principle of magnification above, and enlarge and display it in the drawing area.
Algorithm implementation:
1. Image enlargement
Variable definition:
PZoom: Magnification rate (integer: 100 is 100%, 100 can be changed to 10000 or larger as needed, but floating point numbers are not recommended)
a, b: center point
w, h: width and height of the original image to be captured
x, y: the position to be intercepted (upper left corner)
sw,sh: width and height of the original image
p1, p2: magnification ratio
aw,ah: the size of the enlarged image
pw,ph: drawing area size
vx,vy: the position displayed in the drawing area (upper left corner)
vw, vh: the size displayed in the drawing area
ptx, pty: temporary variables
Known variables: PZoom, (a, b), (sw, sh), (p1, p2), (aw, ah), (pw, ph)
Variables to be calculated: (x,y),(w,h),(vx,vy),(vw,vh)
Start calculating:
aw=Round(PZoom*sw/100);ah=Round(PZoom*sh/100);p1=aw/pwp2=ah/ph// Note: Round is used for rounding, such as Int(), Fix in other languages ()etc if p1>1 then w=Round(sw/p1) else w=swif p2>1 then h=Round(sh/p2) else h=sh// Note: shr is the right shift operator, you can use ">>1", "div 2", "/2" or "Round(w/2)" instead of x=aw shr 1y=bh shr 1 // Note: div is the integer division operator ptx=(w*PZoom) div 100pty=(h*PZoom) div 100// The following calculates the size and position of the image displayed in the drawing area
variable
Pencent:double; // Zoom ratio wx:double; // Wide zoom ratio hx:double; // High zoom ratio // Get zoom ratio wx:=pw/ptx hx:=ph/pty if wx>hx then Pencent: =hx else Pencent:=wx; // Get the final size of the image vw:=Round(Pencent*ptx); vh:=Round(Pencent*pty); // Calculate the position of the picture vx:=(pw-vw) div 2; vy:=(ph-vh) div 2;// --------------------- ---------------
Okay, two important tasks have been completed (x, y), (w, h), (vx, vy), (vw, vh) have been calculated. The following work is displayed. We choose Windows API to perform operate
variable
sDC is the device handle (DC) of the original picture. tDC is the temporary device handle dDC and the final device handle. BitBlt(tDC,0,0,w,h,sDC,0,0,SRCCOPY);SetStretchBltMode(dDC,STRETCH_DELETESCANS);StretchBlt(dDC ,0,0,vw,vh,tDC,0,0,w,h,SRCCOPY);
Finally, draw to the displayed area:
For example:
BitBlt(GetDC(0),vx,vy,vx+vw,xy+vh,dDC,0,0,SRCCOPY);
2. Image roaming
First define three global variables:
FBeginDragPoint :TPoint; // Record the position where the mouse starts dragging FBeginDragSBPoint :TPoint; // Record the "center point" position FBeginDrag :boolean; // Whether "drag" a, b has started: integer; // "Center point" Location
When the left mouse button is clicked, record the position of the mouse and the position of the "center point", and set FBeginDrag to true.
When the right mouse button pops up, set FBeginDrag to false
When the mouse moves, FBeginDrag is judged. If it is false, no processing is performed. If it is true, the following processing is performed:
Assume that X and Y are the current position of the mouse
a=FBeginDragPoint.X-((X-FBeginDragPoint.X)*100) div PZoomb=FBeginDragPoint.Y-((Y-FBeginDragPoint.Y)*100) div PZoom
Finally, use the image introduced above to enlarge and display the image
Tips:
1. If the image is large, a memory overflow error will occur when using delphi's bitmap object. In this case, you can make the following settings:
bitImage:=TBitmap.Create; bitImage.PixelFormat:=pf24bit; bitImage.ReleaseHandle;
2. If you want the image to automatically adapt to the size of the window, refer to the following code:
var p1,p2 :double;begin p1:=pw/sw; p2:=ph/sw; if p1>p2 then PZoom:=Round(p2*100) else PZoom:=Round(p1*100); if PZoom= 0 then PZoom:=100;end;
Delphi grayscale image pixel color brightness processing
In image processing, speed is important. Therefore, we have to reprocess TBitmap to get TVczhBitmap. This is just because GetPixels and SetPixels are too slow, so we need to use another method.
unit untBitmapProc; interface uses Graphics, SysUtils; type TVczhBitmap=class(TBitmap) private Data:PByteArray; Line:Integer; procedure SetFormat; function GetBytePointer(X,Y:Integer):PByte; procedure SetBytes(X,Y:Integer;Value :Byte); function GetBytes(X,Y:Integer):Byte; protected published constructor Create; public property Bytes[X,Y:Integer]:Byte read GetBytes write SetBytes; procedure LoadFromFile(FileName:String); procedure ToGray; end; implementation procedure TVczhBitmap.SetFormat; begin HandleType:=bmDIB; PixelFormat:=pf24bit; end; function TVczhBitmap.GetBytePointer(X,Y:Integer):PByte; begin if Line<>Y then begin Line:=Y; Data:=ScanLine[Y]; end; Longint(result):=Longint(Data)+X; end; procedure TVczhBitmap.SetBytes(X,Y:Integer;Value:Byte); begin GetBytePointer( X,Y)^:=Value; end; function TVczhBitmap.GetBytes(X,Y:Integer):Byte; begin result:=GetBytePointer(X,Y)^; end; constructor TVczhBitmap.Create; begin inherited Create; SetFormat; Line:=-1; end; procedure TVczhBitmap.LoadFromFile(FileName:String); begin inherited LoadFromFile(FileName); SetFormat ; Line:=-1; end; procedure TVczhBitmap.ToGray; var X,Y,R:Integer; B:Byte; begin for Y:=0 to Height-1 do for X:=0 to Width-1 do begin R:=0; for B:=0 to 2 do R:=R+GetBytes(X*3+ B,Y); for B:=0 to 2 do SetBytes(X*3+B,Y,R div 3); end; end; end.
After this, we need to create several forms. The first one is used to display pictures, and the second one is used to process pictures. All other forms inherit from the second form and contain the actual processing methods.
Let’s look at the second window first:
unit untProc; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, untBitmapProc, StdCtrls, ComCtrls; type TfrmProcessor = class(TForm) pbBar: TPaintBox; gpProc: TGroupBox; Button1: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormShow(Sender: TObject); procedure pbBarPaint(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } BarData:array[0 ..255]of Byte; Bar:TVczhBitmap; procedure DrawBar; end; var frmProcessor: TfrmProcessor; implementation {$R *.dfm} uses untViewer; procedure TfrmProcessor.DrawBar; var I:Integer; begin Bar.Canvas.FillRect(Bar.Canvas.ClipRect); Bar.Canvas.MoveTo(0,255-BarData[0]); for I:=1 to 255 do Bar.Canvas.LineTo(I,255-BarData[I]); end; procedure TfrmProcessor.FormCreate(Sender: TObject); begin Bar:=TVczhBitmap.Create; Bar.Width:=256; Bar.Height:=256; Bar.Canvas.Brush.Color:=clWhite; Bar.Canvas.Brush.Style: =bsSolid; end; procedure TfrmProcessor.FormDestroy(Sender: TObject); begin Bar.Free; end; procedure TfrmProcessor.FormShow(Sender: TObject); var I:Integer; begin for I:=0 to 255 do BarData[I]:=I; DrawBar; end; procedure TfrmProcessor.pbBarPaint(Sender: TObject); begin pbBar .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:=0 to Buffer.Width*3-1 do Played.Bytes[X,Y]:=BarData[Buffer.Bytes[ X,Y]]; frmViewer.FormPaint(frmViewer); end; end.
After that, make a window that inherits from it, then adjust BarData[] and press Apply to see the result.
Now start processing the image. See the sample program for specific effects.
1. Color inversion.
The colors of grayscale images range from 0 to 255, so in order to invert the color, we can subtract the color value from 255 to get the inverted color.
var I:Integer; begin inherited; for I:=0 to 255 do BarData[I]:=255-I;//Subtract the color value from 255 DrawBar; pbBarPaint(pbBar); end;
2. Narrow the color range to enhance or weaken the brightness
Color is originally from 0~255. If you adjust its range, for example from 0 to 16, the image will become significantly darker. We can set the starting value to a and the ending value to b, then the new color value New=a+(b-1)*Old/255. Doing this changes the brightness without destroying the original color sequence. The code is as follows
var I:Integer; begin for I:=0 to 255 do BarData[I]:=(255-sbMin.Position)+Round((sbMin.Position-sbMax.Position)/255*I); DrawBar; pbBarPaint(pbBar ); Button1Click(Button1); end;
The sbMin.Position and sbMaxPosition here are both inverted. Therefore, use 255 to subtract
3. Increase the color range within a certain range
If the image itself has a small color range, you can use this method to increase the contrast of the image, which is beneficial to the analysis of the image. Specific methods:
Select a value a as the starting value, select a value b as the ending value, and then deform according to the following formula:
| 0 (X<=a)
f(X)= | 255/(ba)*(Xa)
| 255(X>=b)
var I:Integer; begin for I:=0 to 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)); end; DrawBar; pbBarPaint(pbBar); Button1Click(Button1); end;
4. Convert to black and white pictures
When using the third function, you will find that when b<=a, the colors on the image are white except black. The benefits of this operation cannot be directly displayed. This will only be effective when it comes to more advanced image processing such as edge detection. This example can be transformed using the formula of the third method, so it will not be explained in detail.
5. Exponential brightness adjustment
We assume that the domain of this graph is [0,1], and the value range is also [0,1]. Then, define the function f(x)=x^c, then the image of f(x) has a section as shown above. When we use the mouse to operate again, we can take a point P(a,b) on it, and then make f(x) pass through the point P, then c=ln(b)/ln(a). With c, we can operate on color:
New=(Old/255)^c*255=exp(ln(old/255)*c)*255 var ea,eb,ec:Extended; I:Integer; begin ea:=A/255; eb:=B /255; ec:=Ln(eb)/Ln(ea); for I:=1 to 255 do BarData[I]:=Round(Exp(Ln((I/255))*ec)*255); DrawBar; pbBarPaint(pbBar); Button1Click(Button1); end;
Doing this adjusts the brightness of the image.
Tips for displaying special effects in Delphi graphics
Overview
----At present, in many learning software and game CDs, you can often see various
Graphic display technology relies on graphic movement, interlacing, raindrop shape, blinds, building block stacking and other display methods to make the picture more lively and more attractive to the audience. This article will explore how to implement various graphic display techniques in Delphi.
Basic principles
----In Delphi, it is very simple to display an image. Just define a timage component in the form, set its picture attribute, and then select any valid .ico, .bmp, .emf or .wmf File, load, and the selected file will be displayed in the timage component. But this just displays the graphics directly in the form, and there is no skill at all. In order to make the graphic display have a unique effect, you can follow the following steps:
---- Define a TIMAGE component, and put the graphics to be displayed into the TIMAGE component, that is, load the graphic content from the disk into the memory as a graphical cache.
---- Create a new graph object, the size is the same as the figure in the TIMAGE component.
---- Use the CopyRect function of Canvas (copy the rectangular area of one canvas to the rectangular area of another canvas), use skills, dynamic shape, dynamic shape, dynamic shape
The content of the graph is made, and then the bitmap is displayed in the window.
---- Implementation method
The following introduces various graphics display skills:
1. Pushing effect
The graphs to be displayed are pulled into the screen from the top, down, left, and right directions. At the same time, the original old maps on the screen can be covered. This effect can be divided into four types. But the principles are similar. The above pull effect is an example.
Principles: First, put the first horizontal line of the temporary graphic, move to the last one to be displayed, and then move the first two horizontal lines of the temporary graphic to the last two in order to display the bitmap. The horizontal line, then move the first three and the first four until all the graphic data is moved. In the process of moving, you can see the displayed bitmap float from bottom to top to achieve the effect of pulling up.
Program algorithm:
Procedure TFORM1.Button1Click (Sender: TOBject); Var Newbmp: TBITMAP; I, BMPHEIGHT, BMPWIDTH: Integer; Begin Newbmp: = TBITMAP.Create; DTH: = Image1.Width; NewBMP.Height: = Image1.Height; BMPHEIGHT : = Image1.Height; BMPWIDTH: = Image1.width; for I: = 0 to bmpheight do begin newbmp.canvas.copyrect (RECT (0, BMPHEIGHT-I, BMPWIDTH, BMPHEIGHT), Image1.Canvas, RECT (0,0, BMPWIDTH, I)); anvas.draw (120,100 , newbmp); end; newbmp.free;
2. Vertical staggered effect
Principle: Demand the graphics to be displayed into two parts. The odd number scanning line is moved from top to bottom, and the part of the even scan line is moved from bottom to top, and the two are carried out at the same time. From the screen, we can see that the lighter graphics that appear from the upper and lower ends are moved to the center of the screen until it is completely clear.
Program algorithm:
Procedure tform1.button4clCK (Sender: TOBJECT); VAR NewBMP: TBITMAP; I, J, BMPHeight, BMPWIDTH: Integer; Begin Newbmp: = TBITMAP.CREATE; width: = Image1.width; Newbmp.Height: = Image1.Height ; BMPHEIGHT: = Image1.Height; BMPWIDTH: = Image1.width; i: = 0; While I <= BMPHEIGHT Do Begin J: = i; While J> 0 Do Begin Newbmp.canvas.copyRect (RECT (0, J-1, BMPWIDTH, J), Image1.canvas, Rect BMPHEIGHT-I+J-1, BMPWIDTH, BMPHEIGHT-I+J); newbmp.canvas.copyRect (Rect (0, BMPHEIGHT-J, BMPWIDTH, BMPHEIGHT-J+1), Image1.canvas, Rect (0, IJ, BMPWIDTH, I-J+1)); j: = j-2; form1.canvas.draw (120,100, newbmp); i: = i+2; end; newbmp.free;
3. Horizontal staggered effect
Principle: Like the principle of vertical interlacing effect, the graphics that are divided into two groups are moved from the left and right ends to the screen.
Program algorithm:
Procedure tForm1.Button5Click (Sender: TOBject); VAR NewBMP: TBITMAP; I, J, BMPHeight, BMPWIDTH: Integer; Begin Newbmp: = TBITMAP.CREATE; width: = Image1.width; Newbmp.Height: = Image1.Height ; BMPHEIGHT: = Image1.Height; BMPWIDTH: = Image1.width; i: = 0; While I <= bmpwidth do begin j: = i; while j> 0 do begin newbmp.canvas.copyrect (RECT (J-1,0, J, BMPHEIGHT), Image1.canvas, Rect (BMPWIDTH- I+J-1,0, BMPWIDTH-I+J, BMPHEIGHT); newbmp.canvas.copyRect (RECT (BMPWIDTH-J, 0, BMPWIDTH-J+1, BMPHeight), Image1.canvas, Rect (IJ, 0, I-J+1, BMPHeight)); j: = j-2; form1.canvas.draw (120,100, newbmp); i: = i+2; end; newbmp.free;
4. Rain drop effect
Principle: The last scan line of the temporary graphic is moved to the first article of the visual map to the last scan line in order, so that this scanning line will leave its trajectory on the screen. Then the second scan line of the countdown of the temporary graphics is moved to the first to the second to the penultimate scan line in order to move to the first to the penultimate graph. The rest of the scan lines are pushed according to this.
Program algorithm:
Procedure tform1.button3clCK (Sender: TOBJECT); VAR NewBMP: TBITMAP; I, J, BMPHeight, BMPWIDTH: Integer; Begin Newbmp: = TBITMAP.CREATE; width: = Image1.width; Newbmp.Height: = Image1.Height ; BMPHEIGHT: = Image1.Height; BMPWIDTH: = Image1.width; For I: = BMPHEIGHT DOWNTO 1 Do for J: = 1 to I do Begin Newbmp.canvas.copyRCT (RECT (0, J-1, BMPWIDTH, J), Image1.Canvas, RECT (0, I-1, BMPWIDTH, BMPWIDTH, i); form1.canvas.draw (120,100, newbmp); end; newbmp.free;
5. The effect of the louver window
Principles: The data that will be placed in the temporary graphic is divided into several groups, and then moved from the first group to the last group in turn. The first time each group moves the first scan line to the corresponding position of the visible diagram, the second time Move the second scan line, then move the third and fourth scan lines.
Program algorithm:
Procedure tform1.Button6Click (Sender: TOBJECT); VAR NewBMP: TBITMAP; I, J, BMPHeight, BMPWIDTH: Integer; XCount: Integer; Begin : = tBitmap.create; newbmp.width: = Image1.width; newbmp. height: = Image1.Height; BMPHEIGHT: = Image1.Height; BMPWIDTH: = Image1.width; xgroup: = 16; xcount: = BMPHEIGHT DIV XGROUP; for I: = 0 to xcount do for j: = 0 to xgroup do begin opyrect (RECT (0, XCount*J+ I-1, bmpwidth, xcount*j+i), image1.canvas, RECT (0, XCount*J+I-1, BMPWIDTH, XCount*J+I); Form1.Canvas.draw (120,100, newbmp); End; newbmp.free; End;
6. Building block effect
Principle: It is a change in the effect of raindrops. The difference is that each time the building block effect is moved, it is a graphic, not just a scan line.
Program algorithm:
Procedure tForm1.Button7Click (Sender: TOBject); VAR NewBMP: TBITMAP; I, J, BMPHeight, BMPWIDTH: Integer; Begin Newbmp: = TBITMAP.CREATE; width: = Image1.width; Newbmp.Height: = Image1.Height ; BMPHEIGHT: = Image1.Height; BMPWIDTH: = Image1.width; I: = bmpheight; While I> 0 Do Begin for J: = 10 to I do Begin Newbmp.canvas.copyRct (RECT (0, J-10, BMPWIDTH, J), Image1.Canvas, RECT (0, I-10 , bmpwidth, i)); form1.canvas.draw (120,100, newbmp); End; i: = i-10; end; newbmp.free; end;
Conclusion
The above graphics display effects have been passed on the machine. It works great.
Use Delphi to achieve image magnifying glass
Add two TIMAGE components to the window. One of the TIMAGE components is set to Image1, which acts as the carrier displayed by the original picture. The name property of another TIMAGE component is set to Image2, which can display the magnified image.
The core of this example is the Stretchblt function. The use of the StretchBlt function to achieve local image magnification. The response code is as follows:
Procedure TFORM1.Image1Mousemove (Sender: Tobject; Shift: TashiftState; X, Y: Integer); , Image2.Height, Image1.Canvas.Handle, X-20 , Y-20, 40,40, srccopy); Image2.refresh; Screen.cursors [1]: = LoadcursorFromFile ('Magnify.cur'); Self.cursor: = 1; end;
The program first calls the StretchBlt function, uses the current position of the mouse as the center point, selects local images on the IMAGE1 component with the side length of 40, and amplifies this local image to the Image2 component. Then call the Refresh method of the IMAGE2 component to refresh the display of the Image2 component. Finally, set the mouse pointer to the new shape.
The program code is as follows:
Unit Unit1; InterfaceUSESWINDOWS, MESSAGES, SYSUTILS, Variants, Classes, Graphics, Controls, Dialogs, ExtCTRLS; Type TFORM1 = Class (TFORM) Image1: TIMAGE; Image2: TIMAGE; Procedure Image1Mousemove (Sender: Tobject; Shift: TashiftState ; X, y: integer); procedure Formmousemove (Sender: TOBJECT; Shift: TashiftState; X, Y: Integer); Private {Private Declarations} Public {Public Declarations} End; VAR FORM1: TFOR m1; Implementation {$ R *.dfm} Procedure TFORM1.Image1Mousemove (Sender: TOBject ; Shift: tshiftstate; x, y: integer); Beginstretchblt (Image2.canvas.Handle, 0,0, Image2.width, Image2.Height, Image1.Canvas.Handle, X-20, 40,40, srccopy); Image2.Refresh; Reen.cursors [1 ]: = LoadcursorFromFile ('Magnify.cur'); Self.cursor: = 1; End; Procedure TFORM1.Formmousemove (Sender: TOBJECT; Shift: TSHIFTSTATE; x, Y: Integer); ; Self.cursor: = 1; end; end .
Save the file and press the F9 key to run the program and run the program.
Apricating images is an excellent function of looking at the picture software. This example provides a very simple and easy way to do not only the number of code, but also high execution efficiency.
I hope this article will be helpful to everyone's Delphi programming.