// Es werden alle Schattierungen einer Farbe mit Schattierungen einer
// anderen Farbe ersetzt.
// (nicht verwechseln mit
eine Farbe in einem Bitmap vertauschen)
// Dabei sagt die Farbe der Variablen "Schattierung" nur aus welche
// Schattierungen ausgetauscht werden sollen. Es ist also egal, ob man hier
// "clLime" oder "clGreen" angibt, da ja das eine nur eine Schattierung des
// anderen ist. Bilder mit vielen hellen Stellen sind ungeeignet, da das
// Ergebnis meist fleckig aussieht.
// Querverweis:
Bitmaps tönen

// Getestet mit D4 unter XP

// --- für alle Varianten ---------------------- 
 
function vergleich(r, g, b: byte): byte; 
var 
  r1, g1, b1: byte; 
begin 
  r1 := ord((r > g) and (r > b)); 
  g1 := ord((g > r) and (g > b)); 
  b1 := ord((b > g) and (b > r)); 
  result := r1 or (g1 shl 2) or (b1 shl 4); 
end; 
 
// --------------------------------------------- 
// Variante 1a: Das ganze Bild wird bearbeitet 
//              Die Farbe der Variablen "Farbe" ist nicht nur für die neue 
//              Schattierung da, sondern bestimmt auch deren Helligkeit. 
clred --------------> $DDFFDD
 
Image1.Canvas.Pixels[1, 1] --> $A0FFFF
procedure changeColor(bm: TBitmap; Schattierung, Farbe: TColor); 
var 
  r1, g1, b1, r2, g2, b2, v, gr: byte; 
  x, y, b3: integer; 
  p: pbytearray; 
begin 
  bm.pixelformat := pf24bit; 
  schattierung := ColorToRGB(schattierung); 
  r1 := getrvalue(schattierung); 
  g1 := getgvalue(schattierung); 
  b1 := getbvalue(schattierung); 
  Farbe := ColorToRGB(Farbe); 
  r2 := getrvalue(Farbe); 
  g2 := getgvalue(Farbe); 
  b2 := getbvalue(Farbe); 
  b3 := bm.width * 3; 
  v := vergleich(r1, g1, b1); 
  for y := 0 to bm.height - 1 do begin 
    x := 0; 
    p := bm.scanline[y]; 
    while x < b3 do begin 
      if (vergleich(p[x + 2], p[x + 1], p[x]) = v) 
        then begin 
        gr := trunc(p[x] * 0.11 + p[x + 1] * 0.59 + p[x + 2] * 0.3); 
        p[x] := (b2 * gr) shr 8; 
        p[x + 1] := (g2 * gr) shr 8; 
        p[x + 2] := (r2 * gr) shr 8; 
      end; 
      inc(x, 3); 
    end; 
  end; 
end; 
 
// Beispielaufrufe 
 
procedure TForm1.Button6Click(Sender: TObject); 
begin 
  changeColor(image1.picture.bitmap, clred, $DDFFDD); 
  image1.refresh; 
end; 
 
procedure TForm1.Button7Click(Sender: TObject); 
begin 
  ChangeColor(Image1.picture.bitmap, 
    Image1.Canvas.pixels[1, 1], $A0FFFF); 
  image1.refresh; 
end; 
//-------------------------------------------------------- 
 
// Variante 1b: Es werden nur zusammenhängende Teilbereiche rund um einen 
//              Startpunkt bearbeitet (ähnlich wie bei FloodFill). Weil das
//              rekursiv geschieht, darf die neue Schattierung nicht von
//              gleicher Art wie die alte sein, da sich sonst das Programm
//              totläuft. Außerdem wurde eine Farbaufhellung (1.33) integriert,
//              weil der Austausch dunkler Schattierungen gegen wiederum dunkle 
//              Schattierungen einfach Sch... aussah. 
  siehe Beispiel
 
procedure FloodChangeColor(bm: TBitmap; x, y: integer; 
  Schattierung, Farbe: TColor); 
var 
  r1, g1, b1, r2, g2, b2, v, gr: byte; 
  p: pbytearray; 
  b3: integer; 
  function tst(i, j: integer): boolean; 
  begin 
    result := (i >= b3) or (j >= bm.height) 
      or (i < 0) or (j < 0); 
  end; 
  function frb(bb: byte): byte; 
  var h: integer; 
  begin 
    h := trunc(bb * gr * 1.33) shr 8; 
    if h > 255 then result := 255 else 
      result := h; 
  end; 
  function pixel(i, j: integer): boolean; 
  begin 
    result := false; 
    if tst(i, j) then exit; 
    p := bm.scanline[j]; 
    if (vergleich(p[i + 2], p[i + 1], p[i]) = v) 
      then begin 
      gr := trunc(p[i] * 0.11 + p[i + 1] * 0.59 + p[i + 2] * 0.3); 
      p[i] := frb(b2); 
      p[i + 1] := frb(g2); 
      p[i + 2] := frb(r2); 
      if v = vergleich(p[i + 2], p[i + 1], p[i]) then 
        exit; 
      result := true; 
    end; 
  end; 
  procedure go(i, j: integer); 
  var a, b: integer; 
  begin 
    for b := j - 1 to j + 1 do begin 
      a := i - 3; 
      while a <= i + 3 do begin 
        if pixel(a, b) then go(a, b); 
        inc(a, 3); 
      end; 
    end; 
  end; 
begin 
  bm.pixelformat := pf24bit; 
  b3 := bm.width * 3; 
  x := x * 3; 
  if tst(x, y) then exit; 
  schattierung := ColorToRGB(schattierung); 
  r1 := getrvalue(schattierung); 
  g1 := getgvalue(schattierung); 
  b1 := getbvalue(schattierung); 
  Farbe := ColorToRGB(Farbe); 
  r2 := getrvalue(Farbe); 
  g2 := getgvalue(Farbe); 
  b2 := getbvalue(Farbe); 
  v := vergleich(r1, g1, b1); 
  if v = vergleich(r2, g2, b2) then 
    raise exception.create('Schattierungen dürfen nicht gleich sein'); 
  go(x, y); 
end; 
 
// Beispiel 
 
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton; 
  Shift: TShiftState; X, Y: Integer); 
begin 
  if button = mbleft then 
    FloodChangeColor(TImage(sender).picture.bitmap, 
      x, y, TImage(sender).canvas.pixels[x, y], $8080FF) 
  else if button = mbright then 
    FloodChangeColor(TImage(sender).picture.bitmap, 
      x, y, TImage(sender).canvas.pixels[x, y], $80EEEE); 
  TImage(sender).refresh; 
end; 
//-------------------------------------------------------- 
 
// Variante 2: Der Nachteil der Variante 1 ist, dass eine veränderte 
//             Schattierung nicht wieder zurückgerechnet werden kann. 
//             Deshalb werden bei dieser Variante hier nur die RGB-Werte 
//             eines Pixels untereinander verschoben. Beim Zurückschieben 
//             hat man wieder den Originalzustand. Allerdings sind damit 
//             den Farben der neuen Schattierung enge Grenzen gesetzt. 
//             Bei _grb und _rgb werden jeweils drei Byte verschoben. 
//             Diese beiden Methoden heben sich gegenseitig auf. Ansonsten 
//             werden nur zwei Byte verschoben. Diese Methoden heben sich 
//             logischwerweise selbst wieder auf. 
 
clred ---> _grb clgreen ---> _rbg

type 
  wie = (_grb, _rbg, _gbr, _brg, _rgb); 
 
procedure changeColorx(bm: TBitmap; Schattierung: TColor; art: wie); 
var 
  r1, g1, b1, v, h: byte; 
  x, y, b3: integer; 
  p: pbytearray; 
begin 
  bm.pixelformat := pf24bit; 
  schattierung := ColorToRGB(schattierung); 
  r1 := getrvalue(schattierung); 
  g1 := getgvalue(schattierung); 
  b1 := getbvalue(schattierung); 
  b3 := bm.width * 3; 
  v := vergleich(r1, g1, b1); 
  for y := 0 to bm.height - 1 do begin 
    x := 0; 
    p := bm.scanline[y]; 
    while x < b3 do begin 
      if (vergleich(p[x + 2], p[x + 1], p[x]) = v) 
        then begin 
        case art of 
          _grb: begin 
              h := p[x]; 
              p[x] := p[x + 1]; 
              p[x + 1] := p[x + 2]; 
              p[x + 2] := h; 
            end; 
          _rbg: begin 
              h := p[x]; 
              p[x] := p[x + 2]; 
              p[x + 2] := p[x + 1]; 
              p[x + 1] := h; 
            end; 
          _gbr: begin 
              h := p[x]; 
              p[x] := p[x + 1]; 
              p[x + 1] := h; 
            end; 
          _brg: begin 
              h := p[x + 1]; 
              p[x + 1] := p[x + 2]; 
              p[x + 2] := h; 
            end; 
          _rgb: begin 
              h := p[x]; 
              p[x] := p[x + 2]; 
              p[x + 2] := h; 
            end; 
        end; 
      end; 
      inc(x, 3); 
    end; 
  end; 
end; 
 
// Beispielaufrufe 
 
procedure TForm1.Button9Click(Sender: TObject); 
begin 
  changeColorx(image1.picture.bitmap, clred, _grb); 
  image1.refresh; 
  changeColorx(image2.picture.bitmap, clred, _brg); 
  image2.refresh; 
end; 
 
procedure TForm1.Button10Click(Sender: TObject); 
begin 
  changeColorx(image1.picture.bitmap, clgreen, _rbg); // hebt _grb auf 
  image1.refresh; 
  changeColorx(image2.picture.bitmap, clgreen, _brg); // hebt sich selbst auf 
  image2.refresh; 
end; 



 

Zugriffe seit 6.9.2001 auf Delphi-Ecke