Примеры в этой статье суммируют основные методы обработки изображений в Delphi. Поделитесь этим со всеми для справки. Конкретный анализ заключается в следующем:
//Процедура тиснения Emboss(SrcBmp,DestBmp:TBitmap;AzimuthChange:integer);overload;var i, j, Gray, Azimuthvalue, R, G, B: целое число; SrcRGB, SrcRGB1, SrcRGB2, DestRGB: pRGBTriple;begin for i: = от 0 до SrcBmp.Height - 1 начать SrcRGB := SrcBmp.ScanLine[i]; DestRGB := DestBmp.ScanLine[i]; если (AzimuthChange >= -180) и (AzimuthChange < -135), то начать, если i > 0, то SrcRGB1 := SrcBmp.ScanLine[i-1] иначе SrcRGB1 := SrcRGB Inc(SrcRGB1); := SrcRGB; Inc(SrcRGB2); end else if (AzimuthChange >= -135) and (AzimuthChange < -90) then start if i > 0 then SrcRGB1 := SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1 Inc(SrcRGB2 end else if); (AzimuthChange >= -90) и (AzimuthChange < -45) then start, если i > 0 then SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; end else if (AzimuthChange >= -45) и (AzimuthChange < 0), затем начинается SrcRGB1 := SrcRGB; если i > 0, то SrcRGB2 := SrcBmp.ScanLine[i-1] else SrcRGB2 := SrcRGB; end else if (AzimuthChange >= 0) и (AzimuthChange < 45), затем начать SrcRGB2 := SrcRGB; SrcBmp.Height - 1) затем SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB; end else if (AzimuthChange >= 45) и (AzimuthChange < 90), затем начать if (i < SrcBmp.Height - 1), затем SrcRGB1 := SrcBmp.ScanLine[i +1] иначе SrcRGB1 := SrcRGB2 := SrcRGB1; end else if (AzimuthChange >= 90) и (AzimuthChange < 135) then start if (i < SrcBmp.Height - 1) then SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB2 :=; SrcRGB1 Inc(SrcRGB1); конец еще, если; (AzimuthChange >= 135) и (AzimuthChange <= 180) then start if (i < SrcBmp.Height - 1) then SrcRGB2 := SrcBmp.ScanLine[i+1] else SrcRGB2 := SrcRGB; Inc(SrcRGB2); = SrcRGB; Inc(SrcRGB1); конец для j:= От 0 до SrcBmp.Width - 1 начать, если (AzimuthChange >= -180) и (AzimuthChange < -135), затем начать 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- Значение азимута)дел 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; end else if (AzimuthChange >= -135) и (AzimuthChange < -90), затем начинается значение азимута := AzimuthChange + 135; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Значение азимута div 45)-((SrcRGB2.rgbtRed)*(45-Значение азимута) div 45)+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Значение азимута div 45)-((SrcRGB2.rgbtGreen)*(45-Значение азимута) div 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue) *Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; end else if (AzimuthChange >= -90) и (AzimuthChange < -45) then start если j=1 then Inc(SrcRGB1,- 1); Значение Азимута: = Изменение Азимута + 90; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Значение азимута div 45)-((SrcRGB2.rgbtRed)*(45-Значение азимута) 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- Значение азимута) div 45)+78; если (AzimuthChange >= -45) и (AzimuthChange < 0) то начать, если j=1, то начать Inc(SrcRGB1,-1); Inc(SrcRGB2,-1); 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- Значение азимута)дел 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; end else if (AzimuthChange >= 0) и (AzimuthChange < 45) затем начни, если j=1, то начни Inc(SrcRGB1,-1); Inc(SrcRGB2,-1); end; Azimuthvalue := AzimuthChange; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue div 45)-((SrcRGB2.rgbtRed)*( 45-Значение азимута)дел 45)+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Значение азимута div 45)-((SrcRGB2.rgbtGreen)*(45-Значение азимута) div 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue) *Azimuthvalue div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; end else if (AzimuthChange >= 45) и (AzimuthChange < 90), затем начать, если j=1, затем Inc(SrcRGB2,-1) ; Значение Азимута := Изменение Азимута - 45; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Значение азимута div 45)-((SrcRGB2.rgbtRed)*(45-Значение азимута) 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- Значение азимута) div 45)+78; if (AzimuthChange >= 90) и (AzimuthChange < 135) then start Azimuthvalue := AzimuthChange - 90; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue div 45)-((SrcRGB2.rgbtRed)*(45 -Azimuthvalue) div 45)+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*Значение азимута div 45)-((SrcRGB2.rgbtGreen)*(45-Значение азимута) div 45)+78; (SrcRGB1.rgbtBlue)*Значение азимута div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; end else if (AzimuthChange >= 135) и (AzimuthChange <= 180) then start Azimuthvalue := AzimuthChange - 135; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Значение азимута div 45)-((SrcRGB2.rgbtRed)*(45-Значение азимута) 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- Значение азимута) div 45)+78; R:=Мин(R,255); R:=Макс(R,0); G:=Мин(G,255); B:=Max(B,0); Серый := (R шр 2) + (R шр 4) + (G шр 1) + (G шр 4) + (B шр 3); DestRGB.rgbtRed:=Gray; DestRGB.rgbtGreen:=Gray; DestRGB.rgbtBlue:=Gray; если (j=-180) и (AzimuthChange<-135)) или ((AzimuthChange>=90) и (AzimuthChange<=180). ))) затем начать Inc(SrcRGB1 end); (j=135) и (AzimuthChange<180)) или ((AzimuthChange>=-180) и (AzimuthChange<=-90))) then Begin Inc(SrcRGB2); end; Inc(SrcRGB Inc(DestRGB); конец;конец;процедура 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) ,Изменение веса); Bmp.Assign(DestBmp);end;//Обратная процедура Negative(Bmp:TBitmap);var i, j: Integer; PRGB: pRGBTriple;begin Bmp.PixelFormat:=pf24Bit для i := 0 до Bmp.Height - 1 do Begin PRGB := Bmp.ScanLine[i] для j := от 0 до Bmp.Width - 1 do; start PRGB^.rgbtRed :=not PRGB^.rgbtRed ; = not PRGB^.rgbtGreen; PRGB^.rgbtBlue :=not PRGB^.rgbtBlue; Inc(PRGB); Процедура экспозиции Exposure(Bmp:TBitmap);var i, j: целое число PRGB: pRGBTriple;begin; Bmp.PixelFormat:=pf24Bit; for i := 0 до Bmp.Height - 1 начать PRGB := Bmp.ScanLine[i]; for j := 0 до Bmp.Width - 1 начать, если PRGB^.rgbtRed<128 тогда PRGB^.rgbtRed :=not PRGB^.rgbtRed, если PRGB^.rgbtGreen<128; then PRGB^.rgbtGreen :=not PRGB^.rgbtGreen; если PRGB^.rgbtBlue<128, то PRGB^.rgbtBlue :=not PRGB^.rgbtBlue; Inc(PRGB); end; end;//размытие процедуры Blur( SrcBmp:TBitmap);вар я, j:Integer SrcRGB:pRGBTriple; SrcNextRGB: pRGBTriple; SrcPreRGB: pRGBTriple; процедура IncRGB; Inc (SrcNextRGB); конец; процедура Inc (SrcNextRGB, -1); SrcBmp.PixelFormat:=pf24Bit; for i := 0 до SrcBmp.Height - 1 начинать, если i > 0, тогда SrcPreRGB:=SrcBmp.ScanLine[i-1] else SrcPreRGB := SrcBmp.ScanLine[i] :=; SrcBmp.ScanLine[i]; если я < SrcBmp.Height - 1; then SrcNextRGB:=SrcBmp.ScanLine[i+1] else SrcNextRGB:=SrcBmp.ScanLine[i]; for j := от 0 до SrcBmp.Width - 1 начинать, если j > 0, то DecRGB Value:=SrcPreRGB.rgbtRed+ SrcRGB; .rgbtRed+SrcNextRGB.rgbtRed, если j >; 0 затем agngb; дел. 9; DecRGB; SrcRGB.rgbtRed:=значение; если j > 0, то DecRGB; Значение: = SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen; если j > 0, то IncRGB; Значение:=Value+SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen; если j < SrcBmp.Width - 1, то IncRGB Value:=(Value+SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen) div 9; ; SrcRGB.rgbtGreen:=значение; если j>0, то DecRGB; Значение:=SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue; если j>0, то IncRGB; Значение:=Value+SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB; .rgbtBlue; если j < SrcBmp.Width - 1, затем IncRGB; Значение:=(Value+SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue) div 9; SrcRGB.rgbtBlue:=value; End;end;//процедура повышения резкости; Sharpen(SrcBmp:TBitmap);var i, j: SrcRGB: pRGBTriple; SrcPreRGB: pRGBTriple; Значение: целое число; начать SrcBmp.PixelFormat:=pf24Bit; для i := 0 до SrcBmp.Height - 1 do Begin SrcBmp.ScanLine[i]; SrcPreRGB:=SrcBmp.ScanLine[i-1] else SrcPreRGB:=SrcBmp.ScanLine[i]; for j := от 0 до SrcBmp.Width - 1 начать, если j = 1, то Dec(SrcPreRGB Value:=SrcRGB). rgbtRed+(SrcRGB.rgbtRed-SrcPreRGB.rgbtRed) div 2; Значение: = Макс (0, Значение); Значение: = Мин (255, Значение); SrcRGB.rgbtRed: = значение; Значение: = SrcRGB.rgbtGreen + (SrcRGB.rgbtGreen-SrcPreRGB.rgbtGreen) Значение: = Макс(0,Значение);=Мин(255,Значение); SrcRGB.rgbtGreen:=значение;=SrcRGB.rgbtBlue+(SrcRGB.rgbtBlue-SrcPreRGB.rgbtBlue) div 2; Value:=Max(0,Value); Value:=Min(255,Value); значение Inc(SrcRGB); Inc(SrcPreRGB); конец;конец; [Вращение и переворачивание изображения] Следующий код реализован с использованием ScanLine с перемещением указателя для 24-битного цвета! // Процедура поворота на 90 градусов Rotate90(const Bitmap:TBitmap);var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap; Width,Height:Integer;begin Bmp:=TBitmap.Create; Bitmap.Height; Bmp.Height := Bitmap.Width; pf24bit; Width:=Bitmap.Width-1; for j := 0 to Height do start rowIn := Bitmap.ScanLine[j]; for i := 0 to Width do Begin rowOut : = Bmp.ScanLine[i]; Inc(rowOut,Height - j); rowOut^:= rowIn^; end; Bitmap.Assign(Bmp);end;//Поворот на 180 градусов. Процедура Rotate180(const Bitmap:TBitmap);var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:Width,Height:Integer;begin Bmp:= TBitmap.Create Bmp.Width := Bitmap.Width := Bitmap.Height:= pf24bit; := от 0 до Width do Begin rowOut := Bmp.ScanLine[Height - j] Inc(rowOut,Width - i); rowOut^ := rowIn^; Inc(rowIn); end; end; Bitmap.Assign(Bmp);end;//Поворот на 270 градусов Rotate270(const Bitmap:TBitmap);var i,j:Integer; pRGBTriple Bmp:TBitmapWidth,Height:Integer;begin Bmp:=TBitmap.Create Bmp.Width; := Bitmap.Height; Bmp.Height := Bmp.PixelFormat := pf24bit; Height:=Bitmap.Height-1; для j := 0 до Height do start rowIn := Bitmap.ScanLine[j]; for i := от 0 до Width do Begin rowOut := Bmp.ScanLine[Width - i]; Inc(rowOut^ := rowIn^; end; Bitmap.Assign(Bmp);end;//Любая функция угла RotateBitmap(Bitmap: TBitmap;Angle:Integer;BackColor:TColor):TBitmap;var i,j,iOriginal,jOriginal,CosPoint,SinPoint: RowOriginal,RowRotated: pRGBTriple; SinTheta,CosTheta: Extended; AngleAdd: целое число;begin Result:=TBitmap.Create; Result.PixelFormat:= pf24bit; ; если Угол<0, то Angle:=360-Abs(Angle); если Angle=0, то Result.Assign(Bitmap), иначе, если Angle=90, начинаем Result.Assign(Bitmap);//Если он повернут на 90 градусов, вызовите это напрямую. Приведенный выше код заканчивается еще, если (Угол>90) и (Угол<180), затем начинается AngleAdd:=90; Angle:=Angle-AngleAdd; end else if Angle=180 then start Result.Assign(Bitmap); Rotate180(Result);//Если он повернут на 180 градусов, вызовите вышеуказанный процесс напрямую end else if (Angle>180) и ( Angle<270), затем начать AngleAdd:=180 Angle:=Angle-AngleAdd; end else, если Angle=270, затем начать; Result.Assign(Bitmap); Rotate270(Result);//Если он повёрнут на 270 градусов, напрямую вызовите описанный выше процесс end else if (Angle>270) and (Angle<360) then Begin AngleAdd:=270; Угол -AngleAdd; end else AngleAdd:=0; если (Угол>0) и (Угол<90), то начать SinCos((Угол) + AngleAdd) * Pi / 180, SinTheta, CosTheta); если (SinTheta * CosTheta) < 0, то начать 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)); ; CosTheta:=Abs(CosTheta); (AngleAdd=0) или (AngleAdd=180) thenbegin CosPoint:=Round(Bitmap.Height*CosTheta); 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-( я+1-SinPoint)*SinTheta)-1 iOriginal :=; Round((i+1)*CosTheta-(CosPoint-j-1)*SinTheta)-1 end; 90: начало iOriginal := Round((j+1)*SinTheta-(i+1-SinPoint)*CosTheta; )-1; jOriginal := Bitmap.Height-Round((i+1)*SinTheta-(CosPoint-j-1)*CosTheta); конец; 180: начало jOriginal := Bitmap.Height-Round((j+1)*CosTheta-(i+1-SinPoint)*SinTheta); iOriginal := Bitmap.Width-Round((i+1)*CosTheta-); (CosPoint-j-1)*SinTheta end; 270: начало iOriginal := Bitmap.Width-Round((j+1)*SinTheta-(i+1-SinPoint)*CosTheta := Round((i+1)*SinTheta-(CosPoint-j-1)*CosTheta)-1); ; конец; конец; если (iOriginal >= 0) и (iOriginal <= Bitmap.Width-1) и (jOriginal >= 0) и (jOriginal <= Bitmap.Height-1) then start RowOriginal := Bitmap.Scanline[jOriginal]; Inc(RowOriginal,iOriginal); RowRotated^ := RowOriginal^; Inc(RowRotated); end else Begin Inc(RowRotated); ; end; end; end;end;//Процедура горизонтального переворота FlipHorz(const Bitmap:TBitmap);var i,j:Integer;rowIn,rowOut:pRGBTriple;Bmp:TBitmap;Height:Integer;begin Bmp:=TBitmap.Create; PixelFormat: = pf24bit Ширина: = Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do start rowIn := Bitmap.ScanLine[j]; for i := 0 to Width do Begin rowOut := Bmp.ScanLine[j]; ,Width - i); rowOut^ := rowIn^; Inc(rowIn); end; Bitmap.Assign(Bmp);end;//процедура вертикального переворота FlipVert(const Bitmap:TBitmap);var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap;Height:Integer;begin Bmp:=TBitmap.Create; Bmp.Width:= Bitmap.Height; Высота: = Bitmap.Width; Bmp.PixelFormat: = pf24bit; Width:=Bitmap.Width-1; для j := 0 до Height do start rowIn := Bitmap.ScanLine[j]; for i := 0 до Width do Begin rowOut := Bmp; .ScanLine[Height - j]; Inc(rowOut,i); rowOut^:= rowIn^; Inc(rowIn); end; Bitmap.Assign(Bmp);end;[Регулировка яркости, контрастности и насыщенности] Следующий код реализован с использованием ScanLine с перемещением указателя! функция Min(a, b: целое число): целое число;начало, если a < b, то результат:= a else результат:= b;конец;функция Max(a, b: целое число): целое число;начало, если a > b, то результат: = результат else := b;end;//Процедура настройки яркости BrightnessChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);var i, j: целое число; SrcRGB, DestRGB: pRGBTriple; start for i := 0 до SrcBmp.Height - 1 do start SrcBmp.ScanLine[i]; 1 начать, если ValueChange > 0, затем начать DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + ValueChange); DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange); DestRGB.rgbtBlue := Min(255, SrcRGB.rgbtBlue + ValueChange); end else start DestRGB.rgbtRed : =Макс(0, SrcRGB.rgbtRed + ValueChange); DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + ValueChange); DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue + ValueChange); Inc(SrcRGB); ; конец;конец;//процедура настройки контрастности ContrastChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);var i, j: целое число; SrcRGB, DestRGB: pRGBTriple;begin for i := 0 до SrcBmp.Height - 1 do Begin SrcRGB := SrcBmp.ScanLine[i] ; DestRGB := DestBmp.ScanLine[i] для j; := от 0 до SrcBmp.Width - 1 начать, если ValueChange>=0, затем начать, если SrcRGB.rgbtRed >= 128, затем DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + ValueChange) else DestRGB.rgbtRed := Max(0 , SrcRGB.rgbtRed — Изменение значения); SrcRGB.rgbtGreen >= 128, затем DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange) else DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen - ValueChange); если SrcRGB.rgbtGreen >= 128, то DestRGB.rgbt Синий := Min(255, SrcRGB.rgbtBlue + ValueChange) else DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue - ValueChange); end else start, если SrcRGB.rgbtRed >= 128, то DestRGB.rgbtRed := Max(128, SrcRGB.rgbtRed + ValueChange) еще DestRGB.rgbtRed := Min(128, SrcRGB.rgbtRed - ValueChange); если SrcRGB.rgbtGreen >= 128, то DestRGB.rgbtGreen := Max(128, SrcRGB.rgbtGreen + ValueChange) else DestRGB.rgbtGreen := Min(128, SrcRGB) .rgbtGreen — ValueChange); если SrcRGB.rgbtBlue >= 128, то DestRGB.rgbtBlue := Max(128, SrcRGB.rgbtBlue + ValueChange) else DestRGB.rgbtBlue := Min(128, SrcRGB.rgbtBlue - ValueChange Inc(SrcRGB); Inc(DestRGB); конец; end;end;//Процедура настройки насыщенности SaturationChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);var Grays: array[0..767] of Integer; Alpha: array[0..255] of Word Gray , х, у: целое число SrcRGB, DestRGB: pRGBTriple я: Byte;beginValueChange:=ValueChange+255;for i := от 0 до 255 do Alpha[i] := (i * ValueChange) Shr 8;x := 0;for i := от 0 до 255 dobegin Grey := i - Alpha [i]; Грейс[х] := Серый; Inc(x); Грейс[x] := Грейс[x] := Грей; Inc(x);end; для y := 0 до SrcBmp.Height - 1 dobegin SrcBmp.ScanLine[Y]; DestRGB := DestBmp.ScanLine[Y] для x := 0 до SrcBmp.Width - 1; do Begin Gray := Grays[SrcRGB.rgbtRed + SrcRGB.rgbtGreen + SrcRGB.rgbtBlue]; если Gray + Alpha[SrcRGB.rgbtRed]>0, то DestRGB.rgbtRed := Min(255,Gray + Alpha[SrcRGB.rgbtRed]) else DestRGB.rgbtRed := 0; если Gray + Alpha[SrcRGB. rgbtGreen]>0, затем DestRGB.rgbtGreen := Min(255,Gray + Alpha[SrcRGB.rgbtGreen]) else DestRGB.rgbtGreen := 0; если Grey + Alpha[SrcRGB.rgbtBlue]>0, то DestRGB.rgbtBlue := Min(255,Gray + Alpha[SrcRGB.rgbtBlue] ) еще DestRGB.rgbtBlue := 0 Inc(SrcRGB); Inc(DestRGB); end;end; //процедура настройки RGBChange(SrcBmp,DestBmp:TBitmap;RedChange,GreenChange,BlueChange:integer);var SrcRGB, DestRGB: pRGBTriple;begin for i : = от 0 до SrcBmp.Height- 1, начинаем SrcRGB := SrcBmp.ScanLine[i]; DestRGB :=DestBmp.ScanLine[i]; для j := 0 до SrcBmp.Width - 1 начинать, если RedChange> 0, затем DestRGB.rgbtRed := Min(255, SrcBmp.rgbtRed + RedChange) иначе DestRGB.rgbtRed := Max(0, SrcRGB.rgbtRed + RedChange); если GreenChange> 0, то DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + GreenChange) else DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + GreenChange), если BlueChange> 0, то DestRGB); .rgbtBlue := Мин(255, SrcRGB.rgbtBlue + BlueChange) else DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue + BlueChange); Inc(SrcRGB); Inc(DestRGB); end; end;[Настройка цвета]//RGB<=>BGRprocedure RGB2BGR(const Bitmap:TBitmap);var X: Целое число Y: Целое число; pRGBTriple; Color: Byte;begin для Y := 0 до (Bitmap.Height - 1) do Begin для X := 0 до (Bitmap.Width - 1) do Begin Color := PRGB^.rgbtRed; PRGB^.rgbtRed : = PRGB^.rgbtBlue; PRGB^.rgbtBlue := Цвет Inc(PRGB); end;end;//Grayscale (взвешенная) процедура Grayscale(const Bitmap:TBitmap);var X: Integer; PRGB: pRGBTriple; Gray: Byte;begin for Y := 0 to (Bitmap.Height - 1) do Begin PRGB := Bitmap.ScanLine[Y] для X := от 0 до (Bitmap.Width - 1) do Begin Gray :=; (77 * Красный + 151 * Зеленый + 28 * Синий) shr 8; PRGB^.rgbtRed:=Серый; PRGB^.rgbtGreen:=Серый; PRGB^.rgbtBlue:=Gray; Inc(PRGB); ;
Теория:
Ключевые слова:
Область рисования - то есть область, где в окне отображается изображение, которая также может быть полноэкранной (эффект рисования лучше в полноэкранном режиме, чем в общем окне)
Центральная точка — то есть координаты центральной точки, которая будет отображаться в области рисования на исходном изображении (отказ от ответственности: это понятие особенно важно)
Давайте сначала поговорим об увеличении изображения. Наш общий подход заключается в непосредственном увеличении изображения. Однако метод, представленный в этой статье, увеличивает только ту часть, которую мы видим. Есть две ситуации увеличения области. после увеличения больше области рисования. В такой ситуации и говорить нечего. Конечно, все отображается. Изображение; во-вторых, увеличенное изображение больше области рисования. Это ключевая тема, которую мы собираемся обсудить сегодня. В этом случае мы должны сначала определить размер увеличенного изображения, а затем рассчитать размер. исходное изображение на основе положения и размера «центральной точки» и, наконец, увеличьте захваченное изображение до области рисования.
Давайте поговорим о перемещении изображения. Когда отображаемое изображение превышает область рисования, нам нужно перемещать изображение, чтобы увидеть все изображение. Принцип таков: когда мышь щелкает в области рисования, она начинает перемещаться, сначала записывает положение щелчка мыши, затем обнаруживает движение мыши и вычисляет «центральную точку» на основе мыши и последнего смещения ( координаты экрана необходимо преобразовать в координаты исходного изображения), вычленить отображаемую часть из исходного изображения по принципу увеличения, описанному выше, и увеличить и отобразить ее в области рисования.
Реализация алгоритма:
1. Увеличение изображения
Определение переменной:
PZoom: степень увеличения (целое число: 100%, если используется 100, 100 можно изменить на 10 000 или больше, если необходимо, но числа с плавающей запятой не рекомендуются).
а, б: центральная точка
w, h: ширина и высота исходного изображения, которое нужно захватить.
x, y: позиция, которую нужно перехватить (верхний левый угол)
sw,sh: ширина и высота исходного изображения.
p1, p2: коэффициент увеличения
оу, ах: размер увеличенного изображения
pw,ph: размер области рисования
vx,vy: позиция, отображаемая в области рисования (верхний левый угол)
vw, vh: размер, отображаемый в области рисования.
ptx, pty: временные переменные
Известные переменные: PZoom, (a, b), (sw, sh), (p1, p2), (aw, ah), (pw, ph)
Переменные, подлежащие расчету: (x,y),(w,h),(vx,vy),(vw,vh)
Начинаем считать:
aw=Round(PZoom*sw/100);ah=Round(PZoom*sh/100);p1=aw/pwp2=ah/ph// Примечание. Round используется для округления, например Int(), Fix в других языки () и т. д., если p1>1, то w=Round(sw/p1) else w=swif p2>1, то h=Round(sh/p2) else h=sh// Примечание: shr — это оператор сдвига вправо, вы можете использовать «>>1», «div 2», «/2» или «Round(w/2)» вместо x=aw shr 1y=bh shr 1 // Примечание: div — это оператор целочисленного деления ptx=(w*PZoom) div 100pty=(h*PZoom) div 100// Следующее вычисляет размер и положение изображения, отображаемого в области рисования.
переменная
Pencent:double; // Коэффициент масштабирования wx:double; // Широкий коэффициент масштабирования hx:double // Высокий коэффициент масштабирования // Получить коэффициент масштабирования wx:=pw/ptx hx:=ph/pty if wx>hx then Pencent: =hx else Pencent:=wx; // Получаем окончательный размер изображения vw:=Round(Pencent*ptx); vh:=Round(Pencent*pty); // Вычисляем положение картинки vx:=(pw-vw) div 2; vy:=(ph-vh) div 2;// -------------------- - ---------------
Хорошо, две важные задачи выполнены (x, y), (w, h), (vx, vy), (vw, vh) и рассчитаны. Отображается следующая работа. Мы выбираем Windows API для выполнения операции.
переменная
sDC — это дескриптор устройства (DC) исходного изображения. tDC — это временный дескриптор устройства dDC и окончательный дескриптор устройства 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);
Наконец, нарисуйте отображаемую область:
Например:
BitBlt(GetDC(0),vx,vy,vx+vw,xy+vh,dDC,0,0,SRCCOPY);
2. Роуминг изображений
Сначала определите три глобальные переменные:
FBeginDragPoint :TPoint; // Записываем позицию, в которой мышь начинает перетаскивать FBeginDragSBPoint :TPoint; // Записываем позицию "центральной точки" FBeginDrag :boolean; // Началось ли "перетаскивание" a, b: целое число; // "Центральная точка"; " Расположение
При нажатии левой кнопки мыши запишите положение мыши и положение «центральной точки» и установите для FBeginDrag значение true.
Когда появится правая кнопка мыши, установите для FBeginDrag значение false.
Когда мышь перемещается, оценивается FBeginDrag. Если значение false, обработка не выполняется. Если значение true, будет выполнена следующая обработка.
Предположим, что X и Y — текущая позиция мыши.
a=FBeginDragPoint.X-((X-FBeginDragPoint.X)*100) div PZoomb=FBeginDragPoint.Y-((Y-FBeginDragPoint.Y)*100) div PZoom
Наконец, используйте изображение, представленное выше, чтобы увеличить и отобразить изображение.
Советы:
1. Если изображение большое, при использовании растрового объекта delphi возникнет ошибка переполнения памяти. В этом случае вы можете выполнить следующие настройки:
bitImage:=TBitmap.Create; bitImage.PixelFormat:=pf24bit;
2. Если вы хотите, чтобы изображение автоматически адаптировалось к размеру окна, используйте следующий код:
var p1,p2 :double;begin p1:=pw/sw; p2:=ph/sw; если p1>p2, то PZoom:=Round(p2*100) else PZoom:=Round(p1*100); 0, затем PZoom:=100;end;
Обработка яркости цвета пикселей изображения Delphi в оттенках серого
В обработке изображений важна скорость. Поэтому нам придется повторно обработать TBitmap, чтобы получить TVczhBitmap. Это просто потому, что GetPixels и SetPixels работают слишком медленно, просто используйте другой метод.
модуль untBitmapProc; интерфейс использует Graphics, SysUtils; тип TVczhBitmap = class (TBitmap) частные данные: PByteArray; процедура SetFormat; функция GetBytePointer (X, Y: Integer): PBytes (X, Y: Integer; Value); :Byte); функция GetBytes(X,Y:Integer):Byte защищенный опубликованный конструктор Create; публичное свойство Bytes[X,Y:Integer]:Byte read GetBytes; процедура LoadFromFile(FileName:String); процедура ToGray; конец; процедура реализации TVczhBitmap.SetFormat; начало HandleType:=bmDIB; PixelFormat:=pf24bit функция; TVczhBitmap.GetBytePointer(X,Y:Integer):PByte start if Line<>Y then; начало строки:=Y; данные:=ScanLine[Y]; конец; Longint(результат):=Longint(Данные)+X; конец; процедура TVczhBitmap.SetBytes(X,Y:Integer;Value:Byte); X,Y)^:=Значение; функция TVczhBitmap.GetBytes(X,Y:Integer):Byte Begin; результат:=GetBytePointer(X,Y)^; конструктор TVczhBitmap.Create; начало наследования CreateFormat; Line:=-1; процедура TVczhBitmap.LoadFromFile(FileName:String); начало наследования LoadFromFile(FileName); ; Строка:=-1; конец процедуры TVczhBitmap.ToGray var X,Y,R:Integer; B:Byte; start для Y:=0 до Height-1 do для X:=0 до Width-1 do Begin R:=0; для B:=0 до 2 do R:=R+GetBytes(X*3+) B,Y); для B:=0 до 2 do SetBytes(X*3+B,Y,R div 3 end;
После этого нам нужно создать несколько форм. Первая используется для отображения изображений, а вторая — для обработки изображений. Все остальные формы наследуются от второй формы и содержат собственно методы обработки.
Сначала посмотрим на второе окно:
модуль untProc; интерфейс использует Windows, сообщения, SysUtils, варианты, классы, графику, элементы управления, формы, диалоги, ExtCtrls, untBitmapProc, StdCtrls, ComCtrls; тип TfrmProcessor = class (TForm) pbBar: gpProc: TGroupBox Button1: TButton; процедура FormCreate(Отправитель: TObject); процедура FormDestroy (Отправитель: TObject); процедура FormShow (Отправитель: TObject); процедура pbBarPaint (Отправитель: TObject); ..255] байта; TVczhBitmap; процедура DrawBar; конец; вар frmProcessor: TfrmProcessor; реализация {$R *.dfm} использует untViewer; I:= от 1 до 255 do Bar.Canvas.LineTo(I,255-BarData[I]); TfrmProcessor.FormCreate(Отправитель: TObject); начать Bar:=TVczhBitmap.Create; Bar.Width:=256; Bar.Canvas.Brush.Color:=clWhite; =bsSolid; конец; процедура TfrmProcessor.FormDestroy(Отправитель: TObject); конец; процедура TfrmProcessor.FormShow (Отправитель: TObject); начало для I: = от 0 до 255 do BarData [I]: = I; процедура TfrmProcessor.pbBarPaint (Отправитель: TObject); .Canvas.Draw(0,0,Bar); конец процедуры TfrmProcessor.Button1Click(Sender: TObject); var X,Y:Integer; start для Y:=0 до Buffer.Height-1 do для X:=0 до Buffer.Width*3-1 do Played.Bytes[X,Y]:=BarData[Buffer.Bytes[ X,Y]]; frmViewer.FormPaint(frmViewer); конец;
После этого создайте окно, унаследованное от него, затем настройте BarData[] и нажмите «Применить», чтобы увидеть результат.
Теперь приступим к обработке изображения. См. пример программы для получения информации о конкретных эффектах.
1. Инверсия цвета.
Цвета изображений в оттенках серого варьируются от 0 до 255, поэтому, чтобы инвертировать цвет, мы можем вычесть значение цвета из 255, чтобы получить инвертированный цвет.
var I:Integer; start inherited; for I:=0 to 255 do BarData[I]:=255-I;//Вычитаем значение цвета из 255 DrawBar; pbBarPaint(pbBar);
2. Сузьте цветовой диапазон, чтобы усилить или ослабить яркость.
Цвет изначально от 0 до 255. Если вы отрегулируете его диапазон, например от 0 до 16, изображение станет значительно темнее. Мы можем установить начальное значение a и конечное значение b, а затем новое значение цвета New=a+(b-1)*Old/255. Это изменит яркость, не нарушая исходную цветовую последовательность. Код выглядит следующим образом
var I:Integer; начать для I:=0 до 255 do BarData[I]:=(255-sbMin.Position)+Round((sbMin.Position-sbMax.Position)/255*I); pbBarPaint(pbBar; ); Кнопка1Нажмите(Кнопка1);
Оба значения sbMin.Position и sbMaxPosition инвертированы. Поэтому используйте 255, чтобы вычесть
3. Увеличить цветовую гамму в определенном диапазоне.
Если само изображение имеет небольшой цветовой диапазон, вы можете использовать этот метод для увеличения контрастности изображения, что полезно для анализа изображения. Конкретные методы:
Выберите значение a в качестве начального значения, выберите значение b в качестве конечного значения, а затем выполните деформацию в соответствии со следующей формулой:
0 (Х<=а)
f(X)= | 255/(ба)*(Ха)
255(Х>=б)
var I:Integer; start 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; pbBarPaint (pbBar); Button1Click (Кнопка1);
4. Преобразование в черно-белые изображения
При использовании третьей функции вы обнаружите, что, когда b<=a, цвета на изображении белые, кроме черного. Преимущества этой операции невозможно отобразить напрямую. Это будет эффективно только тогда, когда речь идет о более продвинутой обработке изображений, такой как обнаружение краев. Этот пример можно преобразовать по формуле третьего метода, поэтому он не будет подробно разъясняться.
5. Экспоненциальная регулировка яркости.
Мы предполагаем, что область определения этого графика равна [0,1], а диапазон значений также равен [0,1]. Затем определите функцию f(x)=x^c, тогда изображение f(x) будет иметь сечение, как показано выше. Когда мы используем мышь для работы снова, мы можем взять на нее точку P (a, b), а затем заставить F (x) пройти через точку P, затем C = ln (b)/ln (a). С C мы можем работать на цвете:
New = (Old/255)^C*255 = Exp (LN (Old/255)*C)*255 VAR EA, EB, EC: Extended; /255; Bardata [i]: = Round (exp (ln ((i/255))*ec)*255);
Это регулирует яркость изображения.
Советы по отображению спецэффектов в Delphi Graphics
Обзор
---- В настоящее время, во многих учебных программных и игровых компакт-дисках, вы часто можете видеть различные
Технология графического дисплея зависит от движения, взаимодействия, формы дождя, жалюзи, укладки строительных блоков и других методов отображения графики, чтобы сделать картину более живой и привлекательной для аудитории. В этой статье будет рассмотрено, как реализовать различные методы графического отображения в Delphi.
Основные принципы
---- В Delphi очень просто отобразить изображение. и выбранный файл будет отображаться в компоненте TIMAGE. Но это просто отображает графику непосредственно в форме, и вообще нет навыков. Чтобы сделать графический дисплей, иметь уникальный эффект, вы можете выполнить следующие шаги:
---- Определите компонент TIMAGE и сначала загрузите графику, которая будет отображаться в компонент TIMAGE, то есть загрузите графический содержимое с диска в память как графический кэш.
---- Создайте новый объект растрового изображения с тем же размером, что и графика в компоненте Timage.
---- Используйте функцию Copyrect Canvas (скопируйте прямоугольную область одного холста в прямоугольную область другого холста), используйте методы и динамически форму
Преобразуйте содержимое файла в растровое изображение, а затем отобразите растровое изображение в форме.
---- Метод реализации
Ниже приведены различные методы графического отображения:
1. Эффект отключения
Потяните графику, чтобы отображаться в экране из вверх, вниз, влево и правых направлений, и в то же время прикрывайте исходную старую графику на экране. Потяните налево и потяните направо.
Принцип: сначала перемещайте первую горизонтальную линию в временной графике на последнюю в растровом изображении, а затем перемещайте первые две горизонтальные линии в временной графике в последние два растровых карт. Переместите первые три и четыре строки, пока все графические данные не будут перемещены. В процессе перемещения вы можете видеть, что отображаемый растровый карта плавает снизу вверх, достигая эффекта подтягивания.
Алгоритм программы:
Процедура tform1.button1click (отправитель: Tobject); : = Image1.height; I: = 0 до bmpheight do begin newbmp.canvas.copyrect (rect (0, bmpheight-i, bmpwidth, bmpheight), изображение1.canvas, rect (0,0, bmpwidth, i); , newbmp);
2. Вертикальный ошеломленный эффект
Принцип: Разделите графику, которая будет отображаться на две части. На экране вы можете видеть, что более легкая графика, появляющаяся на верхних и нижних концах, движется к центру экрана, пока они не станут совершенно ясными.
Алгоритм программы:
Процедура tform1.button4click (отправитель: Tobject); ; I: = 0; Bmpheight-i+J-1, Bmpwidth, bmpheight-i+j)); (0, Bmpheight-J, Bmpwidth, Bmpheight-J+1), Image1.canvas, rect (0, ij, bmpwidth, i-j+1); (120,100, newbmp);
3. Горизонтальный ошеломленный эффект
Принцип: тот же принцип, что и вертикальный эффект взаимодействия, за исключением того, что графика, разделенная на две группы, перемещается на экран с левого и правого конца соответственно.
Алгоритм программы:
Процедура tform1.button5click (отправитель: Tobject); ; I: = 0; I+J-1,0, BMPWidth-I+J, Bmpheight)); (Bmpwidth-J, 0, Bmpwidth-J+1, Bmpheight), Image1.canvas, rect (ij, 0, i-j+1, bmpheight); (120,100, newbmp);
4. Эффект дождя
Принцип: переместите последнюю линию сканирования временной графики в первую в последнюю линию сканирования видимой растровой карты в последовательности, позволяя этой линии сканирования оставить свою трассу на экране. Затем предпоследняя линия сканирования временной графики перемещается в первую, чтобы предпоследние линии сканирования видимой растровой карты в последовательности. И так далее для оставшихся линий сканирования.
Алгоритм программы:
Процедура tform1.button3click (отправитель: Tobject); ; для i: = bmpheight downto 1 do j: = 1 to i gogne neplbmp.canvas.copyrect (rect (0, j-1, bmpwidth, j), image1.canvas, rect (0, i-1, bmpwidth, i);
5. Эффект LOUVRES
Принцип: Разделите данные, размещенные во временной графике, на несколько групп, а затем перенесите их последовательно от первой группы в последнюю группу. Время переместить вторую линию сканирования, затем переместите третью и четвертую линии сканирования.
Алгоритм программы:
Процедура tform1.button6click (отправитель: Tobject); Высота: = Image1.Height; Bmpwidth: = Image1.width; -1, bmpwidth, xcount*j+i), image1.canvas, rect (0, xcount*j+i-1, bmpwidth, xcount*j+i));
6. Эффект строительного блока
Принцип: это вариант эффекта капли дождя.
Алгоритм программы:
Процедура tform1.button7click (отправитель: Tobject); ; I: = bmpheight; , bmpwidth, i); конец;
Заключение
Приведенные выше эффекты графического дисплея были переданы на машине. Это отлично работает.
Реализация увеличения изображения с использованием delphi
Добавьте два компонента Timage в форму. Другой компонент Timage имеет свой свойство имени, установленное на Image2, которое отображает увеличенное изображение.
Ядро этого примера - функция StretchBlt.
Процедура tform1.image1mouseMove (отправитель: tobject; shift: tshiftState; x, y: integer); begin stretchblt (image2.canvas.handle, 0,0, image2.width, image2 20,40,40, srccopy); Screen.cursors [1]: = LoadCursorFromFile ('Magnify.cur');
Программа сначала вызовет функцию strectblt, использует текущую позицию мыши в качестве центральной точки, выберите частичное изображение на компоненте Image1 с длиной бокового ранения 40 и увеличит частичное изображение в компонент Image2. Затем обновите отображение компонента Image2, вызывая метод обновления компонента Image2. Наконец -то установите указатель мыши на новую форму.
Код программы следующий:
Unit1; InterfaceUseswindows, Сообщения, Sysutils, Варианты, классы, графики, управления, формы, диалоги, extctrls, stdctrls; тип tform1 = class (tform) Image1: timage; ; FormuseMove (отправитель: tobject; shift: tshiftState;; shift: tshiftState; x, y: целое число); BeginStretchBlt (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; end; Процедура tform1.formmouseMove (отправитель: tobject; shift: tshiftState; x, y: Integer); Begin Screen.cursors [1]: = crdefault; .
Сохраните файл, а затем нажмите клавишу F9, чтобы запустить программу, и программа будет запущена.
Увеличительные изображения являются важной функцией отличного программного обеспечения для просмотра изображений.
Я надеюсь, что эта статья будет полезна каждому программисту на Delphi.