// Eine Bitmap wird
zu einem Zylinder geformt. Dabei muss das Bild
// Variante 1 type PColor = ^TColor; var r, g, b: Byte; bild, spalte: TBitmap; dunkel1, dunkel2, schatten: byte; rx, ry, wlo, wro, wlu, wru, diff: integer; step_i, step_a, schattierung: single; procedure TForm1.FormCreate(Sender: TObject); begin bild := TBitmap.create; spalte := TBitmap.create; spalte.pixelformat := pf24bit; spalte.width := 1; end; procedure TForm1.FormDestroy(Sender: TObject); begin spalte.free; bild.free; end; procedure makespalte(x, hoch: integer; dkl: single; p, v: boolean); var y, z, step: integer; pb, ps: PBytearray; function SetByte(i: integer): byte; asm CMP EAX, 255 JG @MAX CMP EAX, 0 JGE @OK MOV EAX, 0 JMP @OK @MAX: MOV EAX,255 @OK: end; begin x := x * 3; z := ord(not v); for y := 0 to hoch do begin pb := bild.scanline[y]; ps := spalte.scanline[y]; step := trunc(dkl + y * step_i * z); if v or not p then begin ps[0] := setbyte(pb[x] - step); ps[1] := setbyte(pb[x + 1] - step); ps[2] := setbyte(pb[x + 2] - step); end else begin ps[0] := b; ps[1] := g; ps[2] := r; end; end; end; procedure go(x0, y0: integer; cnv: TCanvas; p, v: boolean); var x, y, rx2, ry2, F, Fx, Fy, yy, ryy, rxx, k, h: integer; xx: single; begin h := pred(bild.height); if not v then begin wlo := round(bild.width / 4) + diff; wro := round(bild.width / 4); wru := round(bild.width * 3 / 4); end else begin wlo := 0; wro := pred(bild.width); wru := trunc(bild.width / 2); end; wlu := wru - diff; rx2 := rx * rx; ry2 := ry * ry; inc(x0, rx); inc(y0, ry); F := Round(ry2 - rx2 * ry + 0.25 * rx2); rxx := rx2 + rx2; Fx := 0; Fy := rxx * ry; x := 0; y := ry; ryy := ry2 + ry2; k := ry * 2; // hinten Mitte: makespalte(wlo, k, dunkel1, p, false); bitblt(cnv.handle, x0 - x, y0 - y, 1, k, spalte.canvas.handle, 0, 0, srcCopy); // vorn Mitte: makespalte(wlu, h, 0, p, true); bitblt(cnv.handle, x0 + x, y0 + y, 1, h, spalte.canvas.handle, 0, 0, srcCopy); while Fx < Fy do begin if F >= 0 then begin dec(y); Fy := Fy - rxx; F := F - Fy; end; inc(x); Fx := Fx + ryy; F := F + Fx + ry2; // hinten links (Innenteil) makespalte(wlo, k, dunkel1, p, false); inc(wlo); bitblt(cnv.handle, x0 - x, y0 - y, 1, k, spalte.canvas.handle, 0, 0, srcCopy); // hinten rechts (Innenteil) makespalte(wro, k, dunkel1, p, false); dec(wro); bitblt(cnv.handle, x0 + x, y0 - y, 1, k, spalte.canvas.handle, 0, 0, srcCopy); // vorn links (Innenteil) makespalte(wlu, h, schattierung, p, true); dec(wlu); bitblt(cnv.handle, x0 - x, y0 + y, 1, h, spalte.canvas.handle, 0, 0, srcCopy); // vorn rechts (Innenteil) makespalte(wru, h, schattierung, p, true); inc(wru); bitblt(cnv.handle, x0 + x, y0 + y, 1, h, spalte.canvas.handle, 0, 0, srcCopy); schattierung := schattierung + step_a; end; xx := x + 0.5; yy := pred(y); F := Round(ry2 * xx * xx + rx2 * yy * yy - rx2 * ry2); while y > 0 do begin if F <= 0 then begin inc(x); Fx := Fx + ryy; F := F + Fx; end; dec(y); Fy := Fy - rxx; F := F + rx2 - Fy; // hinten links (Außenteil) makespalte(wlo, k, dunkel1, p, false); inc(wlo); bitblt(cnv.handle, x0 - x, y0 - y, 1, k, spalte.canvas.handle, 0, 0, srcCopy); // hinten rechts (Außenteil) makespalte(wro, k, dunkel1, p, false); dec(wro); bitblt(cnv.handle, x0 + x, y0 - y, 1, k, spalte.canvas.handle, 0, 0, srcCopy); // vorn links (Außenteil) makespalte(wlu, h, schattierung, p, true); dec(wlu); bitblt(cnv.handle, x0 - x, y0 + y, 1, h, spalte.canvas.handle, 0, 0, srcCopy); // vorn rechts (Außenteil) makespalte(wru, h, schattierung, p, true); inc(wru); bitblt(cnv.handle, x0 + x, y0 + y, 1, h, spalte.canvas.handle, 0, 0, srcCopy); schattierung := schattierung + step_a; end; end; function DrawZylinder(vari: boolean; x, y: integer; cnv: TCanvas; pc: PColor; doit: boolean = true): TPoint; const teiler = 4.21; var f: boolean; i, r2: integer; function mass: TPoint; begin result := point(succ(rx * 2), pred(bild.height + r2)); end; begin result := point(0, 0); if (bild.width < 50) or (bild.height < bild.width div 6) then exit; try rx := trunc(bild.width / teiler); ry := round(rx / 3); r2 := ry + ry; if not doit then result := mass else begin bild.pixelformat := pf24bit; if dunkel1 > dunkel2 then begin i := dunkel1; dunkel1 := dunkel2; dunkel2 := i; end; step_i := (dunkel2 - dunkel1) / r2; schattierung := 0; if schatten = 0 then step_a := 0 else step_a := schatten / (rx + rx); if pc <> nil then begin b := getbvalue(pc^); g := getgvalue(pc^); r := getrvalue(pc^); f := true; end else f := false; spalte.height := bild.height; diff := bild.width - trunc(rx * teiler); go(x, y, cnv, f, vari); result := mass; end; except end; end; function CalculateZylinder: TPoint; begin result := DrawZylinder(false, 0, 0, nil, nil, false); end; // -- Beispielaufrufe -- // Beispiel 1 // Bild hinten sichtbar (Röhre offen) procedure TForm1.Button1Click(Sender: TObject); var pkt: TPoint; variante: boolean; begin variante := True; dunkel1 := 40; dunkel2 := 40; schatten := 0; bild.loadfromfile('d:\bilder\Test.bmp'); pkt := DrawZylinder(variante, 50, 10, Canvas, nil); if pkt.y = 0 then showmessage('Verarbeitung war nicht möglich!') else begin label1.caption := 'Zylinderhöhe: ' + inttostr(pkt.y) + ' Pixel'; label2.caption := 'Zylinderbreite: ' + inttostr(pkt.x) + ' Pixel'; end; end; // Beispiel 2 // Bild hinten nicht sichtbar (Röhre geschlossen), // wird durch Angabe einer Farbe erreicht procedure TForm1.Button2Click(Sender: TObject); var f: TColor; begin f := clgreen; schatten := 0; bild.loadfromfile('d:\bilder\Test.bmp'); if DrawZylinder(true, 250, 10, Canvas, @f).y = 0 then showmessage('Fehler bei der Verarbeitung!'); end; // Beispiel 3 // Röhre wird innen nach unten // und außen zum Rand hin dunkler procedure TForm1.Button3Click(Sender: TObject); begin dunkel1 := 0; dunkel2 := 200; schatten := 180; bild.loadfromfile('d:\bilder\Test.bmp'); if DrawZylinder(true, 450, 10, Canvas, nil).y = 0 then showmessage('Fehler bei der Verarbeitung!'); end; // Beispiel 4 // nur Abmaße der Röhre ermitteln ohne sie zu zeichnen procedure TForm1.Button4Click(Sender: TObject); var pkt: TPoint; begin bild.loadfromfile('d:\bilder\Test.bmp'); pkt := CalculateZylinder; if pkt.y = 0 then showmessage('Ermittlung war nicht möglich!') else showmessage('Zylinderhöhe: ' + inttostr(pkt.y) + ' Pixel'#13#10 + 'Zylinderbreite: ' + inttostr(pkt.x) + ' Pixel'); end; // Beispiel 5 // die Röhre wird doppelt so breit wie bei den anderen Beispielen, // dafür ist das komplette Bild vorn zu sehen procedure TForm1.Button5Click(Sender: TObject); var b: TBitmap; begin bild.loadfromfile('d:\bilder\Test.bmp'); b := TBitmap.create; with b, canvas do begin width := bild.width * 2; height := bild.height; brush.color := clgreen; fillrect(cliprect); draw(bild.width div 2, 0, bild); end; bild.assign(b); b.free; dunkel1 := 0; dunkel2 := 100; schatten := 200; if DrawZylinder(true, 650, 10, Canvas, nil).y = 0 then showmessage('Fehler bei der Verarbeitung!'); end; //----------------------------------------------------------------- // Variante 2 // Wer auf Abdunkeln, Größenbestimmung und Schließen der Röhre // sowie auf die Variation (siehe Variante "vari") verzichten kann, // für den ist der nachfolgende einfache Code bestimmt // (die erzeugte Röhre entspricht dem Beispiel 1). var bild: TBitmap; procedure TForm1.FormCreate(Sender: TObject); begin bild := TBitmap.create; end; procedure TForm1.FormDestroy(Sender: TObject); begin bild.free; end; procedure Zylinder(cnv: TCanvas; x0, y0: integer); const teiler = 4.21; var rx, ry, rx2, ry2, rx4, ry4, F, Fx, Fy, x, y, yy, diff, h, k, wlo, wro, wlu, wru: integer; xx: single; procedure Teil; begin bitblt(cnv.handle, x0 - x, y0 - y, 1, k, bild.canvas.handle, wlo, 0, srcCopy); inc(wlo); bitblt(cnv.handle, x0 + x, y0 - y, 1, k, bild.canvas.handle, wro, 0, srcCopy); dec(wro); bitblt(cnv.handle, x0 - x, y0 + y, 1, h, bild.canvas.handle, wlu, 0, srcCopy); dec(wlu); bitblt(cnv.handle, x0 + x, y0 + y, 1, h, bild.canvas.handle, wru, 0, srcCopy); inc(wru); end; begin h := pred(bild.height); rx := trunc(bild.width / teiler); ry := round(rx / 3); rx2 := rx * rx; ry2 := ry * ry; rx4 := rx2 + rx2; ry4 := ry2 + ry2; F := Round(ry2 - rx2 * ry + 0.25 * rx); Fx := 0; Fy := rx4 * ry; x := 0; y := ry; k := ry * 2; diff := bild.width - trunc(rx * teiler); wlo := 0; wro := pred(bild.width); wru := trunc(bild.width / 2); wlu := wru - diff; bitblt(cnv.handle, x0, y0 - y, 1, k, bild.canvas.handle, wlo, 0, srcCopy); bitblt(cnv.handle, x0, y0 + y, 1, h, bild.canvas.handle, wlu, 0, srcCopy); while Fx < Fy do begin if F >= 0 then begin dec(y); Fy := Fy - rx4; F := F - Fy; end; inc(x); Fx := Fx + ry4; F := F + Fx + ry2; Teil; end; xx := x + 0.5; yy := pred(y); F := Round(ry2 * xx * xx + rx2 * yy * yy - rx2 * ry2); while y > 0 do begin if F <= 0 then begin inc(x); Fx := Fx + ry4; F := F + Fx; end; dec(y); Fy := Fy - rx4; F := F + rx2 - Fy; Teil; end; end; // Beispielaufruf procedure TForm1.Button1Click(Sender: TObject); begin bild.loadfromfile('c:\bilder\Test.bmp'); Zylinder(canvas, 200, 100); end; |
Zugriffe seit 6.9.2001 auf Delphi-Ecke