// Getestet mit D4
unter XP // Variante 1: Filter
// Wenn man Bitmaps
einfärben oder tönen
will, geht man am Einfachsten
type aob = array[0..2] of Byte; procedure Kolorieren(Source, Dest: TBitmap; Farbe: TColor; Intensiv: Byte; Filter: boolean); var p: ^aob; Divi: word; hlp: TBitmap; korr: Double; h, w, x: Integer; aos: array[0..2] of Double; procedure rech(i: integer; s: Double); var h: Integer; begin h := Trunc((p^[i] + p^[i] * (s - korr)) / 2); if h > 255 then p^[i] := 255 else if h < 0 then p^[i] := 0 else p^[i] := Byte(h); end; begin hlp := TBitmap.create; hlp.pixelformat := pf24bit; hlp.width := Source.width; hlp.height := Source.height; hlp.canvas.draw(0, 0, Source); Divi := 1084 - Intensiv * 4; Farbe := ColorToRGB(Farbe); aos[0] := getbvalue(Farbe) / Divi + 1; aos[1] := getgvalue(Farbe) / Divi + 1; aos[2] := getrvalue(Farbe) / Divi + 1; korr := ord(Filter) * ((aos[0] + aos[1] + aos[2]) / 9); for h := 0 to hlp.Height - 1 do begin p := hlp.ScanLine[h]; for w := 0 to hlp.Width - 1 do begin for x := 0 to 2 do rech(x, aos[x]); Inc(p); end; end; Dest.pixelformat := pf24bit; Dest.width := Source.width; Dest.height := Source.height; Dest.canvas.draw(0, 0, hlp); hlp.free; end; // Beispielaufruf (siehe obige Abbildung) procedure TForm1.Button2Click(Sender: TObject); var bm: TBitmap; begin bm := TBitmap.Create; kolorieren(image1.Picture.bitmap, bm, clFuchsia, 215, false); canvas.draw(image1.width + 5 + image1.left, image1.top, bm); kolorieren(image1.Picture.bitmap, bm, clFuchsia, 215, true); canvas.draw((image1.width + 5) * 2 + image1.left, image1.top, bm); bm.free; end; // -------------------------------------------------------------------------- // Variante 2: Ohne Filter
// Wer auf den Filter
verzichten kann, nimmt den folgenden
(einfachen)
Code,
procedure einfaerben(src, dst: TBitmap; Farbe: TColor; Intensiv: Byte); var ps, pd: PBytearray; x, y, b3, diff: integer; r, g, b: byte; begin src.pixelformat := pf24bit; dst.pixelformat := pf24bit; dst.width := src.width; dst.height := src.height; Farbe := ColorToRGB(Farbe); r := getrvalue(Farbe); g := getgvalue(Farbe); b := getbvalue(Farbe); b3 := src.Width * 3; diff := 255 - Intensiv; for y := 0 to src.height - 1 do begin x := 0; ps := src.scanline[y]; pd := dst.scanline[y]; while x < b3 do begin pd[x] := (ps[x] * diff + ps[x] * b * intensiv shr 8) shr 8; pd[x + 1] := (ps[x + 1] * diff + ps[x + 1] * g * intensiv shr 8) shr 8; pd[x + 2] := (ps[x + 2] * diff + ps[x + 2] * r * intensiv shr 8) shr 8; Inc(x, 3); end; end; end; // Beispielaufruf procedure TForm1.Button8Click(Sender: TObject); var bm: TBitmap; begin bm := TBitmap.create; einfaerben(Image3.picture.bitmap, bm, clLime, 100); canvas.draw(Image3.boundsrect.right + 10, Image3.top, bm); bm.free; end; // -------------------------------------------------------------------------- // Variante 3: Tönung über TRGBTriple // Weiche Tönung. Ähnelt der Variante 2.
type Prozent = 0..100; var bmp: TBitmap; procedure farb(src, dst: TBitmap; Farbe: TColor; proz: Prozent); type TLine = array[0..21845] of TRGBTriple; PLine = ^TLine; var w, h: integer; r, g, b, t, p, d: Byte; line1, line2: PLine; begin src.pixelformat := pf24bit; dst.pixelformat := pf24bit; t := high(proz); p := proz div 2; d := t - p; farbe := colorToRGB(farbe); r := getrvalue(farbe); g := getgvalue(farbe); b := getbvalue(farbe); for h := 0 to src.Height - 1 do begin line1 := src.ScanLine[h]; line2 := dst.ScanLine[h]; for w := 0 to src.Width - 1 do begin line2[w].rgbtRed := trunc(line1[w].rgbtRed / t * d + r / t * p); line2[w].rgbtGreen := trunc(line1[w].rgbtGreen / t * d + g / t * p); line2[w].rgbtBlue := trunc(line1[w].rgbtBlue / t * d + b / t * p); end; end; end; procedure TForm1.FormCreate(Sender: TObject); begin bmp := TBitmap.create; bmp.loadfromfile('c:\bmp1.bmp'); Image1.picture.bitmap.loadfromfile('c:\bmp1.bmp'); end; procedure TForm1.FormDestroy(Sender: TObject); begin bmp.free; end; // Beispielaufruf procedure TForm1.Button1Click(Sender: TObject); begin farb(bmp, Image1.picture.bitmap, clRed, 50); Image1.Refresh; end; // -------------------------------------------------------------------------- // Variante 4: Vollfarbe // Die Bilder bestehen nur noch aus Tönen ein und der selben Farbe.
procedure faerben(src, dst: TBitmap; Farbe: TColor); var p: PBytearray; x, y, b3: integer; r, g, b: byte; begin src.pixelformat := pf24bit; dst.pixelformat := pf24bit; dst.width := src.width; dst.height := src.height; dst.canvas.draw(0, 0, src); Farbe := ColorToRGB(Farbe); r := getrvalue(Farbe); g := getgvalue(Farbe); b := getbvalue(Farbe); b3 := src.Width * 3; for y := 0 to src.height - 1 do begin x := 0; p := dst.scanline[y]; while x < b3 do begin p[x] := b * p[x] div 255; p[x + 1] := g * p[x + 1] div 255; p[x + 2] := r * p[x + 2] div 255; Inc(x, 3); end; end; end; // Beispielaufruf procedure TForm1.Button8Click(Sender: TObject); var bm: TBitmap; begin bm := TBitmap.create; faerben(Image3.picture.bitmap, bm, clBlue); canvas.draw(100, 0, bm); bm.free; end; procedure TForm1.Button9Click(Sender: TObject); var bm: TBitmap; begin bm := TBitmap.create; faerben(Image3.picture.bitmap, bm, $80FF); canvas.draw(500, 0, bm); bm.free; end; // -------------------------------------------------------------------------- // Variante 5: Sepia
// Der Effekt Sepia
simuliert den traditionellen Dunkelkammer-Effekt,
procedure sepia(Source, Dest: TBitmap; stufe, farbvariante: byte); var r, g, b, h, w, w3, st, st3: integer; p: PBytearray; hlp: TBitmap; begin hlp := TBitmap.create; hlp.pixelformat := pf24bit; hlp.width := Source.width; hlp.height := Source.height; hlp.canvas.draw(0, 0, Source); st3 := round(stufe * 0.444); st := round(stufe * 0.167); w3 := hlp.width * 3 - 1; for h := 0 to hlp.height - 1 do begin w := 0; p := hlp.scanline[h]; while w < w3 do begin b := (p[w] + p[w + 1] + p[w + 2]) div 3; r := b + st3; g := b + st; if r > 255 then r := 255; if g > 255 then g := 255; case farbvariante of 0: ; 1: begin p[w] := b; p[w + 1] := g; p[w + 2] := r; end; 2: begin p[w] := r; p[w + 1] := g; p[w + 2] := b; end; 3: begin p[w] := g; p[w + 1] := b; p[w + 2] := r; end; 4: begin p[w] := g; p[w + 1] := r; p[w + 2] := b; end; 5: begin p[w] := r; p[w + 1] := b; p[w + 2] := g; end; else begin p[w] := b; p[w + 1] := b; p[w + 2] := b; end; end; inc(w, 3); end; end; Dest.pixelformat := pf24bit; Dest.width := Source.width; Dest.height := Source.height; Dest.canvas.draw(0, 0, hlp); hlp.free; end; procedure TForm1.Button2Click(Sender: TObject); var bm: TBitmap; begin bm := TBitmap.Create; sepia(image1.picture.bitmap, bm, 100, 1); canvas.draw(image1.width + 5 + image1.left, image1.top, bm); bm.free; end;
// Variante 6: Schwarz-Farb-Technik
// ab einer bestimmten
Helligkeitsstufe wird die entsprechende Stelle im
var graugrenze: integer = 95; weissgrenze: integer = 242; schwarzgrenze: integer = 80; procedure schwrzfrb(Source, Dest: TBitmap; farbe: TColor; intensiv: byte); var k, x, y, r, g, b, w: integer; p: PBytearray; hlp: TBitmap; function rech(i, j: integer): integer; asm add eax, edx sub eax, $40 cmp eax, 0 jge @weiter xor eax, eax jmp @fertig @weiter: cmp eax, $FF jle @fertig mov eax, $FF @fertig: end; begin hlp := TBitmap.create; hlp.pixelformat := pf24bit; hlp.width := Source.width; hlp.height := Source.height; hlp.canvas.draw(0, 0, Source); farbe := colortorgb(farbe); r := getrvalue(farbe) * intensiv shr 8; g := getgvalue(farbe) * intensiv shr 8; b := getbvalue(farbe) * intensiv shr 8; w := hlp.width * 3; for y := 0 to pred(hlp.height) do begin p := hlp.scanline[y]; x := 0; while x < w do begin k := (p[x] + p[x + 1] + p[x + 2]) div 3; if k > weissgrenze then begin p[x] := rech(290, b); p[x + 1] := rech(290, g); p[x + 2] := rech(290, r); end else if k < schwarzgrenze then begin p[x] := 0; p[x + 1] := 0; p[x + 2] := 0; end else if k < graugrenze then begin p[x] := rech(60, b); p[x + 1] := rech(60, g); p[x + 2] := rech(60, r); end else begin p[x] := rech(k, b); p[x + 1] := rech(k, g); p[x + 2] := rech(k, r); end; inc(x, 3); end; end; Dest.pixelformat := pf24bit; Dest.width := Source.width; Dest.height := Source.height; Dest.canvas.draw(0, 0, hlp); hlp.free; end; // Beispielaufruf procedure TForm1.Button3Click(Sender: TObject); begin schwrzfrb(Image1.picture.bitmap, Image1.picture.bitmap, clGreen, 150); end;
// Variante 7: one color gray // Eine der 3 RGB-Farben wird betont, alle anderen Farben in Grau gewandelt.
type RoGrBl = (rot, gruen, blau); procedure onecolorgray(Source, Dest: TBitmap; farbe: RoGrBl; intensiv: byte); var x, y, b3: integer; p: PBytearray; procedure grau; begin p[x] := (p[x] + p[x + 1] + p[x + 2]) div 3; p[x + 1] := p[x]; p[x + 2] := p[x]; end; begin dest.pixelformat := pf24bit; dest.width := source.width; dest.height := source.height; dest.canvas.draw(0, 0, source); b3 := dest.width * 3; for y := 0 to dest.height - 1 do begin x := 0; p := dest.scanline[y]; while x < b3 do begin case farbe of rot: if (p[x + 2] + intensiv > p[x] + 128) and (p[x + 2] <> p[x]) and (p[x + 2] + intensiv > p[x + 1] + 128) and (p[x + 2] <> p[x + 1]) then begin p[x] := (255 - p[x + 2]) div 2; if p[x] > p[x + 2] then begin p[x + 1] := p[x + 2]; p[x + 2] := p[x]; p[x] := p[x + 1]; end else p[x + 1] := p[x]; end else grau; gruen: if (p[x + 1] + intensiv > p[x] + 128) and (p[x + 1] <> p[x]) and (p[x + 1] + intensiv > p[x + 2] + 128) and (p[x + 1] <> p[x + 2]) then begin p[x] := (255 - p[x + 1]) div 2; if p[x] > p[x + 1] then begin p[x + 2] := p[x + 1]; p[x + 1] := p[x]; p[x] := p[x + 2]; end else p[x + 2] := p[x]; end else grau; else if (p[x] + intensiv > p[x + 2] + 128) and (p[x + 2] <> p[x]) and (p[x] + intensiv > p[x + 1] + 128) and (p[x + 1] <> p[x]) then begin p[x + 1] := (255 - p[x]) div 2; if p[x + 1] > p[x] then begin p[x + 2] := p[x]; p[x] := p[x + 1]; p[x + 1] := p[x + 2]; end else p[x + 2] := p[x + 1]; end else grau; end; inc(x, 3); end; end; end; procedure TForm1.Button5Click(Sender: TObject); var bm: TBitmap; begin bm := TBitmap.create; onecolorgray(image1.picture.bitmap, bm, rot, 92); canvas.draw(image1.left + image1.width + 5, image1.top, bm); bm.free; end;
// Variante 8: Bonbon-Farbe
// Durch Überbetonen
aller Kanäle werden unnatürliche Farben erzeugt.
procedure bonbon(src: TGraphic; dst: TBitmap; stufe: byte); var x, y, b3: integer; p: PBytearray; b, c: byte; function vergl: byte; begin result := ord((p[x + 2] > p[x + 1]) and (p[x + 2] > p[x])) or (ord((p[x + 1] > p[x + 2]) and (p[x + 1] > p[x])) shl 1) or (ord((p[x] > p[x + 1]) and (p[x] > p[x + 2])) shl 2); end; function rech(b, s: byte): byte; var h: integer; begin if b < 32 then result := b else begin h := b + s; if h < 0 then result := 0 else if h > 255 then result := 255 else result := h; end; end; begin if not Assigned(src) then exit; dst.width := src.width; dst.height := src.height; dst.pixelformat := pf24bit; dst.canvas.draw(0, 0, src); b3 := dst.width * 3; for y := 0 to dst.height - 1 do begin x := 0; p := dst.scanline[y]; while x < b3 do begin b := vergl; c := ord(b = 0); if b in [0, 1] then p[x + 2] := rech(p[x + 2], trunc(stufe * (0.5 - c * 0.4))); if b in [0, 2] then p[x + 1] := rech(p[x + 1], trunc(stufe * 0.1)); if b in [0, 4] then p[x] := rech(p[x], trunc(stufe * (0.4 - c * 0.3))); inc(x, 3); end; end; end; // Beispiel procedure TForm1.Button4Click(Sender: TObject); var bm: TBitmap; begin bm := TBitmap.create; bonbon(Image1.picture.graphic, bm, 175); canvas.draw(Image1.left + Image1.width + 5, Image1.top, bm); bm.free; end;
// Variante 9: Blassfärben
type staerke = 0..100; procedure grad(dst, src: TBitmap; Farbe: TColor; Stufe: staerke); var x, y, x3, r, g, b: integer; p, p2: pbytearray; function rechnen(bf, bp: byte): byte; var h: integer; begin h := abs(trunc(Stufe * bf / (bp + 0.01) * 0.333)); if h <= 0 then result := 255 else if h >= 255 then result := 0 else result := 255 - h; end; begin inc(Stufe, 155); dst.pixelformat := pf24bit; src.pixelformat := pf24bit; Farbe := ColorToRGB(Farbe); r := 128 - GetRValue(Farbe) div 2; g := 128 - GetGValue(Farbe) div 2; b := 128 - GetBValue(Farbe) div 2; for y := 0 to dst.height - 1 do begin p := dst.scanline[y]; p2 := src.scanline[y]; for x := 0 to dst.width - 1 do begin x3 := x * 3; if (p2[x3] <> 255) or (p2[x3 + 1] <> 255) or (p2[x3 + 2] <> 255) then begin p[x3] := rechnen(b, p2[x3]); p[x3 + 1] := rechnen(g, p2[x3 + 1]); p[x3 + 2] := rechnen(r, p2[x3] + 2); end else begin p[x3] := 238; p[x3 + 1] := 238; p[x3 + 2] := 238; end; end; end; end; // Beispiel procedure TForm1.Button2Click(Sender: TObject); var b: TBitmap; begin b := TBitmap.create; b.width := image1.width; b.height := image1.height; Grad(b, Image1.picture.bitmap, $404080, 50); canvas.draw(10, 10, b); Grad(b, Image1.picture.bitmap, $804040, 50); canvas.draw(200, 10, b); b.free; end;
// -------------------------------------------------------------------------- // Variante 10: Nachtstimmung
type staerke = 0..100; procedure Nacht(dst, src: TBitmap; Farbe: TColor; stufe: staerke); const dv = 127; var x, y, x3, r, g, b, f: integer; p, p2: pbytearray; px1, px2, px3: Byte; function rechnen(pb: byte): byte; var h: integer; begin h := trunc(pb * (f - dv * 1.5) / dv - dv); if h < 0 then result := 0 else if h > 255 then result := 255 else result := h; end; begin src.pixelformat := pf24bit; dst.pixelformat := pf24bit; dst.width := src.width; dst.height := src.height; Farbe := ColorToRGB(Farbe); r := dv + GetRValue(Farbe) div 2; g := dv + GetGValue(Farbe) div 2; b := dv + GetBValue(Farbe) div 2; with dst.canvas do begin brush.color := 0; fillrect(cliprect); end; inc(stufe, 155); for y := 0 to dst.height - 1 do begin p := dst.scanline[y]; p2 := src.scanline[y]; for x := 0 to dst.width - 1 do begin x3 := x * 3; f := p2[x3] + p2[x3 + 1] + p2[x3 + 2]; px1 := rechnen(p2[x3]); px2 := rechnen(p2[x3 + 1]); px3 := rechnen(p2[x3 + 2]); p[x3] := (px1 * b * stufe) shr 16; p[x3 + 1] := (px2 * g * stufe) shr 16; p[x3 + 2] := (px3 * r * stufe) shr 16; end; end; end; // Beispiel procedure TForm1.Button2Click(Sender: TObject); var b: TBitmap; begin b := TBitmap.create; Nacht(b, Image1.picture.bitmap, clBlue, 100); canvas.draw(10, 10, b); Nacht(b, Image1.picture.bitmap, clPurple, 100); canvas.draw(200, 10, b); b.free; end;
|