ตัวอย่างในบทความนี้สรุปวิธีการประมวลผลภาพพื้นฐานของ Delphi แบ่งปันกับทุกคนสำหรับการอ้างอิงของคุณ การวิเคราะห์เฉพาะมีดังนี้:
// ขั้นตอนการนูน นูน (SrcBmp, DestBmp: TBitmap; AzimuthChange: integer); โอเวอร์โหลด; var i, j, Grey, Azimuthvalue, R, G, B: จำนวนเต็ม; SrcRGB, SrcRGB1, SrcRGB2, DestRGB: pRGBTriple; เริ่มต้นสำหรับ 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); สิ้นสุด else if (AzimuthChange >= -135) และ (AzimuthChange < -90) จากนั้นให้เริ่มต้นหาก i > 0 แล้ว SrcRGB1 := SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; Inc(SrcRGB2); สิ้นสุดอย่างอื่น (AzimuthChange >= -90) และ (AzimuthChange < -45) จากนั้นให้เริ่มต้นหาก i > 0 แล้ว SrcRGB1 := SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB2 := SrcRGB1; -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 := SrcRGB; SrcRGB2 := SrcRGB1; สิ้นสุดอย่างอื่น if (AzimuthChange >= 90) และ (AzimuthChange < 135) จากนั้นให้เริ่มต้น if (i < SrcBmp.Height - 1) จากนั้น SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB; SrcRGB2 := SrcRGB1; Inc(SrcRGB1); (AzimuthChange >= 135) และ (AzimuthChange <= 180) จากนั้นเริ่มต้น if (i < SrcBmp.Height - 1) จากนั้น 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-ค่าอะซิมุท) 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 >= -135) และ (AzimuthChange < -90) จากนั้นเริ่มต้น Azimuthvalue := ราบเปลี่ยน + 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) * div ค่าอะซิมุท 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; จบอย่างอื่นถ้า (AzimuthChange >= -90) และ (AzimuthChange < -45) จากนั้นเริ่มต้นถ้า j=1 แล้ว Inc(SrcRGB1,- 1); ค่าอะซิมุท := เปลี่ยนอะซิมุท + 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; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*ค่าอะซิมุท div 45)-((SrcRGB2.rgbtBlue)*(45- ค่าอะซิมุท) div 45)+78; end else ถ้า (AzimuthChange >= -45) และ (AzimuthChange < 0) ให้เริ่ม ถ้า j=1 ให้เริ่ม Inc(SrcRGB2,-1); end; 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; สิ้นสุดอย่างอื่นถ้า (AzimuthChange >= 0) และ (AzimuthChange < 45) จากนั้นให้เริ่มต้น ถ้า j=1 ให้เริ่มต้น Inc(SrcRGB1,-1); Inc(SrcRGB2,-1); สิ้นสุด; 45-ค่าอะซิมุท)div 45)+78; G:=SrcRGB.rgbtGreen-((SrcRGB1.rgbtGreen)*ค่าอะซิมุท div 45)-((SrcRGB2.rgbtGreen)*(ค่าอะซิมุท 45) div 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue) * div ค่าอะซิมุท 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; จบอย่างอื่นถ้า (AzimuthChange >= 45) และ (AzimuthChange < 90) จากนั้นเริ่มต้นถ้า j=1 แล้ว Inc(SrcRGB2,-1) ; ค่าอะซิมุท := เปลี่ยนอะซิมุท - 45; 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; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*ค่าอะซิมุท div 45)-((SrcRGB2.rgbtBlue)*(45- ค่าอะซิมุท) div 45)+78; end else ถ้า (AzimuthChange >= 90) และ (AzimuthChange < 135) ให้เริ่ม Azimuthvalue := AzimuthChange - 90; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*Azimuthvalue 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)*ค่าแอซิมัท div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; จบอย่างอื่นถ้า (AzimuthChange >= 135) และ (AzimuthChange <= 180) จากนั้นเริ่ม Azimuthvalue := AzimuthChange - 135; 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; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*ค่าอะซิมุท div 45)-((SrcRGB2.rgbtBlue)*(45- ค่าอะซิมุท) div 45)+78; R:=ต่ำสุด(R,255); R:=สูงสุด(R,0); G:=ต่ำสุด(G,255); G:=สูงสุด(G,0); B:=สูงสุด(B,0); สีเทา := (R shr 2) + (R shr 4) + (G shr 1) + (G shr 4) + (B shr 3); DestRGB.rgbtRed:=Gray; DestRGB.rgbtGreen:=Gray; DestRGB.rgbtBlue:=Gray; ถ้า (j=-180) และ (AzimuthChange<-135)) หรือ ((AzimuthChange>=90) และ (AzimuthChange<=180 ))) จากนั้นให้เริ่มต้น Inc(SrcRGB1); (j=135) และ (AzimuthChange<180)) หรือ ((AzimuthChange>=-180) และ (AzimuthChange<=-90))) จากนั้นเริ่มต้น Inc(SrcRGB2); end; Inc(SrcRGB); สิ้นสุด; สิ้นสุด; สิ้นสุด; ขั้นตอน Emboss(Bmp:TBitmap;AzimuthChange:integer;ElevationChange:integer;WeightChange:integer);overload;var DestBmp:TBitmap;begin DestBmp:=TBitmap.Create; นูน(Bmp,DestBmp,AzimuthChange,ElevationChange ,เปลี่ยนน้ำหนัก); Bmp.Assign(DestBmp);end;//Inverse Procedure Negative(Bmp:TBitmap);var i, j: Integer; PRGB: pRGBTriple;begin Bmp.PixelFormat:=pf24Bit; สำหรับ i := 0 ถึง Bmp.Height - 1 เริ่ม PRGB := Bmp.ScanLine[i]; สำหรับ j := 0 ถึง Bmp.Width - 1 ทำ เริ่ม PRGB^.rgbtRed :=ไม่ใช่ PRGB^.rgbtBlue; Inc(PRGB); ขั้นตอนการเปิดรับแสง (Bmp:TBitmap);var i, j: integer; PRGB: pRGBTriple;begin Bmp.PixelFormat:=pf24Bit; for i := 0 ถึง Bmp.Height - 1 จะเริ่มต้น PRGB := Bmp.ScanLine[i]; สำหรับ j := 0 ถึง Bmp.Width - 1 จะเริ่มต้นหาก PRGB^.rgbtRed<128 จากนั้น PRGB^.rgbtRed :=ไม่ใช่ PRGB^.rgbtRed ; ถ้า PRGB^.rgbtGreen<128 จากนั้น PRGB^.rgbtGreen :=ไม่ใช่ PRGB^.rgbtGreen; ถ้า PRGB^.rgbtBlue<128 แล้ว PRGB^.rgbtBlue :=ไม่ใช่ PRGB^.rgbtBlue; Inc(PRGB); end; end;//blur ขั้นตอน SrcBmp:TBitmap);var i, j:จำนวนเต็ม; SrcNextRGB: SrcPreRGB; Inc (SrcNextRGB); SrcBmp.PixelFormat:=pf24Bit; for i := 0 ถึง SrcBmp.Height - 1 จะเริ่มต้นถ้า i > 0 แล้ว SrcPreRGB:=SrcBmp.ScanLine[i-1] อย่างอื่น SrcPreRGB := SrcBmp.ScanLine[i]; SrcBmp.ScanLine[i]; ถ้าฉัน < SrcBmp.Height - 1 จากนั้น SrcNextRGB:=SrcBmp.ScanLine[i+1] else SrcNextRGB:=SrcBmp.ScanLine[i]; สำหรับ j := 0 ถึง SrcBmp.Width - 1 จะเริ่มต้นถ้า j > 0 จากนั้น DecRGB; Value:=SrcPreRGB.rgbtRed+ SrcRGB .rgbtRed+SrcNextRGB.rgbtRed; ถ้า j > 0 จากนั้น IncRGB; ค่า:=(ค่า+SrcPreRGB.rgbtRed+SrcRGB.rgbtRed+SrcNextRGB.rgbtRed) div 9; DecRGB; SrcRGB.rgbtRed:=value; ถ้า j > 0 แล้ว DecRGB; ค่า:=Value+SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen; ถ้า j < SrcBmp.Width - 1 แล้ว IncRGB; ; SrcRGB.rgbtGreen:=value; ถ้า j>0 แล้ว DecRGB; Value:=SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB .rgbtBlue; ถ้าเจ < SrcBmp.Width - 1 จากนั้น IncRGB; Value:=(Value+SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue) div 9; DecRGB ทำให้คมชัดขึ้น(SrcBmp:TBitmap);var i, j: จำนวนเต็ม; SrcRGB: pRGBTriple; SrcPreRGB: pRGBTriple; ค่า: จำนวนเต็ม; เริ่มต้น SrcBmp.PixelFormat:=pf24Bit; สำหรับ i := 0 ถึง SrcBmp.Height - 1 จะเริ่มต้น SrcRGB := SrcBmp.ScanLine[i]; SrcPreRGB:=SrcBmp.ScanLine[i-1] else SrcPreRGB:=SrcBmp.ScanLine[i]; สำหรับ j := 0 ถึง SrcBmp.Width - 1 ให้เริ่มต้นถ้า j = 1 แล้ว Dec(SrcPreRGB); rgbtRed+(SrcRGB.rgbtRed-SrcPreRGB.rgbtRed) div 2; ค่า:=สูงสุด(0,ค่า); ค่า:=ต่ำสุด(255,ค่า); SrcRGB.rgbtRed:=value; ค่า:=SrcRGB.rgbtGreen+(SrcRGB.rgbtGreen-SrcPreRGB.rgbtGreen) div 2; สูงสุด(0,มูลค่า); มูลค่า:=ต่ำสุด(255,มูลค่า); SrcRGB.rgbtGreen:=value; Value:=SrcRGB.rgbtBlue+(SrcRGB.rgbtBlue-SrcPreRGB.rgbtBlue) div 2; Value:=สูงสุด(0,มูลค่า:=ต่ำสุด(255,ค่า) ค่า Inc (SrcRGB); Inc (SrcPreRGB); สิ้นสุด; [การหมุนภาพและการพลิก] รหัสต่อไปนี้ถูกนำมาใช้โดยใช้ ScanLine พร้อมการเคลื่อนไหวของตัวชี้สำหรับสี 24 บิต! //หมุน 90 องศา Rotate90(const Bitmap:TBitmap);var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap; Begin Bmp:=TBitmap.Create; Bitmap.Height; Bmp.Height := Bitmap.Width; pf24bit; width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do start rowIn := Bitmap.ScanLine[j]; = Bmp.ScanLine[i]; Inc(rowOut,Height - j); rowOut^ := rowIn^; Bitmap.Assign(Bmp);end;//หมุนขั้นตอน 180 องศา Rotate180(const Bitmap:TBitmap);var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap; TBitmap.Create; Bmp.Width := Bitmap.Width; Bitmap.Height; Bmp.PixelFormat := pf24bit; width:=Bitmap.Width-1; Height:=Bitmap.Height-1; := 0 ถึงความกว้างจะเริ่มต้น 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:TBitmap; ความกว้าง,ความสูง:จำนวนเต็ม;เริ่มต้น Bmp:=TBitmap.Create; := Bitmap.Height; Bmp.Height := Bitmap.Width; := Bitmap.ScanLine[j]; สำหรับ i := 0 ถึง width จะเริ่มต้น rowOut := Bmp.ScanLine[Width - i]; Inc(rowOut,j); rowOut^ := rowIn^; end; Bitmap.Assign(Bmp);end;//ฟังก์ชันมุมใดๆ TBitmap;มุม:จำนวนเต็ม;สีด้านหลัง:TColor):TBitmap;var i,j,iOriginal,jOriginal,CosPoint,SinPoint: จำนวนเต็ม; RowOriginal,RowRotated: pRGBTriple; SinTheta,CosTheta: Extended; AngleAdd: integer;begin Result:=TBitmap.Create; Result.PixelFormat; Result.Canvas.Brush.Color:=BackColor; ; ถ้ามุม<0 แล้ว Angle:=360-Abs(Angle); ถ้า Angle=0 แล้ว Result.Assign(Bitmap) อย่างอื่น ถ้า Angle=90 ให้เริ่ม Result.Assign(Bitmap); Rotate90(Result);//ถ้าหมุน 90 องศา ให้เรียก โดยตรง โค้ดด้านบนจะสิ้นสุดอย่างอื่นถ้า (Angle>90) และ (Angle<180) จากนั้นให้เริ่ม AngleAdd:=90; Angle:=Angle-AngleAdd; end else if Angle=180 ให้เริ่ม Result.Assign(Bitmap); Rotate180(Result);//ถ้าหมุน 180 องศา ให้เรียกกระบวนการข้างต้นโดยตรง end else if (Angle>180) และ ( Angle<270) จากนั้นเริ่ม AngleAdd:=180; Angle:=Angle-AngleAdd; สิ้นสุดอย่างอื่นถ้า Angle=270 ให้เริ่มต้น Result.Assign(Bitmap); Rotate270(Result);//ถ้าหมุน 270 องศา ให้เรียกกระบวนการข้างต้นโดยตรง ถ้า (Angle>270) และ (Angle<360) ให้เริ่ม AngleAdd:=270; Angle -AngleAdd; จบอย่างอื่น AngleAdd:=0; if (Angle>0) และ (Angle<90) จากนั้นให้เริ่ม SinCos((Angle + AngleAdd) * Pi / 180, SinTheta, CosTheta); if (SinTheta * CosTheta) < 0 จากนั้นให้เริ่ม Result.Width := Round(Abs(Bitmap.Width * CosTheta - Bitmap.Height * SinTheta)); = รอบ(Abs(Bitmap.Width * SinTheta - Bitmap.Height * CosTheta)); end else เริ่ม Result.Width := Round(Abs(Bitmap.Width * CosTheta + Bitmap.Height * SinTheta)); Result.Height := Round(Abs(Bitmap.Width * SinTheta + Bitmap.Height * CosTheta)); ; CosTheta:=Abs(คอสเธต้า); (AngleAdd=0) หรือ (AngleAdd=180) จากนั้นเริ่ม CosPoint:=Round(Bitmap.Height*CosTheta); SinPoint:=Round(Bitmap.Height*SinTheta); ); CosPoint:=Round(Bitmap.Width*SinTheta); สำหรับ j := 0 ถึง Result.Height-1 จะเริ่มต้น RowRotated := Result.Scanline[j]; สำหรับ i := 0 ถึง Result.Width-1 จะเริ่มต้น Case AngleAdd จาก 0: เริ่มต้น jOriginal := Round((j+1)*CosTheta-( i+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.Width-Round((j+1)*CosTheta-(i+1-SinPoint)*SinTheta); (CosPoint-j-1)*SinTheta); 270: เริ่ม iOriginal := Bitmap.Width-Round((j+1)*SinTheta-(i+1-SinPoint)*CosTheta); jOriginal := รอบ((i+1)*SinTheta-(CosPoint-j-1)*CosTheta)-1 ; สิ้นสุด; สิ้นสุด; ถ้า (iOriginal >= 0) และ (iOriginal <= Bitmap.Width-1) และ (jOriginal >= 0) และ (jOriginal <= Bitmap.Height-1) จากนั้นเริ่ม RowOriginal := Bitmap.Scanline[jOriginal]; Inc(RowOriginal,iOriginal); RowRotated^ := RowRotated); ; end; end; end;end;//ขั้นตอนการพลิกแนวนอน FlipHorz(const Bitmap:TBitmap);var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap; ความกว้าง,ความสูง:จำนวนเต็ม;เริ่มต้น Bmp:=TBitmap.Create; รูปแบบพิกเซล := pf24bit; width:=Bitmap.Width-1; ความสูง:=Bitmap.Height-1; สำหรับ j := 0 ถึงความสูง จะเริ่มต้นแถวใน := Bitmap.ScanLine[j]; สำหรับ i := 0 ถึง ความกว้าง จะเริ่มต้น rowOut := Bmp.ScanLine[j]; ,ความกว้าง - i); rowOut^ := rowIn^; end; end; Bitmap.Assign(Bmp);end;//พลิกแนวตั้ง FlipVert(const บิตแมป:TBitmap);var i,j:Integer; rowIn,rowOut:pRGBTriple; Bmp:TBitmap; ความสูง := Bitmap.Width; Bmp.PixelFormat := pf24bit; ความกว้าง:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do beginning rowIn := Bitmap.ScanLine[j]; .ScanLine[ความสูง - j]; Inc(rowOut,i); rowOut^ := rowIn^; Inc(rowIn); Bitmap.Assign(Bmp);end;[การปรับความสว่าง คอนทราสต์ และความอิ่มตัว] รหัสต่อไปนี้ถูกนำมาใช้โดยใช้ ScanLine พร้อมการเคลื่อนไหวของตัวชี้! function Min(a, b: integer): integer;begin if a < b แล้ว result := a else result := b;end;function Max(a, b: integer): integer;begin if a > b แล้ว result : = ผลลัพธ์อื่น := b;end;//ขั้นตอนการปรับความสว่าง BrightnessChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);var i, j: integer; SrcRGB, DestRGB: pRGBTriple; เริ่มต้นสำหรับ i := 0 ถึง SrcBmp.Height - 1 จะเริ่มต้น SrcRGB := SrcBmp.ScanLine[i]; 1 จะเริ่มต้นถ้า ValueChange > 0 จากนั้นเริ่ม DestRGB.rgbtRed := ขั้นต่ำ (255, SrcRGB.rgbtRed + ValueChange); DestRGB.rgbtGreen := Min (255, SrcRGB.rgbtGreen + ValueChange) =สูงสุด(0, SrcRGB.rgbtRed + ValueChange; DestRGB.rgbtGreen := สูงสุด (0, SrcRGB.rgbtGreen + ValueChange) ; end; end;end;//ขั้นตอนการปรับความคมชัด ContrastChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);var i, j: integer; SrcRGB, DestRGB: pRGBTriple;เริ่มต้นสำหรับ i := 0 ถึง SrcBmp.Height - 1 จะเริ่มต้น SrcRGB := SrcBmp.ScanLine[i] ; DestRGB := DestBmp.ScanLine[i]; := 0 ถึง SrcBmp.Width - 1 จะเริ่มต้นหาก ValueChange>=0 จากนั้นเริ่มต้นหาก SrcRGB.rgbtRed >= 128 จากนั้น DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + ValueChange) มิฉะนั้น DestRGB.rgbtRed := Max(0 , SrcRGB.rgbtRed - การเปลี่ยนแปลงค่า); SrcRGB.rgbtGreen >= 128 จากนั้น DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange) มิฉะนั้น DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen - ValueChange) ถ้า SrcRGB.rgbtBlue >= 128 แล้ว DestRGB.rgbtBlue := Min(255, SrcRGB.rgbtBlue + ValueChange) else DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue - ValueChange) มิฉะนั้นจะเริ่มต้นถ้า SrcRGB.rgbtRed >= 128 แล้ว DestRGB.rgbtRed := Max(128, SrcRGB.rgbtRed) + ค่าเปลี่ยน) อื่น ๆ DestRGB.rgbtRed := Min(128, SrcRGB.rgbtRed - ValueChange) ถ้า SrcRGB.rgbtGreen >= 128 แล้ว DestRGB.rgbtGreen := Max (128, SrcRGB.rgbtGreen + ValueChange) อย่างอื่น DestRGB.rgbtGreen := Min (128, SrcRGB .rgbtGreen - ValueChange); ถ้า SrcRGB.rgbtBlue >= 128 แล้ว DestRGB.rgbtBlue := Max(128, SrcRGB.rgbtBlue + ValueChange) อย่างอื่น DestRGB.rgbtBlue := Min(128, SrcRGB.rgbtBlue - ValueChange) สิ้นสุด; Inc(DestRGB); สิ้นสุด; end;end;//ขั้นตอนการปรับความอิ่มตัว SaturationChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);var Grays: array[0..767] of Integer; Alpha: array[0..255] of Word; x, y: จำนวนเต็ม; 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]; Greys[x] := Grey; Inc(x); Greys[x] := Grey; Inc(x); Inc(x);end; สำหรับ y := 0 ถึง SrcBmp.Height - 1 dobegin SrcRGB := SrcBmp.ScanLine[Y]; จะเริ่มต้นสีเทา := สีเทา [SrcRGB.rgbtRed + SrcRGB.rgbtGreen + SrcRGB.rgbtBlue]; ถ้าเป็นสีเทา + Alpha[SrcRGB.rgbtRed]>0 แล้ว DestRGB.rgbtRed := Min(255,Gray + Alpha[SrcRGB.rgbtRed]) อย่างอื่น DestRGB.rgbtRed := 0; rgbtGreen]>0 จากนั้น DestRGB.rgbtGreen := ต่ำสุด (255, สีเทา + อัลฟ่า [SrcRGB.rgbtGreen]) มิฉะนั้น DestRGB.rgbtGreen := 0; ถ้าสีเทา + อัลฟ่า [SrcRGB.rgbtBlue]>0 แล้ว DestRGB.rgbtBlue := ต่ำสุด (255, สีเทา + อัลฟ่า [SrcRGB.rgbtBlue] ) อื่น ๆ DestRGB.rgbtBlue := 0; Inc(SrcRGB); Inc(DestRGB); end;end; end;//ขั้นตอนการปรับ RGBChange(SrcBmp,DestBmp:TBitmap;RedChange,GreenChange,BlueChange:integer);var SrcRGB, DestRGB: pRGBTriple; = 0 ถึง SrcBmp.Height- 1 จะเริ่มต้น SrcRGB := SrcBmp.ScanLine[i]; DestRGB :=DestBmp.ScanLine[i]; สำหรับ j := 0 ถึง SrcBmp.Width - 1 จะเริ่มต้นถ้า RedChange> 0 จากนั้น DestRGB.rgbtRed := Min(255, SrcRGB.rgbtRed + RedChange) อย่างอื่น DestRGB.rgbtRed := สูงสุด (0, SrcRGB.rgbtRed + RedChange) ถ้า GreenChange> 0 แล้ว DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + GreenChange) อย่างอื่น DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + GreenChange) ถ้า BlueChange> 0 แล้ว DestRGB .rgbtBlue := นาที (255, SrcRGB.rgbtBlue + BlueChange) อื่น ๆ DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue + BlueChange) Inc(DestRGB); end; end;[การปรับสี]//RGB<=>BGRprocedure RGB2BGR(const บิตแมป:TBitmap);var X: จำนวนเต็ม; Y: จำนวนเต็ม; pRGBTriple; Color: Byte;begin for Y := 0 to (Bitmap.Height - 1) do beginning for X := 0 to (Bitmap.Width - 1) do beginning for X := PRGB^.rgbtRed; = PRGB^.rgbtBlue; PRGB^.rgbtBlue := สี; Inc(PRGB); end;end;//ขั้นตอนสีเทา (ถ่วงน้ำหนัก) ระดับสีเทา (const Bitmap:TBitmap);var X: Integer; PRGB: pRGBTriple; Grey: Byte;begin for Y := 0 to (Bitmap.Height - 1) จะเริ่มต้น PRGB := Bitmap.ScanLine[Y]; สำหรับ X := 0 ถึง (Bitmap.Width - 1) จะเริ่มต้นเป็นสีเทา := (77 * แดง + 151 * เขียว + 28 * น้ำเงิน) shr 8; PRGB^.rgbtRed:=Gray; PRGB^.rgbtGreen:=Gray; PRGB^.rgbtBlue:=Gray; end; ;
ทฤษฎี:
คำสำคัญ:
พื้นที่วาดภาพ - นั่นคือพื้นที่ที่หน้าต่างแสดงรูปภาพซึ่งอาจเป็นแบบเต็มหน้าจอก็ได้ (เอฟเฟกต์การวาดจะดีกว่าในแบบเต็มหน้าจอมากกว่าในหน้าต่างทั่วไป)
จุดกึ่งกลาง - นั่นคือพิกัดของจุดกึ่งกลางที่จะแสดงในพื้นที่วาดภาพในภาพต้นฉบับ (ข้อจำกัดความรับผิดชอบ: แนวคิดนี้มีความสำคัญอย่างยิ่ง)
เรามาพูดถึงการขยายภาพกันก่อน ในการขยายภาพ วิธีการทั่วไปของเราคือการขยายภาพโดยตรง แต่วิธีที่แนะนำในบทความนี้จะขยายเฉพาะส่วนที่เราเห็นเท่านั้น มีสองสถานการณ์ในการขยายภาพ การขยายมีขนาดใหญ่กว่าพื้นที่วาดภาพด้วยซ้ำ ไม่มีอะไรจะพูดเกี่ยวกับสถานการณ์นี้มากนัก รูปภาพ ประการที่สองคือรูปภาพที่ขยายมีขนาดใหญ่กว่าพื้นที่วาดภาพ นี่คือหัวข้อสำคัญที่เราจะพูดถึงในวันนี้ ในกรณีนี้ เราต้องกำหนดขนาดของรูปภาพที่ขยายแล้วจึงคำนวณขนาดของรูปภาพ รูปภาพต้นฉบับตามตำแหน่งและขนาด "จุดกึ่งกลาง" และสุดท้ายจะขยายภาพที่ถ่ายไปยังพื้นที่วาดภาพ
เรามาพูดถึงการโรมมิ่งรูปภาพกันดีกว่า เมื่อรูปภาพที่แสดงเกินพื้นที่วาด เราจำเป็นต้องโรมมิ่งรูปภาพเพื่อดูรูปภาพทั้งหมด หลักการคือ: เมื่อคลิกเมาส์ในพื้นที่วาดภาพ มันจะเริ่มโรมมิ่ง บันทึกตำแหน่งการคลิกของเมาส์ก่อน จากนั้นจึงตรวจจับการเคลื่อนไหวของเมาส์ และคำนวณ "จุดกึ่งกลาง" ตามเมาส์และการกระจัดครั้งล่าสุด ( พิกัดหน้าจอจะต้องแปลงเป็นพิกัดภาพต้นฉบับ) นำส่วนที่จะแสดงออกจากภาพต้นฉบับตามหลักการขยายด้านบนแล้วขยายและแสดงในพื้นที่วาด
การใช้อัลกอริทึม:
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() แก้ไขในส่วนอื่นๆ ภาษา () ฯลฯ ถ้า 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 ถ้า wx>hx แล้ว 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 และหมายเลขอ้างอิงอุปกรณ์สุดท้าย ,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 ได้เริ่มต้นแล้ว: integer; " ที่ตั้ง
เมื่อคลิกปุ่มซ้ายของเมาส์ ให้บันทึกตำแหน่งของเมาส์และตำแหน่งของ "จุดกึ่งกลาง" และตั้งค่า FBeginDrag ให้เป็นจริง
เมื่อปุ่มเมาส์ขวาปรากฏขึ้น ให้ตั้งค่า FBeginDrag เป็น false
เมื่อเมาส์เคลื่อนที่ FBeginDrag จะถูกตัดสิน หากเป็นเท็จ จะไม่มีการประมวลผลใดๆ เกิดขึ้น หากเป็นจริง จะดำเนินการต่อไปนี้:
สมมติว่า 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; bitImage.ReleaseHandle;
2. หากคุณต้องการให้รูปภาพปรับให้เข้ากับขนาดของหน้าต่างโดยอัตโนมัติ โปรดดูรหัสต่อไปนี้:
var p1,p2 :double;begin p1:=pw/sw; p2:=ph/sw; ถ้า p1>p2 แล้ว PZoom:=Round(p2*100) อย่างอื่น PZoom:=Round(p1*100); 0 จากนั้น PZoom:=100;สิ้นสุด;
การประมวลผลความสว่างสีพิกเซลภาพระดับสีเทาของ Delphi
ในการประมวลผลภาพ ความเร็วเป็นสิ่งสำคัญ ดังนั้นเราจึงต้องประมวลผล TBitmap ใหม่เพื่อรับ TVczhBitmap นี่เป็นเพียงเพราะ GetPixels และ SetPixels ช้าเกินไป ดังนั้นเราจึงจำเป็นต้องใช้วิธีอื่น
หน่วย untBitmapProc; อินเทอร์เฟซใช้กราฟิก, SysUtils; type TVczhBitmap=class(TBitmap) ข้อมูลส่วนตัว: PByteArray; Line: Integer; function GetBytePointer(X,Y:Integer):PByte; :Byte); ฟังก์ชั่น GetBytes(X,Y:Integer):Byte; ทรัพย์สินสาธารณะ Bytes[X,Y:Integer]:Byte อ่าน GetBytes; PixelFormat:=pf24bit; TVczhBitmap.GetBytePointer(X,Y:Integer):PByte; เริ่มต้นถ้า Line<>Y แล้ว start Line:=Y; Data:=ScanLine[Y]; end; Longint(Data)+X; end; X,Y)^:=ค่า; ฟังก์ชัน TVczhBitmap.GetBytes(X,Y:Integer):Byte; ผลลัพธ์:=GetBytePointer(X,Y)^; end; ; Line:=-1; end; B:Byte; เริ่มต้นสำหรับ Y:=0 ถึง Height-1 do สำหรับ X:=0 ถึง width-1 do start R:=0; สำหรับ B:=0 ถึง 2 do R:=R+GetBytes(X*3+ B,Y); สำหรับ B:=0 ถึง 2 ทำ SetBytes(X*3+B,Y,R div 3); สิ้นสุด;
หลังจากนี้เราจะต้องสร้างหลายรูปแบบ รูปแบบแรกใช้เพื่อแสดงรูปภาพ และรูปแบบที่สองใช้เพื่อประมวลผลรูปภาพ
ลองดูที่หน้าต่างที่สองก่อน:
หน่วย untProc; อินเทอร์เฟซใช้ Windows, ข้อความ, SysUtils, ตัวแปร, คลาส, กราฟิก, การควบคุม, แบบฟอร์ม, กล่องโต้ตอบ, ExtCtrls, untBitmapProc, StdCtrls, ComCtrls; ประเภท TfrmProcessor = คลาส (TForm) pbBar: TPaintBox; ขั้นตอน FormCreate (ผู้ส่ง: TObject); ขั้นตอน FormDestroy (ผู้ส่ง: TObject); ขั้นตอน FormShow (ผู้ส่ง: TObject); ขั้นตอน pbBarPaint (ผู้ส่ง: TObject); ส่วนตัว { ประกาศส่วนตัว } สาธารณะ { การประกาศสาธารณะ } BarData: array [0 ..255] ของ Byte; Bar: TVczhBitmap; การใช้งาน {$R *.dfm} ใช้ untViewer; Bar.Canvas.MoveTo(0,255-BarData[0]); I:=1 ถึง 255 ทำ Bar.Canvas.LineTo(I,255-BarData[I]); สิ้นสุด; TfrmProcessor.FormCreate (ผู้ส่ง: TObject); Bar.Canvas.Brush.Color:=clWhite; =bsSolid; end; ขั้นตอน TfrmProcessor.FormDestroy (ผู้ส่ง: TObject); ขั้นตอน TfrmProcessor.FormShow(Sender: TObject); var I:Integer; start for I:=0 ถึง 255 do BarData[I]:=I; .Canvas.Draw(0,0,Bar); ขั้นตอน TfrmProcessor.Button1Click(ผู้ส่ง: TObject); var X,Y:Integer; เริ่มต้นสำหรับ Y:=0 ถึง Buffer.Height-1 ทำเพื่อ X:=0 ถึง Buffer.Width*3-1 do Played.Bytes[X,Y]:=BarData[Buffer.Bytes[ X,Y]]; frmViewer.FormPaint(frmViewer); สิ้นสุด;
หลังจากนั้น ให้สร้างหน้าต่างที่สืบทอดมาจากหน้าต่างนั้น จากนั้นปรับ BarData[] แล้วกด Apply เพื่อดูผลลัพธ์
ตอนนี้เริ่มประมวลผลภาพ ดูโปรแกรมตัวอย่างสำหรับเอฟเฟกต์เฉพาะ
1. การกลับสี
สีของภาพระดับสีเทามีตั้งแต่ 0 ถึง 255 ดังนั้นเพื่อที่จะกลับสี เราสามารถลบค่าสีออกจาก 255 เพื่อให้ได้สีกลับด้าน
var I:Integer; เริ่มสืบทอด; สำหรับ I:=0 ถึง 255 do BarData[I]:=255-I;//ลบค่าสีออกจาก 255 DrawBar(pbBar);
2. จำกัดช่วงสีให้แคบลงเพื่อเพิ่มหรือลดความสว่าง
สีมีตั้งแต่ 0 ~ 255 หากคุณปรับช่วง เช่น จาก 0 ถึง 16 ภาพจะมืดลงอย่างมาก เราสามารถตั้งค่าเริ่มต้นเป็น a และค่าสิ้นสุดเป็น b จากนั้นค่าสีใหม่ New=a+(b-1)*Old/255 การทำเช่นนี้จะเปลี่ยนความสว่างโดยไม่ทำลายลำดับสีดั้งเดิม รหัสมีดังนี้
var I:Integer; เริ่มต้นสำหรับ I:=0 ถึง 255 ทำ BarData[I]:=(255-sbMin.Position)+Round((sbMin.Position-sbMax.Position)/255*I); DrawBar; ); Button1Click (ปุ่ม 1);
sbMin.Position และ sbMaxPosition ที่นี่ทั้งคู่กลับด้าน ดังนั้นให้ใช้ 255 ลบ
3. เพิ่มช่วงสีภายในช่วงที่กำหนด
หากรูปภาพมีช่วงสีน้อย คุณสามารถใช้วิธีนี้เพื่อเพิ่มคอนทราสต์ของรูปภาพ ซึ่งเป็นประโยชน์ต่อการวิเคราะห์รูปภาพ วิธีการเฉพาะ:
เลือกค่า a เป็นค่าเริ่มต้น เลือกค่า b เป็นค่าสิ้นสุด จากนั้นเปลี่ยนรูปตามสูตรต่อไปนี้:
|. 0 (X<=ก)
ฉ(X)= |. 255/(บา)*(Xa)
|.255(X>=ข)
var I:Integer; start for I:=0 ถึง 255 do start if I<=sbMin.Position แล้ว BarData[I]:=0 else if I>=sbMax.Position แล้ว BarData[I]:=255 else BarData[I ]:=รอบ(255/(sbMax.Position-sbMin.Position)*(I-sbMin.Position)); สิ้นสุด; pbBarPaint(pbBar); Button1Click(ปุ่ม1);
4. แปลงเป็นภาพขาวดำ
เมื่อใช้ฟังก์ชันที่ 3 จะพบว่าเมื่อ b<=a สีในภาพเป็นสีขาวยกเว้นสีดำ ประโยชน์ของการดำเนินการนี้ไม่สามารถแสดงได้โดยตรง วิธีนี้จะได้ผลก็ต่อเมื่อต้องประมวลผลภาพขั้นสูง เช่น การตรวจจับขอบ ตัวอย่างนี้สามารถแปลงได้โดยใช้สูตรของวิธีที่ 3 ดังนั้นจึงไม่สามารถอธิบายได้อย่างละเอียด
5. การปรับความสว่างแบบเอ็กซ์โปเนนเชียล
เราถือว่าโดเมนของกราฟนี้คือ [0,1] และช่วงของค่าก็คือ [0,1] เช่นกัน จากนั้น ให้กำหนดฟังก์ชัน f(x)=x^c จากนั้น รูปภาพของ f(x) จะมีส่วนดังที่แสดงไว้ด้านบน เมื่อเราใช้เมาส์เพื่อทำงานอีกครั้งเราสามารถใช้จุด P (a, b) บนมันแล้วทำให้ F (x) ผ่านจุด P จากนั้น c = ln (b)/ln (a) ด้วย C เราสามารถใช้งานสี:
ใหม่ = (เก่า/255)^c*255 = exp (ln (เก่า/255)*c)*255 Var EA, EB, EC: Extended; /255; Bardata [I]: = EXP (LN (I/255))*EC)*255) DrawBar;
การทำเช่นนี้จะปรับความสว่างของภาพ
เคล็ดลับในการแสดงเอฟเฟกต์พิเศษใน Delphi Graphics
ภาพรวม
---- ในปัจจุบันในซอฟต์แวร์การเรียนรู้และซีดีเกมมากมายคุณมักจะเห็นหลากหลาย
เทคโนโลยีการแสดงผลกราฟิกขึ้นอยู่กับการเคลื่อนไหวของกราฟิกการเชื่อมโยงกันรูปร่างของน้ำฝนมู่ลี่การสร้างบล็อกการจัดซ้อนและวิธีการแสดงผลอื่น ๆ เพื่อให้ภาพมีชีวิตชีวาและน่าดึงดูดยิ่งขึ้นสำหรับผู้ชม บทความนี้จะสำรวจวิธีการใช้เทคนิคการแสดงผลกราฟิกต่างๆใน Delphi
หลักการพื้นฐาน
---- ใน Delphi มันง่ายมากที่จะแสดงภาพ และไฟล์ที่เลือกจะปรากฏในส่วนประกอบ timage แต่สิ่งนี้เพียงแสดงกราฟิกโดยตรงในรูปแบบและไม่มีทักษะเลย เพื่อให้การแสดงผลกราฟิกมีเอฟเฟกต์ที่ไม่ซ้ำกันคุณสามารถทำตามขั้นตอนต่อไปนี้:
---- กำหนดส่วนประกอบช่วงเวลาและโหลดกราฟิกที่จะแสดงลงในส่วนประกอบช่วงเวลาก่อนนั่นคือโหลดเนื้อหากราฟิกจากดิสก์ลงในหน่วยความจำเป็นแคชกราฟิก
---- สร้างวัตถุบิตแมปใหม่ที่มีขนาดเท่ากับกราฟิกในส่วนประกอบช่วงเวลา
---- ใช้ฟังก์ชั่นลิขสิทธิ์ของผืนผ้าใบ (คัดลอกพื้นที่สี่เหลี่ยมของผืนผ้าใบหนึ่งไปยังพื้นที่สี่เหลี่ยมของผืนผ้าใบอื่น) ใช้เทคนิคและรูปร่างแบบไดนามิก
แปลงเนื้อหาไฟล์เป็นบิตแมปจากนั้นแสดงบิตแมปในแบบฟอร์ม
---- วิธีการใช้งาน
เทคนิคการแสดงผลกราฟิกต่างๆมีการแนะนำด้านล่าง:
1. เอฟเฟกต์แบบพัล
ดึงกราฟิกที่จะแสดงลงในหน้าจอจากขึ้น, ลง, ซ้ายและขวาทิศทางและในเวลาเดียวกันครอบคลุมกราฟิกเก่าดั้งเดิมบนหน้าจอ ดึงไปทางซ้ายและดึงไปทางขวา
หลักการ: ขั้นแรกให้ย้ายเส้นแนวนอนแรกที่วางไว้ในกราฟิกชั่วคราวไปยังอันสุดท้ายในบิตแมปที่จะแสดงแล้วย้ายเส้นแนวนอนสองเส้นแรกในกราฟิกชั่วคราวไปยังบิตแมปสองเส้นสุดท้ายที่จะแสดง จากนั้นย้ายสามและสี่บรรทัดแรกจนกว่าข้อมูลกราฟิกทั้งหมดจะถูกย้าย ในระหว่างกระบวนการเคลื่อนที่คุณจะเห็นว่าบิตแมปที่แสดงลอยจากล่างขึ้นบนเพื่อให้ได้เอฟเฟกต์แบบดึงขึ้น
อัลกอริทึมโปรแกรม:
ขั้นตอน TFORM1.BUTTON1CLICK (ผู้ส่ง: tobject); : = image1.height; i: = 0 ถึง bmpheight เริ่มต้น newbmp.canvas.copyrect (rect (0, bmpheight-i, bmpwidth, bmpheight), image1.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 ทำเพื่อ j: = 1 ถึงฉันเริ่ม newbmp.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; xgroup: = 16; -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 ลงในแบบฟอร์ม องค์ประกอบเวลาอื่นมีคุณสมบัติชื่อตั้งค่าเป็น Image2 ซึ่งแสดงภาพที่ขยายใหญ่ขึ้น
แกนกลางของตัวอย่างนี้คือฟังก์ชั่นการยืดตัว
ขั้นตอน tform1.image1mousemove (ผู้ส่ง: tobject; shift: tshiftstate; x, y: จำนวนเต็ม); เริ่ม stretchblt (image2.canvas.handle, 0,0, image2.width, image2.height, image1.canvas.handle, y- 20,40,40, srccopy); Screen.cursors [1]: = loadcursorFromFile ('magnify.cur');
โปรแกรมจะเรียกใช้ฟังก์ชัน stretchblt ก่อนใช้ตำแหน่งปัจจุบันของเมาส์เป็นจุดกึ่งกลางเลือกภาพบางส่วนบนองค์ประกอบ Image1 ที่มีความยาวด้านข้าง 40 และขยายภาพบางส่วนไปยังองค์ประกอบ Image2 จากนั้นรีเฟรชการแสดงผลของส่วนประกอบ Image2 โดยเรียกวิธีการรีเฟรชของส่วนประกอบ Image2 ในที่สุดก็ตั้งค่าตัวชี้เมาส์เป็นรูปร่างใหม่
รหัสโปรแกรมมีดังนี้:
UNIT1; Interfaceuseswindows, ข้อความ, sysutils, ตัวแปร, คลาส, กราฟิก, การควบคุม, รูปแบบ, กล่องโต้ตอบ, extctrls, stdctrls; พิมพ์ tform1 = คลาส (tform) image1: timage; ; x, y: จำนวนเต็ม); formmousemove (ผู้ส่ง: tobject; shift: tshiftstate;; shift: tshiftstate; x, y: จำนวนเต็ม); เริ่มต้น (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: จำนวนเต็ม); .
บันทึกไฟล์แล้วกดปุ่ม F9 เพื่อเรียกใช้โปรแกรมและโปรแกรมจะเรียกใช้
การขยายภาพเป็นฟังก์ชั่นที่สำคัญของซอฟต์แวร์การดูภาพที่ยอดเยี่ยม
ฉันหวังว่าบทความนี้จะเป็นประโยชน์กับการเขียนโปรแกรม Delphi ของทุกคน