تلخص الأمثلة الواردة في هذه المقالة الطرق الأساسية لمعالجة الصور في دلفي. شاركها مع الجميع لتكون مرجعا لك. التحليل المحدد هو كما يلي:
// إجراء النقش 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 إلى SrcBmp.Height - 1 يبدأ SrcRGB := SrcBmp.ScanLine[i]; DestRGB := DestBmp.ScanLine[i]; إذا (AzimuthChange >= -180) و(AzimuthChange <-135) ثم ابدأ إذا كان i > 0 ثم SrcRGB1 := SrcBmp.ScanLine[i-1] else SrcRGB1 := SrcRGB Inc(SrcRGB1); := SrcRGB; Inc(SrcRGB2); end 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 end else if (AzimuthChange >= -45) و(AzimuthChange <0) ثم ابدأ SrcRGB1 := SrcRGB; SrcBmp.Height - 1) ثم SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB; end else if (AzimuthChange >= 45) و (AzimuthChange <90) ثم ابدأ إذا (i < SrcBmp.Height - 1) ثم SrcRGB1 := SrcBmp.ScanLine[i +1] else SrcRGB1 := SrcRGB2 := SrcRGB1؛ end else if (AzimuthChange >= 90) and (AzimuthChange < 135) ثم ابدأ إذا (i < SrcBmp.Height - 1) ثم SrcRGB1 := SrcBmp.ScanLine[i+1] else SrcRGB1 := SrcRGB2 := SrcRGB1; Inc(SrcRGB1); (AzimuthChange >= 135) و(AzimuthChange <= 180) ثم ابدأ إذا (i < SrcBmp.Height - 1) ثم SrcRGB2 := SrcBmp.ScanLine[i+1] else SrcRGB2 := SrcRGB Inc(SrcRGB2); = SrcRGB; Inc(SrcRGB1); 0 إلى SrcBmp.Width - 1 يبدأ إذا (AzimuthChange >= -180) و(AzimuthChange <-135) ثم يبدأ قيمة السمت := AzimuthChange + 180 R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*قيمة السمت div 45)-((SrcRGB2.rgbtRed)*(45-قيمة السمت) div 45)+78; قيمة السمت)div 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*قيمة السمت div 45)-((SrcRGB2.rgbtBlue)*(45-قيمة السمت) div 45)+78; < -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) * قسم قيمة السمت 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; end else if (AzimuthChange >= -90) and (AzimuthChange < -45) ثم ابدأ إذا كانت j=1 ثم Inc(SrcRGB1,- 1); قيمة السمت := تغيير السمت + 90; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*قيمة السمت div 45)-((SrcRGB2.rgbtRed)*(45-قيمة السمت) div 45)+78; * قسم قيمة السمت 45)-((SrcRGB2.rgbtGreen)*(45-قيمة السمت) div 45)+78; قيمة السمت) div 45)+78; if (AzimuthChange >= -45) and (AzimuthChange < 0) ثم ابدأ إذا كان j=1 ثم ابدأ Inc(SrcRGB2,-1); SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*قيمة السمت div 45)-((SrcRGB2.rgbtRed)*(45-قيمة السمت) div 45)+78; قيمة السمت)div 45)+78; B:=SrcRGB.rgbtBlue-((SrcRGB1.rgbtBlue)*قيمة السمت div 45)-((SrcRGB2.rgbtBlue)*(45-قيمة السمت) div 45)+78; 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) * قسم قيمة السمت 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; end else if (AzimuthChange >= 45) and (AzimuthChange <90) ثم ابدأ إذا j=1 ثم Inc(SrcRGB2,-1) ; قيمة السمت := تغيير السمت - 45; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*قيمة السمت div 45)-((SrcRGB2.rgbtRed)*(45-قيمة السمت) div 45)+78; * قسم قيمة السمت 45)-((SrcRGB2.rgbtGreen)*(45-قيمة السمت) div 45)+78; قيمة السمت) div 45)+78; إذا (AzimuthChange >= 90) و (AzimuthChange < 135) ثم ابدأ قيمة السمت := AzimuthChange - 90; - قيمة السمت) شعبة 45)+78; (SrcRGB1.rgbtBlue)*قيمة السمت div 45)-((SrcRGB2.rgbtBlue)*(45-Azimuthvalue) div 45)+78; end else if (AzimuthChange >= 135) and (AzimuthChange <= 180) ثم ابدأ Azimuthvalue := AzimuthChange - 135; R:=SrcRGB.rgbtRed-((SrcRGB1.rgbtRed)*قيمة السمت div 45)-((SrcRGB2.rgbtRed)*(45-قيمة السمت) div 45)+78; * قسم قيمة السمت 45)-((SrcRGB2.rgbtGreen)*(45-قيمة السمت) div 45)+78; قيمة السمت) div 45)+78; R:=Min(R,255); R:=Max(R,0); B:=Max(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; ))) ثم ابدأ Inc(SrcRGB1); (j=135) و (AzimuthChange<180)) أو ((AzimuthChange>=-180) و (AzimuthChange<=-90))) ثم ابدأ Inc(SrcRGB2); Inc(SrcRGB Inc(DestRGB); النهاية؛ النهاية؛ الإجراء Emboss(Bmp:TBitmap;AzimuthChange:integer;ElevationChange:integer;WeightChange:integer);overload;var DestBmp:TBitmap;begin DestBmp:=TBitmap.Create; DestBmp.Assign(Bmp); ، تغيير الوزن)؛ Bmp.Assign(DestBmp);end;// الإجراء العكسي Negative(Bmp:TBitmap);var i, j: PRGB: pRGBTriple;begin Bmp.PixelFormat:=pf24Bit; ابدأ PRGB := Bmp.ScanLine[i]; لـ j := 0 إلى Bmp.Width - 1 do begin PRGB^.rgbtRed :=not PRGB^.rgbtRed ;=not PRGB^.rgbtGreen; إجراء التعريض Exposure(Bmp:TBitmap);var i, j: عدد صحيح; Bmp.PixelFormat:=pf24Bit; for i := 0 إلى Bmp.Height - 1 يبدأ PRGB := Bmp.ScanLine[i]; لـ j := 0 إلى Bmp.Width - 1 يبدأ إذا كان PRGB^.rgbtRed<128 ثم PRGB^.rgbtRed :=not PRGB^.rgbtRed ; إذا كان PRGB^.rgbtGreen<128 ثم PRGB^.rgbtGreen:=not PRGB^.rgbtGreen; إذا كان PRGB^.rgbtBlue<128 ثم PRGB^.rgbtBlue:=not PRGB^.rgbtBlue Inc(PRGB);end; SrcBmp:TBitmap);var i, j:Integer; SrcNextRGB:pRGBTriple; SrcPreRGB:pRGBTriple; Value:Integer; begin Inc(SrcRGB); 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 ثم SrcNextRGB:=SrcBmp.ScanLine[i+1] else SrcNextRGB:=SrcBmp.ScanLine[i]; for j := 0 إلى SrcBmp.Width - 1 يبدأ إذا كانت j > 0 ثم قيمة DecRGB:=SrcPreRGB.rgbtRed+ SrcRGB .rgbtRed+SrcNextRGB.rgbtRed; 0 ثم قيمة IncRGB:=(Value+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 Value:=(Value+SrcPreRGB.rgbtGreen+SrcRGB.rgbtGreen+SrcNextRGB.rgbtGreen) div 9; غيغابايت ; SrcRGB.rgbtGreen:=value; .rgbtBlue; إذا كان j < SrcBmp.Width - 1 ثم IncRGB؛ القيمة:=(Value+SrcPreRGB.rgbtBlue+SrcRGB.rgbtBlue+SrcNextRGB.rgbtBlue) div 9; SrcRGB.rgbtBlue:=value; end; شحذ(SrcBmp:TBitmap);var i, j: SrcRGB: pRGBTriple; SrcPreRGB: pRGBTriple; Value: integer;begin SrcBmp.PixelFormat:=pf24Bit; 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) شعبة 2; Value:=Max(0,Value); Value:=Min(255,Value); SrcRGB.rgbtRed:=value; Max(0,Value Value:=Min(255,Value); SrcRGB.rgbtGreen:=value; Value:=SrcRGB.rgbtBlue+(SrcRGB.rgbtBlue-SrcPreRGB.rgbtBlue) div 2; القيمة Inc(SrcRGB); [تدوير الصورة وقلبها] يتم تنفيذ الكود التالي باستخدام ScanLine مع حركة المؤشر، للحصول على لون 24 بت! // إجراء التدوير بمقدار 90 درجة Rotate90(const Bitmap:TBitmap);var i,j:Integer;rowIn,rowOut:pRGBTriple; Bmp:TBitmap; Bitmap.Height; Bmp.Height := Bitmap.Width; pf24bit; Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 للارتفاع ابدأ الصف:= Bitmap.ScanLine[j]; = Bmp.ScanLine[i]; Bitmap.Assign(Bmp);end;// إجراء التدوير 180 درجة Rotate180(const Bitmap:TBitmap);var i,j:Integer;rowIn,rowOut:pRGBTriple; TBitmap.Create; Bmp.Width := Bitmap.Width; Bitmap.Height; Bmp.PixelFormat := pf24bit; Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; := 0 للعرض، ابدأ الصف := Bmp.ScanLine[Height - j]; Inc(rowOut,Width - i); RowOut^ :=rowIn^; Inc(rowIn); end; pRGBTriple; Bmp:TBitmap; := Bitmap.Height; Bmp.Height := Bmp.PixelFormat := pf24bit Width:=Bitmap.Width-1; := Bitmap.ScanLine[j]; for i := 0 إلى العرض، ابدأ الصف := Bmp.ScanLine[Width - i]; Inc(rowOut,j); RotateBitmap(Bitmap); TBitmap;Angle:Integer;BackColor:TColor):TBitmap;var i,j,iOriginal,jOriginal,CosPoint,SinPoint: RowOriginal,RowRotated : pRGBTriple; ; إذا كانت الزاوية<0 Angle:=360-Abs(Angle); إذا كانت Angle=0 ثم Result.Assign(Bitmap) وإلا إذا كانت Angle=90 فابدأ Result.Assign(Bitmap);// إذا تم تدويرها 90 درجة، فاتصل إنه مباشرة ينتهي الكود أعلاه وإلا إذا (Angle>90) و (Angle<180) ثم يبدأ AngleAdd:=90; Angle:=Angle-AngleAdd; end else if Angle=180 ثم ابدأ Result.Assign(Bitmap); Angle<270) ثم ابدأ AngleAdd:=180; Angle:=Angle-AngleAdd; نهاية إذا كانت Angle=270 فابدأ Result.Assign(Bitmap);// إذا تم تدويره بمقدار 270 درجة، فاستدعاء نهاية العملية المذكورة أعلاه مباشرةً وإلا إذا (Angle>270) و(Angle<360) فابدأ AngleAdd:=270; Angle -AngleAdd; end else AngleAdd:=0; إذا (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)); = Round(Abs(Bitmap.Width * SinTheta - Bitmap.Height * CosTheta)); النهاية وإلا ابدأ Result.Width := Round(Abs(Bitmap.Width * CosTheta + Bitmap.Height * SinTheta)); Result.Height := Round(Abs(Bitmap.Width * SinTheta + Bitmap.Height * CosTheta)); ; CosTheta:=Abs(CosTheta); (AngleAdd=0) أو (AngleAdd=180) ثم ابدأ CosPoint:=Round(Bitmap.Height*CosTheta);=Round(Bitmap.Height*SinTheta); ); CosPoint:=Round(Bitmap.Width*SinTheta); Result.Height-1 يبدأ RowRotated := Result.Scanline[j]; for i := 0 إلى Result.Width-1 يبدأ Case AngleAdd of 0: begin jOriginal := Round((j+1)*CosTheta-( i+1-SinPoint)*SinTheta)-1; Round((i+1)*CosTheta-(CosPoint-j-1)*SinTheta)-1; )-1; jOriginal := Bitmap.Height-Round((i+1)*SinTheta-(CosPoint-j-1)*CosTheta); النهاية 180: البدء jOriginal := Bitmap.Height-Round((j+1)*CosTheta-(i+1-SinPoint)*SinTheta); (CosPoint-j-1)*SinTheta); Bitmap.Width-Round((j+1)*SinTheta-(i+1-SinPoint)*CosTheta); النهاية؛ إذا (iOriginal >= 0) و (iOriginal <= Bitmap.Width-1) و (jOriginal >= 0) و (jOriginal <= Bitmap.Height-1) ثم ابدأ RowOriginal := Bitmap.Scanline[jOriginal]; Inc(RowOriginal,iOriginal); ; end; end; end;// إجراء الوجه الأفقي FlipHorz(const Bitmap:TBitmap);var i,j:Integer;rowIn,rowOut:pRGBTriple; PixelFormat := pf24bit Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 to Height do startrowIn := Bitmap.ScanLine[j]; for i := 0 to Width do beginrowOut := Bmp.ScanLine[j] Inc(rowOut ,Width - i);rowOut^ :=rowIn^; end; FlipVert(const Bitmap:TBitmap);var i,j:Integer;rowIn,rowOut:pRGBTriple; الارتفاع := Bitmap.Width; Width:=Bitmap.Width-1; Height:=Bitmap.Height-1; for j := 0 إلى الارتفاع ابدأ الصف := Bitmap.ScanLine[j]; .ScanLine[Height - j]; Inc(rowOut,i); Bitmap.Assign(Bmp);end;[تعديل السطوع والتباين والتشبع] يتم تنفيذ الكود التالي باستخدام ScanLine مع حركة المؤشر! الوظيفة Min(a, b: integer): عدد صحيح;تبدأ إذا كانت a < b ثم النتيجة:= نتيجة أخرى:= b;end;الوظيفة Max(a, b: عدد صحيح): عدد صحيح;تبدأ إذا كانت a > b ثم النتيجة: = نتيجة أخرى := b;end;// إجراء ضبط السطوع 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]; DestBmp.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 نهاية أخرى تبدأ DestRGB.rgbtRed): =الحد الأقصى(0، SrcRGB.rgbtRed + ValueChange); DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + ValueChange); ; end;end;end;//إجراء تعديل التباين ContrastChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);var i, j: integer; ; 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 - ValueChange if). SrcRGB.rgbtGreen >= 128 ثم DestRGB.rgbtGreen := Min(255, SrcRGB.rgbtGreen + ValueChange) else 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); + تغيير القيمة) آخر 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 end; Inc(DestRGB); end;end;// إجراء تعديل التشبع SaturationChange(const SrcBmp,DestBmp:TBitmap;ValueChange:integer);var Grays: array[0..767] of Integer; x، y: عدد صحيح؛ بايت؛beginValueChange:=ValueChange+255؛for i := 0 إلى 255 do Alpha[i] := (i * ValueChange) Shr 8;x := 0;for i := 0 إلى 255 dobegin Gray := i - Alpha [i]؛ Grays[x] := Gray Inc(x); Inc(x);end; for y := 0 إلى SrcBmp.Height - 1 dobegin SrcRGB := SrcBmp.ScanLine[Y]; DestRGB := DestBmp.ScanLine[Y]; ابدأ باللون الرمادي := Grays[SrcRGB.rgbtRed + SrcRGB.rgbtGreen + SrcRGB.rgbtBlue]; إذا كان Gray + Alpha[SrcRGB.rgbtRed]>0 ثم DestRGB.rgbtRed := Min(255,Gray + Alpha[SrcRGB.rgbtRed]) else DestRGB.rgbtRed := 0; rgbtGreen]>0 ثم DestRGB.rgbtGreen := Min(255,Gray + Alpha[SrcRGB.rgbtGreen]) else DestRGB.rgbtGreen := 0; إذا كان Gray + Alpha[SrcRGB.rgbtBlue]>0 ثم DestRGB.rgbtBlue := Min(255,Gray + Alpha[SrcRGB.rgbtBlue] ) else DestRGB.rgbtBlue := 0; Inc(DestRGB); end; end;// إجراء ضبط RGB RGBChange(SrcBmp,DestBmp:TBitmap;RedChange,GreenChange,BlueChange:integer);var SrcRGB, DestRGB: pRGBTriple; = 0 إلى SrcBmp.Height- 1 يبدأ SrcRGB := SrcBmp.ScanLine[i]; DestRGB :=DestBmp.ScanLine[i]; for 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) else DestRGB.rgbtGreen := Max(0, SrcRGB.rgbtGreen + GreenChange); .rgbtBlue := الحد الأدنى (255، SrcRGB.rgbtBlue + BlueChange) else DestRGB.rgbtBlue := Max(0, SrcRGB.rgbtBlue + BlueChange); Inc(SrcRGB Inc(DestRGB;end;[تعديل اللون]//RGB<=>BGRprocedure RGB2BGR(const Bitmap:TBitmap);var X: عدد صحيح Y: عدد صحيح; pRGBTriple؛ اللون: بايت؛ يبدأ من Y := 0 إلى (Bitmap.Height - 1) يبدأ من X := 0 إلى (Bitmap.Width - 1) يبدأ اللون:= PRGB^.rgbtRed; = PRGB^.rgbtBlue; PRGB^.rgbtBlue := Color Inc(PRGB); end;end;// إجراء التدرج الرمادي (المرجح) Grayscale(const Bitmap:TBitmap);var X: Y: Integer; ابدأ PRGB := Bitmap.ScanLine[Y]; لـ X := 0 إلى (Bitmap.Width - 1) ابدأ باللون الرمادي := (77 * أحمر + 151 * أخضر + 28 * أزرق) shr 8؛ PRGB^.rgbtRed:=Gray; ;
نظرية:
الكلمات الرئيسية:
منطقة الرسم - أي المنطقة التي تعرض فيها النافذة الصورة، والتي يمكن أن تكون أيضًا ملء الشاشة (يكون تأثير الرسم أفضل في ملء الشاشة منه في النافذة العامة)
النقطة المركزية - أي إحداثيات النقطة المركزية التي سيتم عرضها في منطقة الرسم في الصورة الأصلية (إخلاء المسؤولية: هذا المفهوم مهم بشكل خاص)
لنتحدث أولاً عن تكبير الصورة، نهجنا العام هو تكبير الصورة مباشرةً، لكن الطريقة المقدمة في هذه المقالة تقوم فقط بتكبير الجزء الذي يمكننا رؤيته. هناك حالتان للتكبير: أحدهما هو المنطقة التالية التكبير أكبر من مساحة الرسم، ولا يوجد الكثير مما يمكن قوله عن هذا الوضع. الصورة الثانية هي أن الصورة المكبرة أكبر من مساحة الرسم وهذا هو الموضوع الرئيسي الذي سنناقشه اليوم، وفي هذه الحالة يجب علينا أولاً تحديد حجم الصورة المكبرة، ومن ثم حساب حجمها الصورة الأصلية بناءً على موضع وحجم "النقطة المركزية"، وأخيرًا قم بتكبير الصورة الملتقطة إلى منطقة الرسم.
لنتحدث عن تجوال الصور عندما تتجاوز الصورة المعروضة منطقة الرسم، نحتاج إلى تجوال الصورة لرؤية الصورة بأكملها. المبدأ هو: عندما ينقر الماوس في منطقة الرسم، فإنه يبدأ التجوال، ويسجل أولاً موضع نقر الماوس، ثم يكتشف حركة الماوس، ويحسب "النقطة المركزية" بناءً على الماوس والإزاحة الأخيرة ( (يجب تحويل إحداثيات الشاشة إلى إحداثيات الصورة الأصلية)، وإخراج الجزء المراد عرضه من الصورة الأصلية وفقًا لمبدأ التكبير أعلاه، وتكبيره وعرضه في منطقة الرسم.
تنفيذ الخوارزمية:
1. تكبير الصورة
تعريف متغير:
PZoom: معدل التكبير (العدد الصحيح: 100 هو 100%، يمكن تغيير 100 إلى 10000 أو أكبر حسب الحاجة، ولكن لا يوصى باستخدام أرقام الفاصلة العائمة)
أ، ب: النقطة المركزية
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// ملاحظة: يتم استخدام التقريب للتقريب، مثل Int()، والإصلاح في طرق أخرى اللغات ()إلخ إذا كان p1>1 ثم w=Round(sw/p1) وإلا w=swif p2>1 ثم h=Round(sh/p2) آخر 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); احسب موضع الصورة vx:=(pw-vw) 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; " موقع
عند النقر فوق زر الماوس الأيسر، قم بتسجيل موضع الماوس وموضع "النقطة المركزية"، ثم قم بتعيين FBeginDrag إلى true.
عندما ينبثق زر الفأرة الأيمن، قم بتعيين FBeginDrag إلى false
عندما يتحرك الماوس، يتم الحكم على FBeginDrag إذا كان خطأ، فلن يتم إجراء أي معالجة. إذا كان صحيحًا، يتم تنفيذ المعالجة التالية:
افترض أن X وY هما الموضع الحالي للماوس
a=FBeginDragPoint.X-((X-FBeginDragPoint.X)*100) div PZoomb=FBeginDragPoint.Y-((Y-FBeginDragPoint.Y)*100) div PZoom
وأخيرا، استخدم الصورة المعروضة أعلاه لتكبير الصورة وعرضها
نصائح:
1. إذا كانت الصورة كبيرة، سيحدث خطأ في تجاوز سعة الذاكرة عند استخدام كائن الصورة النقطية لدلفي، في هذه الحالة، يمكنك إجراء الإعدادات التالية:
bitImage:=TBitmap.Create; bitImage.PixelFormat:=pf24bit;
2. إذا كنت تريد أن تتكيف الصورة تلقائيًا مع حجم النافذة، فارجع إلى الكود التالي:
var p1,p2 :double;begin p1:=pw/sw; if p1>p2 ثم PZoom:=Round(p2*100) else PZoom:=Round(p1*100); 0 ثم PZoom:=100;end;
معالجة سطوع ألوان بكسل الصورة بتدرج دلفي الرمادي
في معالجة الصور، السرعة مهمة. ولذلك، يتعين علينا إعادة معالجة TBitmap للحصول على TVczhBitmap. وذلك لأن GetPixels وSetPixels بطيئان للغاية، لذلك نحتاج إلى استخدام طريقة أخرى.
واجهة untBitmapProc تستخدم الرسومات، SysUtils؛ نوع TVczhBitmap=class(TBitmap) data:PByteArray; Line:Integer; Value :Byte); وظيفة GetBytes(X,Y:Integer):Byte; الخاصية العامة Bytes[X,Y:Integer]: بايت يقرأ SetBytes؛ الإجراء LoadFromFile(FileName:String); نهاية الإجراء TVczhBitmap.SetFormat; TVczhBitmap.GetBytePointer(X,Y:Integer):PByte; يبدأ إذا كان Line<>Y بعد ذلك start Line:=Y; Data:=ScanLine[Y]; end; Longint(result):=Longint(Data)+X; end; X,Y)^:=Value; function TVczhBitmap.GetBytes(X,Y:Integer):Byte; result:=GetBytePointer(X,Y)^; end; create inherited Create SetFormat; end; ; Line:=-1; end; الإجراء TVczhBitmap.ToGray; B: البايت يبدأ من Y:=0 إلى الارتفاع-1 من أجل X:=0 إلى العرض-1 يبدأ من R:=0 من أجل B:=0 إلى 2 يفعل R:=R+GetBytes(X*3+ B,Y); for B:=0 to 2 do SetBytes(X*3+B,Y,R div end;
بعد ذلك، نحن بحاجة إلى إنشاء عدة أشكال. يستخدم الأول لعرض الصور، ويستخدم الثاني لمعالجة الصور. جميع النماذج الأخرى ترث من النموذج الثاني وتحتوي على طرق المعالجة الفعلية.
لننظر إلى النافذة الثانية أولاً:
تستخدم واجهة الوحدة untProc Windows، والرسائل، وSysUtils، والمتغيرات، والفئات، والرسومات، والنماذج، ومربعات الحوار، وExtCtrls، وuntBitmapProc، وStdCtrls، وComCtrls؛ إنشاء نموذج الإجراء (المرسل: TObject); الإجراء FormDestroy(Sender: TObject); الإجراء FormShow(Sender: TObject); الإجراء pbBarPaint(Sender: TObject); الإجراء Button1Click(Sender: TObject); public { الإعلانات العامة } BarData:array[0 ..255]من شريط:TVczhBitmap نهاية الإجراء؛ var frmProcessor: TfrmProcessor؛ يستخدم الإجراء {$R *.dfm} untViewer؛ TfrmProcessor.DrawBar؛ var I:Integer; begin Bar.Canvas.FillRect(Bar.Canvas.ClipRect); I:=1 إلى 255 قم بإجراء Bar.Canvas.LineTo(I,255-BarData[I]); TfrmProcessor.FormCreate(Sender: TObject); begin Bar:=TVczhBitmap.Create; =bsSolid end; الإجراء TfrmProcessor.FormDestroy(Sender: TObject); end؛ الإجراء TfrmProcessor.FormShow(Sender: TObject); var I:Integer; begin for I:=0 to 255 do BarData[I]:=I; .Canvas.Draw(0,0,Bar); الإجراء TfrmProcessor.Button1Click(Sender: TObject); var X,Y:Integer; begin for Y:=0 to 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; begin inherited; for I:=0 to 255 do BarData[I]:=255-I;// اطرح قيمة اللون من 255 DrawBar;
2. قم بتضييق نطاق الألوان لتعزيز السطوع أو إضعافه
اللون في الأصل من 0 ~ 255. إذا قمت بضبط نطاقها، على سبيل المثال من 0 إلى 16، ستصبح الصورة أكثر قتامة بشكل ملحوظ. يمكننا ضبط قيمة البداية على a وقيمة النهاية على b، ثم قيمة اللون الجديدة New=a+(b-1)*Old/255. يؤدي القيام بذلك إلى تغيير السطوع دون تدمير تسلسل الألوان الأصلي. الرمز هو كما يلي
var I:Integer; begin for I:=0 to 255 do BarData[I]:=(255-sbMin.Position)+Round((sbMin.Position-sbMax.Position)/255*I); pbBarPaint(pbBar );
كلا من sbMin.Position وsbMaxPosition هنا معكوسان. لذلك، استخدم 255 للطرح
3. زيادة نطاق الألوان ضمن نطاق معين
إذا كانت الصورة نفسها تحتوي على نطاق ألوان صغير، فيمكنك استخدام هذه الطريقة لزيادة تباين الصورة، وهو أمر مفيد لتحليل الصورة. طرق محددة:
حدد قيمة a كقيمة البداية، وحدد قيمة b كقيمة النهاية، ثم قم بالتشويه وفقًا للصيغة التالية:
|.0 (س<=أ)
و(X)= |.255/(با)*(Xa)
|.255(س>=ب)
var I:Integer; begin for I:=0 to 255 do start if I<=sbMin.Position ثم BarData[I]:=0 وإلا إذا I>=sbMax.Position ثم BarData[I]:=255 else BarData[I ]:=Round(255/(sbMax.Position-sbMin.Position)*(I-sbMin.Position)); pbBarPaint(pbBar);
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 ، يمكننا العمل على اللون:
جديد = (Old/255)^C*255 = LN (Old/255)*C) /255 ؛ Bardata [i]: exp (ln (i/255)*eC) ؛
القيام بذلك يعدل سطوع الصورة.
نصائح لعرض المؤثرات الخاصة في رسومات دلفي
ملخص
---- في الوقت الحاضر ، في العديد من البرامج التعليمية والأقراص المدمجة للألعاب ، يمكنك في كثير من الأحيان رؤية مختلف
تعتمد تقنية العرض الرسومية على حركة الرسوم ، والتداخل ، وشكل قطرة المطر ، والستائر ، وتكديس لبنة البناء وطرق العرض الأخرى لجعل الصورة أكثر حيوية وأكثر جاذبية للجمهور. ستستكشف هذه المقالة كيفية تنفيذ العديد من تقنيات عرض الرسوم في دلفي.
المبادئ الأساسية
---- في دلفي ، من السهل جدًا عرض صورة. وسيتم عرض الملف المحدد في مكون TIMAGE. لكن هذا يعرض الرسومات مباشرة في النموذج ، ولا توجد مهارة على الإطلاق. من أجل جعل عرض الرسوم يكون له تأثير فريد ، يمكنك اتباع الخطوات التالية:
---- تحديد مكون توقيت ، وقم بتحميل الرسومات المراد عرضها في مكون timage أولاً ، أي ، قم بتحميل محتوى الرسومات من القرص إلى الذاكرة كذاكرة التخزين المؤقت للرسومات.
---- إنشاء كائن Bitmap جديد بنفس حجم الرسومات في مكون Timage.
---- استخدم وظيفة حقوق النشر للقطن (انسخ المساحة المستطيلة لأحد اللوحة إلى المنطقة المستطيلة من قماش آخر) ، والتقنيات ، والشكل الديناميكي
قم بتحويل محتويات الملف إلى صورة نقطية ثم عرض صورة نقطية في النموذج.
---- طريقة التنفيذ
يتم تقديم تقنيات عرض الرسوم البيانية المختلفة أدناه:
1.push-pull effect
اسحب الرسومات المراد عرضها في الشاشة من الاتجاهات لأعلى وأسفل واليسار واليمين ، وفي الوقت نفسه ، يمكن تقسيم الرسومات القديمة الأصلية على الشاشة. سحب اليسار ، وسحب اليمين.
المبدأ: أولاً ، حرك الخط الأفقي الأول الموضوع في الرسم المؤقت إلى آخر خط النقط الذي يتم عرضه ، ثم تحرك الخطين الأفقيين في الرسم المؤقت إلى آخر خطوط نقطية ليتم عرضه ثم حرك الخطوط الثلاثة والأربعة الأولى حتى يتم نقل جميع البيانات الرسومية. أثناء العملية المتحركة ، يمكنك أن ترى أن صورة نقطية معروضة تطفو من أسفل إلى أعلى ، مما يحقق تأثير السحب.
خوارزمية البرنامج:
الإجراءات tform1 : = Image1. HIEGH I: = 0 إلى BMPHEight تبدأ newbmp.canvas.copyrect (Rect (0 ، BMPHEIGHT-I ، BMPWIDTH ، BMPHEIGH ، newbmp) ؛
2. التأثير العمودي المتداخلة
المبدأ: تقسيم الرسومات المراد عرضها إلى جزأين. من الشاشة ، يمكنك أن ترى أن الرسومات الأخف التي تظهر في الأطراف العلوية والسفلية تتحرك نحو مركز الشاشة حتى تكون واضحة تمامًا.
خوارزمية البرنامج:
الإجراءات tform1.button4 (Sender: var) ؛ ؛ i: = 0 ؛ BMPHEight-I+J-1 ، BMPWIDTH ، BMPHEIGHT-I+J)) ؛ (0 ، BMPHEIGHT-J ، BMPWIDTH ، BMPHEIGHT-J+1) (120،100 ، newbmp) ؛
3. التأثير الأفقي المتداخل
المبدأ: نفس مبدأ التأثير المتداخل العمودي ، باستثناء أن الرسومات المقسمة إلى مجموعتين يتم نقلها إلى الشاشة من النهايات اليمنى واليمنى على التوالي.
خوارزمية البرنامج:
الإجراءات tform1.button5 ؛ I: = 0 ؛ i+j-1 ، bmpwidth-i+j ، bmpheight)) ؛ (BMPWIDTH-J ، 0 ، BMPWIDTH-J+1 ، BMPHEIGHT) (120،100 ، newbmp) ؛
4. تأثير قطرات المطر
المبدأ: انقل خط المسح الأخير للرسومات المؤقتة إلى الخط الأول إلى آخر خط المسح الضوئي من صورة نقطية مرئية بالتسلسل ، مما يسمح لخط المسح هذا بترك تتبعه على الشاشة. بعد ذلك ، يتم نقل خط المسح قبل الأخير للرسومات المؤقتة إلى خطوط المسح الضوئية قبل الأخيرة من صورة نقطية مرئية بالتسلسل. وهلم جرا لخطوط المسح المتبقية.
خوارزمية البرنامج:
الإجراءات tform1.button3 ؛ من أجل i: = bmpheight down to 1 do for j: = 1 to i do inching newbmp.canvas.copyrect (rect (0 ، J-1 ، bmpwidth ، j) ، image1.canvas ، rect (0 ، i-1 ، bmpwidth ، I) ؛
5. تأثير الضوضاء
المبدأ: قسّم البيانات الموضوعة في الرسومات المؤقتة إلى عدة مجموعات ، ثم نقلها بالتتابع من المجموعة الأولى إلى المجموعة الأخيرة. الوقت تحرك خط المسح الثاني ، ثم حرك خطوط المسح الثالث والرابع.
خوارزمية البرنامج:
الإجراءات tform1.button6 الارتفاع: = Image1.Height ؛ BMPWidth: = Image1.WIDTH ؛ -1 ، BMPWIDTH ، XCOUNT*J+I) ، Image1.Canvas ، Rect (0 ، xcount*j+i-1 ، bmpwidth ، xcount*j+i) ؛
6. تأثير البناء
المبدأ: إنه تباين في تأثير قطرة المطر.
خوارزمية البرنامج:
الإجراءات tform1.button7 (Sender: var) ؛ ؛ i: = bmpheight ؛ ، bmpwidth ، i) ؛ نهاية؛
خاتمة
تم تمرير جميع تأثيرات عرض الرسوم أعلاه على الكمبيوتر. إنه يعمل بشكل رائع.
تنفيذ مكبر الصوت باستخدام دلفي
أضف مكونين توقيت إلى النموذج. يحتوي مكون TIMAGE الآخر على خاصية اسمه على Image2 ، والذي يعرض الصورة الموسعة.
جوهر هذا المثال هو وظيفة التمدد.
الإجراء tform1.image1mouseMove (المرسل: tobject ؛ Shift: TshiftState ؛ x ، y: integer) ؛ structblt (image2.canvas.handle ، 0،0 ، image2.width ، image2.height ، image1.canvas.handle ، y- y- 20،40،40 ، srccopy) ؛ screen.cursors [1]: = loadcursorfromfile ('magefy.cur') ؛
سيقوم البرنامج أولاً بالاتصال بوظيفة StretchBlt ، واستخدم الموضع الحالي للماوس كنقطة مركزية ، وتحديد الصورة الجزئية على مكون Image1 بطول جانبي 40 ، وتوسيع الصورة الجزئية إلى مكون Image2. ثم قم بتحديث عرض مكون Image2 عن طريق استدعاء طريقة التحديث لمكون Image2. وأخيرا اضبط مؤشر الماوس على الشكل الجديد.
رمز البرنامج هو كما يلي:
UNIT1 ؛ InterfaceSeSwindows ، الرسائل ، sysutils ، المتغيرات ، الفئات ، الرسومات ، النماذج ، الحوار ، extctrls ، stdctrls ؛ type tform1 = class (tform) Image1: timage ؛ ؛ formmousemove (المرسل: TOBJECT ؛ Shift: tshiftState ؛ ؛ Shift: tshiftstate ؛ x ، y: integer) ؛ inctretchblt (Image2.Canvas.Handle ، 0،0 ، Image2 ، image2.height ، image1.canvas.handle ، x-20 ، y-20،40،40 ، srccopy) ؛ ]: = loadCursorFromFile ('magefy.cur') ؛ Self.Cursor: = 1 ؛ end ؛ الإجراء tform1.formmousemove (المرسل: TOBJECT ؛ Shift: .
احفظ الملف ثم اضغط على مفتاح F9 لتشغيل البرنامج وسيتم تشغيل البرنامج.
يعد مكبر الصور وظيفة أساسية لبرنامج عرض الصور الممتاز.
آمل أن تكون هذه المقالة مفيدة لبرمجة دلفي للجميع.