// Verschiedene
Farbverläufe.
// Getestet mit D4 unter XP
//
1.
Variante:
Sehr simple Methode um
den Verlauf einer Farbe hin zu
// Schwarz auf einer Zeichenfläche
(TCanvas)
zu realisieren.
procedure verlauf(cnv: TCanvas; Rot, Gruen, Blau, vertikal, dunkler: boolean);
var
stufe, faktor, farbe, richtung: integer;
begin
if not Rot and not Gruen and not Blau then begin
Rot := true;
Gruen := Rot;
Blau := Rot;
end;
with cnv, cnv.cliprect do begin
if vertikal then richtung := (bottom - top) else richtung := (right - left);
faktor := succ(richtung div 256);
for stufe := 0 to 255 do begin
farbe := abs(ord(dunkler) * 255 - stufe);
Brush.Color := RGB(ord(Rot) * farbe, ord(Gruen) * farbe, ord(blau) * farbe);
if vertikal then
FillRect(Rect(0, stufe * faktor, right, succ(stufe) * faktor))
else FillRect(Rect(stufe * faktor, 0, succ(stufe) * faktor, bottom));
end;
end;
end;
//
------------------ Beispiel --------------
// Die Fläche einer Paintbox erhält einen Farbverlauf.
procedure TForm1.FormPaint(Sender: TObject);
begin
verlauf(paintbox1.canvas, true, false, true, false, true); // violett
(* , true, false, false, // rot
, true, true, false, // gelb
, false, false, true, // blau
, false, true, false, // grün
, false, true, true, // blaugrün
, false, false, false, // grau
, true, true, true, // grau *)
end;
//
----------------------------------------------------------------------
// 2.
Variante:
Es
können
zwei Farben und ein Rechteck definiert werden.
procedure DrawGradient(const Canvas: TCanvas; C1, C2: TColor;
X1, Y1, X2, Y2: Integer; Horizontal: Boolean);
var
Y, R, G, B, H, DR, DB, DG: Integer;
RC1, GC1, BC1: Integer;
RC2, GC2, BC2: Integer;
begin
if Y1 > Y2 then begin
Y := Y1;
Y1 := Y2;
Y2 := Y;
end;
if X1 > X2 then begin
Y := X1;
X1 := X2;
X2 := Y;
end;
C1 := ColorToRGB(C1);
C2 := ColorToRGB(C2);
RC1 := GetRValue(C1);
GC1 := GetGValue(C1);
BC1 := GetBValue(C1);
RC2 := GetRValue(C2);
GC2 := GetGValue(C2);
BC2 := GetBValue(C2);
DR := RC2 - RC1;
DG := GC2 - GC1;
DB := BC2 - BC1;
if Horizontal then begin
H := pred(X2 - X1);
for y := 0 to H do
begin
R := Round(RC1 + (DR * Y / H));
G := Round(GC1 + (DG * Y / H));
B := Round(BC1 + (DB * Y / H));
Canvas.Brush.Color := RGB(R, G, B);
Canvas.FillRect(Rect(X1 + Y, Y1, X1 + succ(Y), Y2));
end;
end else begin
H := pred(Y2 - Y1);
for y := 0 to H do
begin
R := Round(RC1 + (DR * Y / H));
G := Round(GC1 + (DG * Y / H));
B := Round(BC1 + (DB * Y / H));
Canvas.Brush.Color := RGB(R, G, B);
Canvas.FillRect(Rect(X1, Y1 + Y, X2, Y1 + succ(Y)));
end;
end;
end;
// ------------------
Beispiel --------------
// Die Fläche einer Form erhält zwei Farbverläufe.
procedure zeichnen;
begin
with Form2 do begin
DrawGradient(canvas, clLime, clRed, 0, 0,
clientwidth div 2, clientheight, true);
DrawGradient(canvas, clLime, clRed, clientwidth div 2,
0, clientwidth, clientheight, false);
end;
end;
procedure TForm2.FormPaint(Sender: TObject);
begin
zeichnen;
end;
procedure TForm2.FormResize(Sender: TObject);
begin
zeichnen;
end;
//
--------------------------------------------------------------------
//
3.
Variante:
Es werden Linien auf eine Zeichenfläche
gezeichnet.
// Man
kann Farbverläufe innerhalb eines Rechtecks mit mehreren Farben
// horizontal oder vertikal erstellen.
type
rgbarray = array[0..2] of byte;
procedure
Farbverlauf(cv: TCanvas; Rect: TRect; horizontal: boolean; c: array of
TColor);
var
x, y, z, stelle, mx, bis, fach, mass: integer;
faktor: double;
a: rgbarray;
b: array of rgbarray;
merkw: integer;
merks: TPenStyle;
merkp: TColor;
begin
mx := high(c);
if mx > 0 then begin
if horizontal then mass := rect.right - rect.left
else mass := rect.bottom - rect.top;
setlength(b, mx + 1);
for x := 0 to mx do begin
c[x] := colortorgb(c[x]);
b[x][0] := getrvalue(c[x]);
b[x][1] := getgvalue(c[x]);
b[x][2] := getbvalue(c[x]);
end;
merkw := cv.Pen.Width;
merks := cv.Pen.Style;
merkp := cv.Pen.Color;
cv.Pen.Width := 1;
cv.Pen.Style := psSolid;
fach := round(mass / mx);
for y := 0 to mx - 1 do begin
if y = mx - 1 then bis := mass - y * fach - 1
else bis := fach;
for x := 0 to bis do begin
stelle := x + y * fach;
if bis = 0 then faktor := 1 else
faktor := x / bis;
for z := 0 to 2 do
a[z] := trunc(b[y][z] + ((b[y + 1][z] - b[y][z]) * faktor));
cv.Pen.Color := RGB(a[0], a[1], a[2]);
if horizontal then begin
cv.MoveTo(rect.left + stelle, Rect.Top);
cv.LineTo(rect.left + stelle, Rect.Bottom);
end else begin
cv.MoveTo(rect.left, rect.top + stelle);
cv.LineTo(rect.right, rect.top + stelle);
end;
end;
end;
b := nil;
cv.Pen.Width := merkw;
cv.Pen.Style := merks;
cv.Pen.Color := merkp;
end
else showmessage('Es müssen mindestens 2 Farben angegeben werden');
end;
//
------------------ Beispiel --------------
// ein Rechteck
wird von links nach rechts mit 6 Farben gefüllt
procedure TForm1.Button3Click(Sender: TObject);
var links, oben, rechts, unten: integer;
begin
links := 10;
oben := 10;
rechts := 160;
unten := 100;
canvas.pen.color := clblack;
canvas.brush.style := bsclear;
canvas.rectangle(links, oben, rechts, unten);
farbverlauf(canvas, rect(links + 1, oben + 1, rechts - 1, unten - 1), true,
[clred, clwhite, clblack, clyellow, clgreen, claqua]);
end;
//
---------------------------------------------------------------------------
//
4. Variante:
Um mehrere Verläufe zu benutzen und möglichst
Flackern
// zu vermeiden, wird ein Bitmap zu Hilfe genommen. An dessen oberen
Rand
// verlaufen andere Farben als am unteren Rand und auch von oben nach
unten
// wird ein einfacher Verlauf realisiert.
type
rgbarray = array[0..2] of byte;
argbarray = array of rgbarray;
var bmp: TBitmap;
procedure TForm1.FormCreate(Sender: TObject);
begin
bmp := TBitmap.create;
bmp.pixelformat := pf24bit;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
bmp.free;
end;
procedure farbverlauf
(dc: HDC; x, y, breit, hoch: integer; oben, unten: array of TColor);
var
b1, b2: rgbarray;
o, u, w, h, j, c, z, fo: integer;
ao: argbarray;
au: argbarray;
p: PBytearray;
procedure rgbermitteln(at: array of TColor; ar: argbarray; k: integer);
var i: integer;
begin
for i := 0 to k do begin
at[i] := colortorgb(at[i]);
ar[i][2] := getrvalue(at[i]);
ar[i][1] := getgvalue(at[i]);
ar[i][0] := getbvalue(at[i]);
end;
end;
function rechnen(ar: argbarray): byte;
begin
result := trunc(ar[j][z] + (ar[j + 1][z] - ar[j][z]) * (w / fo));
end;
begin
o := high(oben);
u := high(unten);
if o = u then begin
if o > 0 then begin
bmp.width := breit;
bmp.height := hoch;
setlength(ao, o + 1);
setlength(au, u + 1);
rgbermitteln(oben, ao, o);
rgbermitteln(unten, au, u);
fo := trunc(breit / o + 1) * 3;
for h := 0 to hoch - 1 do begin
p := bmp.scanline[h];
for j := 0 to o do begin
w := 0;
while w <= fo - 1 do begin
c := j * fo + w;
if c <= breit * 3 - 1 then begin
for z := 0 to 2 do begin
b1[z] := rechnen(ao);
b2[z] := rechnen(au);
p[c + z] := trunc(b1[z] + (b2[z] - b1[z]) * (h / hoch));
end;
end;
inc(w, 3);
end;
end;
end;
bitblt(dc, x, y, breit, hoch, bmp.canvas.handle, 0, 0, srccopy);
end else showmessage('Es müssen mindestens zwei Farben angegeben werden!');
end else
showmessage('Die Anzahl der Farben muss oben und unten gleich sein!');
end;
//
------------------ Beispiel --------------
// Ein Rechteck von 120 Pixel Breite und 120 Pixel
Höhe wird mit
// einem Mehrfach-Farbverlauf gefüllt
procedure TForm1.Button3Click(Sender: TObject);
begin
farbverlauf(canvas.handle, 20, 30, 120, 120,
[clblack, claqua, clblack, clfuchsia, clblack, clyellow, clblack],
[clblack, clyellow, clblack, cllime, clblack, clred, clblack]);
end;
//
-------------------------------------------------------------------------
//
5. Variante:
Wer nur einen einfachen Verlauf zwischen zwei
Farben benötigt,
// kann den folgenden Code verwenden, welcher die Farben mittels
API-Aufruf
// einem Bitmap zuweist. Zusätzlich zu den vier Verlaufsrichtungen kann
die
// Dominanz der zuerst benannten Farbe gesteuert werden, wodurch
unterschiedlich
// starke Verläufe realisiert werden.
type
Richtung = (VonLinksNachRechts, VonRechtsNachLinks,
VonObenNachUnten, VonUntenNachOben);
procedure verlaufx(bm: TBitmap; wdth, hght: integer;
Start, Ende: TColor; Dominanz: Single; wie: Richtung);
var
tb: tagBITMAP;
i, j: integer;
s: Single;
CStep, TmpC: array[0..2] of Single;
ColorS, ColorE: array[0..2] of byte;
BmBitsx: array of array[0..3] of byte;
function CalcStep(von, bis: integer): Single;
begin
if von > bis then begin
Result := von - bis;
if Result <> 0 then
Result := -(Result / (wdth * Dominanz))
end else begin
Result := bis - von;
if Result <> 0 then
Result := Result / (wdth * Dominanz);
end;
end;
procedure quad(wh: integer);
begin
BmBitsx[i + j * wh][3] := 0;
BmBitsx[i + j * wh][2] := trunc(TmpC[0]);
BmBitsx[i + j * wh][1] := trunc(TmpC[1]);
BmBitsx[i + j * wh][0] := trunc(TmpC[2]);
end;
procedure steps;
var x: integer;
begin
for x := 0 to 2 do
TmpC[x] := TmpC[x] + CStep[x];
end;
begin
if (wdth < 2) or (hght < 2) then raise exception.create('Bitmap-Abmaße zu niedrig');
if ord(wie) < 2 then s := wdth / 10 else s := hght / 10;
if (dominanz < 1) or (dominanz > s) then
raise exception.create('Dominanz überschreitet Toleranzgrenze');
Start := ColorToRGB(Start);
Ende := ColorToRGB(Ende);
CopyMemory(@ColorS, @Start, 3);
CopyMemory(@ColorE, @Ende, 3);
for i := 0 to 2 do begin
CStep[i] := CalcStep(ColorS[i], ColorE[i]);
TmpC[i] := ColorS[i];
end;
setlength(BmBitsx, wdth * hght);
case wie of
VonLinksNachRechts: begin
for i := 0 to wdth - 1 do begin
steps;
for j := 0 to hght - 1 do
quad(wdth);
end;
end;
VonUntenNachOben: begin
for j := wdth - 1 downto 0 do begin
steps;
for i := 0 to hght - 1 do
quad(hght);
end;
end;
VonObenNachUnten: begin
for j := 0 to wdth - 1 do begin
steps;
for i := 0 to hght - 1 do
quad(hght);
end;
end;
else begin
for i := wdth - 1 downto 0 do begin
steps;
for j := 0 to hght - 1 do
quad(wdth);
end;
end;
end;
with tb do begin
bmtype := 0;
bmwidth := wdth;
bmheight := hght;
bmwidthbytes := wdth * 4;
bmplanes := 1;
bmbitspixel := 32;
bmbits := bmbitsx;
end;
bm.handle := CreateBitmapIndirect(tb);
BmBitsx := nil;
end;
//
------------------ Beispiel --------------
// Zwei Farbverläufe mit unterschiedlicher
Dominanz der Farbe Gelb:
procedure TForm1.Button3Click(Sender: TObject);
var Bitmap: TBitmap;
begin
Bitmap := TBitmap.create;
verlaufx(Bitmap, 80, 40, clyellow, clblue, 1, VonLinksNachRechts);
canvas.draw(310, 10, Bitmap);
verlaufx(Bitmap, 80, 40, clyellow, clblue, 1.4, VonLinksNachRechts);
canvas.draw(310, 55, Bitmap);
Bitmap.free;
end;
//
---------------------------------------------------------------------------
//
6. Variante:
Ein Farbverlauf unter Zuhilfenahme des "GDI".
type
TForm1 = class(TForm)
procedure FormPaint(Sender: TObject);
procedure FormResize(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
function GradientFill(hdc: HDC; pVertex: PTriVertex;
dwNumVertex: DWORD; pMesh: Pointer;
dwNumMesh: DWORD; dwMode: DWORD): Boolean; stdcall;
external 'gdi32.dll' name 'GdiGradientFill';
implementation
{$R *.DFM}
procedure RechteckVerlauf(DC: HDC; x1, y1, x2, y2: integer; von, nach: TColor;
horizontal: boolean);
type
TVertex = packed record
x, y: Integer;
rot, gruen, blau, Alpha: Word;
end;
const
VertexCount = 2;
var
Vertex: array[0..VertexCount - 1] of TVertex;
TVRect: TGradientRect;
richtung: Cardinal;
begin
von := ColorToRGB(von);
nach := ColorToRGB(nach);
if horizontal then richtung := GRADIENT_FILL_RECT_H
else richtung := GRADIENT_FILL_RECT_V;
Vertex[0].x := x1;
Vertex[0].y := y1;
Vertex[0].rot := getrvalue(von) shl 8;
Vertex[0].gruen := getgvalue(von) shl 8;
Vertex[0].blau := getbvalue(von) shl 8;
Vertex[0].Alpha := 0;
Vertex[1].x := x2;
Vertex[1].y := y2;
Vertex[1].rot := getrvalue(nach) shl 8;
Vertex[1].gruen := getgvalue(nach) shl 8;
Vertex[1].blau := getbvalue(nach) shl 8;
Vertex[1].Alpha := 0;
with TVREct do begin
UpperLeft := 0;
LowerRight := 1;
end;
GradientFill(DC, @Vertex[0], VertexCount, @TVREct, 1, richtung);
end;
//
------------------ Beispiel --------------
procedure TForm1.FormPaint(Sender: TObject);
begin
RechteckVerlauf(canvas.handle, 0, 0, clientwidth, clientheight,
$88FF, clblue, true);
end;
procedure TForm1.FormResize(Sender: TObject);
begin
refresh;
end;
//
-------------------------------------------------------------------------
//
7. Variante:
Ein dreifach Farbverlauf in einem Dreieck mittels
"GDI".
type
TForm1 = class(TForm)
procedure FormPaint(Sender: TObject);
procedure FormResize(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
function GradientFill(hdc: HDC; pVertex: PTriVertex;
dwNumVertex: DWORD; pMesh: Pointer;
dwNumMesh: DWORD; dwMode: DWORD): Boolean; stdcall;
external 'gdi32.dll' name 'GdiGradientFill';
implementation
{$R *.DFM}
procedure DreieckVerlauf(DC: HDC; x1, y1, x2, y2, x3, y3: integer;
eins, zwei, drei: TColor);
type
TVertex = packed record
x, y: Integer;
rot, gruen, blau, Alpha: Word;
end;
const
VertexCount = 3;
var
Vertex: array[0..VertexCount - 1] of TVertex;
Triangle: TGradientTriangle;
begin
eins := ColorToRGB(eins);
zwei := ColorToRGB(zwei);
drei := ColorToRGB(drei);
Vertex[0].x := x1;
Vertex[0].y := y1;
Vertex[0].rot := getrvalue(eins) shl 8;
Vertex[0].gruen := getgvalue(eins) shl 8;
Vertex[0].blau := getbvalue(eins) shl 8;
Vertex[0].Alpha := 0;
Vertex[1].x := x2;
Vertex[1].y := y2;
Vertex[1].rot := getrvalue(zwei) shl 8;
Vertex[1].gruen := getgvalue(zwei) shl 8;
Vertex[1].blau := getbvalue(zwei) shl 8;
Vertex[1].Alpha := 0;
Vertex[2].x := x3;
Vertex[2].y := y3;
Vertex[2].rot := getrvalue(drei) shl 8;
Vertex[2].gruen := getgvalue(drei) shl 8;
Vertex[2].blau := getbvalue(drei) shl 8;
Vertex[2].Alpha := 0;
Triangle.Vertex1 := 0;
Triangle.Vertex2 := 1;
Triangle.Vertex3 := 2;
GradientFill(DC, @Vertex[0], VertexCount, @TRiangle, 1, GRADIENT_FILL_TRIANGLE);
end;
// ------------------
Beispiel --------------
procedure TForm1.FormPaint(Sender: TObject);
begin
DreieckVerlauf(canvas.handle, 0, 0, 0, clientheight, clientwidth,
clientheight div 2, clblue, cllime, clred);
end;
procedure TForm1.FormResize(Sender: TObject);
begin
refresh;
end;
//
----------------------------------------------------------------------------
//
8. Variante:
Der folgende Code erlaubt einen Farbverlauf bis
45° nach
// rechts oder links zu neigen. Es können bis zu 8 Farben verwendet
werden.
procedure farbverlauf
(dc: HDC; x, y, breit, hoch: integer; ar: array of TColor; Winkel: Single);
var
bmp: TBitmap;
o, w, h, j, c, z, v, br, fo: integer;
ao: array of array[0..2] of byte;
p: PBytearray;
procedure rgbermitteln;
var
i: integer;
begin
for i := 0 to o do begin
ar[i] := colortorgb(ar[i]);
ao[i][2] := getrvalue(ar[i]);
ao[i][1] := getgvalue(ar[i]);
ao[i][0] := getbvalue(ar[i]);
end;
for i := 0 to 2 do
ao[o + 1][i] := ao[0][i];
end;
function rechnen: byte;
begin
result := trunc(ao[j][z] + (ao[j + 1][z] - ao[j][z]) * (w / fo));
end;
begin
if (breit > 1) and (hoch > 1) then begin
if (Winkel >= -45) and (Winkel <= 45) then begin
o := high(ar);
if (o > 0) and (o < 8) then begin
bmp := TBitmap.create;
bmp.pixelformat := pf24bit;
Winkel := -Winkel / 45;
fo := round(breit / o + 1.3333) * 3;
bmp.width := breit;
bmp.height := hoch;
br := breit * 3;
setlength(ao, o + 2);
rgbermitteln;
for h := 0 to hoch - 1 do begin
p := bmp.scanline[h];
for j := 0 to o do begin
w := 0;
while w < fo do begin
c := j * fo + w + round(h * Winkel) * 3;
v := br + fo + o * 3;
while c < 0 do inc(c, v);
while c >= v do dec(c, v);
if c < br then
for z := 0 to 2 do
p[c + z] := rechnen;
inc(w, 3);
end;
end;
end;
bitblt(dc, x, y, breit, hoch, bmp.canvas.handle, 0, 0, srccopy);
bmp.free;
end else showmessage('Anzahl der Farben ungültig!');
end else showmessage('Der Winkel muss zwischen -45.0 und +45.0 liegen!');
end else showmessage('Abmaße zu gering!');
end;
// ------------------ Beispiel --------------
procedure TForm1.Button2Click(Sender: TObject);
begin
farbverlauf(canvas.handle, 10, 20, 75, 80, [$330000, $FFE080,
$330000, $FFE080], 33.3);
end;
//
----------------------------------------------------------------------------
//
9. Variante:
Zwei Farben verlaufen stufenweise.
procedure StufenVerlauf(cnv: TCanvas; F1, F2: TColor; stufen: byte;
X1, Y1, X2, Y2: integer; horizontal: boolean);
var
r1, g1, b1: byte;
v, u, f, i, h: integer;
r, g, b, dr, dg, db: single;
begin
if stufen < 2 then stufen := 2;
if Y1 > Y2 then begin
i := Y1;
Y1 := Y2;
Y2 := i;
end;
if X1 > X2 then begin
i := X1;
X1 := X2;
X2 := i;
end;
if horizontal then
h := X2 - X1 else
h := Y2 - Y1;
if stufen > h then stufen := h;
v := pred(stufen);
f := round(h / stufen);
F1 := ColorToRGB(F1);
F2 := ColorToRGB(F2);
r1 := getrvalue(F1);
g1 := getgvalue(F1);
b1 := getbvalue(F1);
dr := (getrvalue(F2) - r1) / v;
dg := (getgvalue(F2) - g1) / v;
db := (getbvalue(F2) - b1) / v;
for i := 0 to v do begin
with cnv do begin
r := r1 + i * dr;
g := g1 + i * dg;
b := b1 + i * db;
brush.color := RGB(round(r), round(g), round(b));
if horizontal then begin
if i = v then u := X2 else
u := X1 + succ(i) * f;
fillrect(rect(X1 + i * f, Y1, u, Y2));
end else begin
if i = v then u := Y2 else
u := Y1 + succ(i) * f;
fillrect(rect(X1, i * f + Y1, X2, u));
end;
end;
end;
end;
// ------------------ Beispiel --------------
procedure TForm1.Button2Click(Sender: TObject);
begin
canvas.rectangle(29, 29, 101, 101);
stufenverlauf(canvas, clyellow, clpurple, 7, 30, 30, 100, 100, false);
end;
//
----------------------------------------------------------------------------
//
10. Variante:
Zwei Farben verlaufen stufenweise waagerecht als
auch
// senkrecht. Dadurch ergibt sich ein mosaikartiger diagonaler
Farbverlauf.
// Da der Aufbau langsam von statten geht, wird eine Bitmap eingesetzt.
procedure MosaikVerlauf(bm: TBitmap; F1, F2: TColor;
stufewaag, stufesenk: byte);
var
r1, g1, b1: byte;
vh, vw, uh, uw, fh, fw, i, j: integer;
rj, gj, bj, ri, bi, gi, drh, dgh, dbh, drw, dgw, dbw: single;
begin
if (bm.height > 1) and (bm.width > 1) then begin
if (stufesenk > bm.height) or (stufesenk < 2) then stufesenk := bm.height;
if (stufewaag > bm.width) or (stufewaag < 2) then stufewaag := bm.width;
vh := pred(stufesenk);
vw := pred(stufewaag);
fh := round(bm.height / stufesenk);
fw := round(bm.width / stufewaag);
F1 := ColorToRGB(F1);
F2 := ColorToRGB(F2);
r1 := getrvalue(F1);
g1 := getgvalue(F1);
b1 := getbvalue(F1);
drh := (getrvalue(F2) - r1) / vh;
dgh := (getgvalue(F2) - g1) / vh;
dbh := (getbvalue(F2) - b1) / vh;
drw := (getrvalue(F2) - r1) / vw;
dgw := (getgvalue(F2) - g1) / vw;
dbw := (getbvalue(F2) - b1) / vw;
for i := 0 to vw do begin
ri := r1 + i * drw;
gi := g1 + i * dgw;
bi := b1 + i * dbw;
if i = vw then uw := bm.width else
uw := succ(i) * fw;
for j := 0 to vh do begin
with bm.canvas do begin
rj := r1 + j * drh;
gj := g1 + j * dgh;
bj := b1 + j * dbh;
brush.color := RGB(round((rj + ri) / 2), round((gj + gi) / 2),
round((bj + bi) / 2));
if j = vh then uh := bm.height else
uh := succ(j) * fh;
fillrect(rect(i * fw, j * fh, uw, uh));
end;
end;
end;
end;
end;
// ------------------
Beispiel --------------
procedure TForm1.Button2Click(Sender: TObject);
var bm: TBitmap;
begin
bm := TBitmap.create;
bm.width := 70;
bm.height := 70;
mosaikverlauf(bm, cllime, clred, 5, 5);
canvas.draw(30, 30, bm);
bm.free;
end;
//
----------------------------------------------------------------------------
//
11. Variante:
(Gespiegelte Verläufe) Der Code erlaubt neben
einem einfachen
// diagonalen Verlauf drei gespiegelte Verläufe: Dreieck, Diamant und
Linse.
type
shp = (Diagonal, Dreieck, Diamant, Linse);
procedure verlauf(bm: TBitmap; farbe1, farbe2: TColor; art: shp);
var
x, y, h, w, w3: integer;
p: pBytearray;
ri, gi, bi: byte;
ra, ga, ba: word;
rd, gd, bd, a, d: single;
begin
bm.pixelformat := pf24bit;
if art = Diamant then
h := bm.height shr 1
else h := bm.height - 1;
if art <> Diagonal then
w := bm.width shr 1 else
w := bm.width;
w3 := w * 3;
farbe1 := colortorgb(farbe1);
farbe2 := colortorgb(farbe2);
ra := getrvalue(farbe1);
ga := getgvalue(farbe1);
ba := getbvalue(farbe1);
ri := getrvalue(farbe2);
gi := getgvalue(farbe2);
bi := getbvalue(farbe2);
rd := ri - ra;
gd := gi - ga;
bd := bi - ba;
inc(ra, ra);
inc(ga, ga);
inc(ba, ba);
for y := 0 to h do begin
p := bm.scanline[y];
a := y / h;
if art = Linse then a := sin(pi * a);
x := 0;
while x < w3 do begin
d := a + x / w3;
p[x] := trunc((ba + bd * d) / 2);
p[x + 1] := trunc((ga + gd * d) / 2);
p[x + 2] := trunc((ra + rd * d) / 2);
inc(x, 3);
end;
end;
if art <> Diagonal then
stretchblt(bm.canvas.handle, w, 0, w + 1, h + 1,
bm.canvas.handle, w - 1, 0, -w, h, SRCCOPY);
if art = Diamant then
stretchblt(bm.canvas.handle, 0, h + 1, bm.width, h,
bm.canvas.handle, 0, h, bm.width, -h, SRCCOPY);
end;
// ------------------
Beispiel --------------
procedure TForm1.Button2Click(Sender: TObject);
var
bm: TBitmap;
begin
bm := TBitmap.create;
bm.width := 100;
bm.height := 75;
verlauf(bm, clblue, $80FF, Dreieck);
canvas.draw(10, 10, bm);
verlauf(bm, clblue, $80FF, Diamant);
canvas.draw(120, 10, bm);
verlauf(bm, clblue, $80FF, Linse);
canvas.draw(230, 10, bm);
bm.free;
end;
//
----------------------------------------------------------------------------
//
12. Variante:
Erstellen eines radialen Verlaufes. Wird eine
Hintergrundfarbe
// angegeben, erzeugt das eine Ellipse. Ansonsten wird das komplette
Rechteck
// ausgefüllt.
procedure DrawR(bm: TBitmap; c1, c2: TColor; fw, fh: integer);
var
i, stp: Integer;
R1, G1, B1, R2, G2, B2: Integer;
Rx, Gx, Bx: byte;
begin
with bm, Canvas do begin
c1 := ColorToRGB(c1);
c2 := ColorToRGB(c2);
R1 := GetRValue(c1);
G1 := GetGValue(c1);
B1 := GetBValue(c1);
R2 := GetRValue(c2);
G2 := GetGValue(c2);
B2 := GetBValue(c2);
if width > height then
stp := height div 2 + fh else
stp := width div 2 + fw;
for i := 1 to stp do begin
Rx := Round(R1 - ((R1 - R2) / stp) * i);
Gx := Round(G1 - ((G1 - G2) / stp) * i);
Bx := Round(B1 - ((B1 - B2) / stp) * i);
Brush.Color := RGB(Rx, Gx, Bx);
Pen.Color := Brush.Color;
Ellipse(i - fw, i - fh, width - i + fw, height - i + fh);
end;
end;
end;
procedure DrawRadial(bm: TBitmap; c1, c2: TColor); overload;
var dm: double;
fw, fh: integer;
begin
with bm do begin
dm := sqrt(sqr(width) + sqr(height));
fw := round((dm - width) / 2) + 2;
fh := round((dm - height) / 2) + 2;
end;
DrawR(bm, c1, c2, fw, fh);
end;
procedure DrawRadial(bm: TBitmap; c1, c2, Hintergrund: TColor); overload;
begin
with bm.Canvas do begin
brush.color := Hintergrund;
fillrect(cliprect);
end;
DrawR(bm, c1, c2, 0, 0);
end;
// -------------------- Beispiel ------------------------
procedure TForm1.Button1Click(Sender: TObject);
var bm: TBitmap;
begin
bm := TBitmap.create;
bm.width := 100;
bm.height := 100;
drawradial(bm, clblack, cllime, Color);
canvas.draw(500, 20, bm);
bm.width := 125;
bm.height := 75;
drawradial(bm, clblack, clRed, Color);
canvas.draw(602, 32, bm);
bm.width := 75;
bm.height := 125;
drawradial(bm, clblack, clYellow);
canvas.draw(730, 5, bm);
bm.free;
end;
//
----------------------------------------------------------------------------
//
13. Variante:
Verlauf Schwarz-Farbe-Schwarz
type
art = (vlHorizontal, vlVertical, vlRadial);
procedure grad(bm: TBitmap; Farbe: TColor; wie: art);
var x, y, z, x3: integer;
x1, x2, y1, y2, sx, sy: single;
r, g, b: byte;
p: pbytearray;
begin
bm.pixelformat := pf24bit;
case wie of
vlHorizontal: begin
x2 := bm.height;
y2 := bm.height;
end;
vlVertical: begin
x2 := bm.width;
y2 := bm.width;
end;
else begin
x2 := bm.width;
y2 := bm.height;
end;
end;
Farbe := ColorToRGB(Farbe);
r := GetRValue(Farbe);
g := GetGValue(Farbe);
b := GetBValue(Farbe);
for y := 0 to bm.height - 1 do begin
p := bm.scanline[y];
for x := 0 to bm.width - 1 do begin
x3 := x * 3;
case wie of
vlHorizontal: begin
x1 := y;
y1 := y;
end;
vlVertical: begin
x1 := x;
y1 := x;
end;
else begin
x1 := x;
y1 := y;
end;
end;
sx := sin(x1 / x2 * pi);
sy := sin(y1 / y2 * pi);
z := trunc(sx * sy * 256);
p[x3] := (z * b) shr 8;
p[x3 + 1] := (z * g) shr 8 ;
p[x3 + 2] := (z * r) shr 8 ;
end;
end;
end;
// ------------- Beispiel --------------------
procedure TForm1.Button2Click(Sender: TObject);
var b: TBitmap;
begin
b := TBitmap.create;
b.width := 80;
b.height := 100;
Grad(b, clLime, vlVertical);
canvas.draw(10, 10, b);
Grad(b, clFuchsia, vlHorizontal);
canvas.draw(100, 10, b);
Grad(b, clAqua, vlRadial);
canvas.draw(190, 10, b);
b.free;
end;
//
----------------------------------------------------------------------------
//
13. Variante:
Verlauf Schwarz-Farbe schräg. procedure grads(bm: TBitmap; Farbe: TColor; blacktop: Boolean);
var
X, y, z, x3: Integer;
srg, x1, yy, sx, sy: single;
r, g, b: Byte;
p: pbytearray;
begin
srg := sqrt(bm.height / bm.width) * 4;
bm.pixelformat := pf24bit;
Farbe := ColorToRGB(Farbe);
r := GetRValue(Farbe);
g := GetGValue(Farbe);
b := GetBValue(Farbe);
for y := 0 to bm.height - 1 do
begin
p := bm.scanline[y];
yy := y * 0.75;
for X := 0 to bm.width - 1 do
begin
x3 := X * 3;
x1 := X + yy;
if not blacktop then
begin
sx := cos(x1 / bm.width * pi / srg);
sy := cos(x1 / bm.width * pi / srg);
end
else
begin
sx := sin(x1 / bm.width * pi / srg);
sy := sin(x1 / bm.width * pi / srg);
end;
z := trunc(sx * sy * 256);
p[x3] := (z * b) shr 8;
p[x3 + 1] := (z * g) shr 8;
p[x3 + 2] := (z * r) shr 8;
end;
end;
end;
// ------------- Beispiel --------------------
|
|
blacktop = False |
blacktop = True |
procedure TForm1.Button1Click(Sender: TObject);
var
b: TBitmap;
begin
b := TBitmap.Create;
b.width := 100;
b.height := 100;
grads(b, clBlue, False);
canvas.draw(50, 50, b);
grads(b, clBlue, True);
canvas.draw(50, 250, b);
b.free;
end;
//
----------------------------------------------------------------------------
//
14. Variante:
Verlauf mehrere Farben auf einem TImage schräg nach links
oder nach
rechts.(Variante von 8. ohne Scanline)
type
Ba = Array [0 .. 2] of Byte;
Schraeg = -45 .. 45;
Aoc = Array of TColor;
var
MyArray: Aoc = [clRed, clBlue, clYellow, clGreen];
function Verlauf(PB: TBitmap; C: Aoc; V: Schraeg): Boolean;
var
X, Y, Z, Stelle, Mx, Bis, Fach, Mass: Integer;
A: Ba;
B: Array of Ba;
W, Faktor, VV: Single;
Rect: TRect;
begin
Result := False;
Mx := High(C);
if Mx > 0 then
try
for X := 0 to Mx do
C[X] := ColorToRGB(C[X]);
W := abs(V);
if PB.Height > PB.Width then
VV := PB.Height / PB.Width
else
VV := PB.Width / PB.Height;
VV := VV * W * 4;
with PB.Canvas do
begin
Rect := cliprect;
Rect.right := Round(Rect.right + VV);
Mass := Rect.right - Rect.Left;
SetLength(B, Mx + 1);
Fach := Round(Mass / Mx);
for X := 0 to Mx do
begin
B[X][0] := GetRValue(C[X]);
B[X][1] := GetGValue(C[X]);
B[X][2] := GetBValue(C[X]);
end;
Pen.Width := 1;
Pen.Style := psSolid;
for Y := 0 to Mx - 1 do
begin
if Y = Mx - 1 then
Bis := Mass - Y * Fach - 1
else
Bis := Fach;
for X := 0 to Bis do
begin
Stelle := Round(X + Y * Fach);
if Bis = 0 then
Faktor := 1
else
Faktor := X / Bis;
for Z := 0 to 2 do
A[Z] := trunc(B[Y][Z] + ((B[Y + 1][Z] - B[Y][Z]) * Faktor));
Pen.Color := RGB(A[0], A[1], A[2]);
if V >= 0 then
begin
MoveTo(Rect.Left + Stelle, Rect.top);
LineTo(Round(Rect.Left + Stelle - VV), Rect.bottom);
end
else
begin
MoveTo(Round(Rect.Left + Stelle - VV), Rect.top);
LineTo(Rect.Left + Stelle, Rect.bottom);
end;
end;
end;
B := nil;
end;
Result := true;
except
end;
end;
// ------------- Beispiel --------------------
|
|
|
|
|
Schraeg
= 0 |
Schraeg
= -20 |
Schraeg
= -45 |
Schraeg
= 5 |
Schraeg
= 45 |
procedure TForm1.FormCreate(Sender: TObject);
begin
With Image1 do
begin
autosize := true;
Left := 50;
top := 50;
with Picture.Bitmap, canvas do
begin
begin
Brush.Color := Form1.Color;
width := 200;
height := 200;
end;
end;
end;
with TrackBar1 do
begin
min := -45;
max := 45;
Position := 0;
end;
TrackBar1Change(Sender);
end;
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
if not Verlauf(Image1.Picture.Bitmap, MyArray, TrackBar1.Position) then
Showmessage('FEHLER');
end;
|