Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Bild abdunkeln


HenryHux - Di 19.04.11 17:56
Titel: Bild abdunkeln
Hi,

ich versuche ein Bitmap abzudunkeln. Bisher mache ich das über eine Graustufen Funktion, welche auch gut klappt, aber eben nur Graustufen macht und das Bild nicht wirklich dunkler macht.
So sieht sie aus :


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
Procedure TDrawings.GreyBitmap(Const ABitmap: TBitmap);
Var
   I, J, Gr: Integer;
   Row:      ^TRGBTriple;
Begin
     For J      := 0 To ABitmap.Height -1 Do Begin
         Row    := ABitmap.ScanLine[J];
         For I  := 0 To ABitmap.Width -1 Do Begin
             Gr := Trunc(Row^.rgbtRed * 0.3 + Row^.rgbtGreen * 0.59 +
                         Row^.rgbtBlue * 0.11);
             //Gr := Trunc(Row^.rgbtRed * 0.1 + Row^.rgbtGreen * 0.39 +
             //            Row^.rgbtBlue * 0.0);
             Row^.rgbtRed   := Gr;
             Row^.rgbtGreen := Gr;
             Row^.rgbtBlue  := Gr;
             Inc(Row);
         End;
     End;
     ABitmap.Assign(ABitmap);
End;


Das Auskommentierte macht dann auch wirklich dunkel, aber nicht konstant, sprich bei mehrfachen Ausführen habe ich ein schwarzes Bild :D
Da ich nun leider überhaupt keine Ahnung von Farbberechnung via RGB habe, muss ich euch um Hilfe bitten.

lg


Stundenplan - Di 19.04.11 18:05

Ziehe von R, G und B jeweils einen bestimmten Wert ab, dann sollte es gehen! :idea:
Du könntest dir auch mal den HSV-Farbraum [http://de.wikipedia.org/wiki/HSV-Farbraum] anschauen, damit kannst du direkt auf Farbton, Sättigung und eben Helligkeit zugreifen.

EDIT: Möchtest du nun das Bild abdunkeln oder in Graustufen konvertieren oder beides? :gruebel:

Viele Grüße,
Stundenplan.


HenryHux - Di 19.04.11 18:18

Hi,

also erstmal habe ich versucht die R G B Werte zu verkleinern.
Auch das funktioniert nicht so wie ich will, wie gesagt beim mehrfachen Ausführen sollte das Bild nur einmal verdunkelt werden.
Ob das Bild jetzt abgedunkelt und in Graustufen konvertiert wird oder nur abgedunkelt ist erstmal egal, müsste ich dann das Resultat sehen.
Ich guck mir dann jetzt mal den HSV-Farbraum an.

lg


Dude566 - Di 19.04.11 18:41

Habs nur mal schnell geschrieben und nicht richtig getestet aber schaut ganz gut aus, auch wenn wegen Pixels die Perfomance leidet:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
procedure TfrmMain.btnScaleClick(Sender: TObject);
var
  bmp : TBitmap;
  x, y : integer;
  r,g,b : byte;
begin
  percentage := StrToInt(edtPercentage.Text);
  bmp := TBitmap.Create;
  bmp.LoadFromFile(sourcepath);
  for x := 1 to bmp.Width do
  begin
    for y := 1 to bmp.Height do
    begin
      r := GetRValue(bmp.Canvas.Pixels[x,y]);
      g := GetGValue(bmp.Canvas.Pixels[x,y]);
      b := GetBValue(bmp.Canvas.Pixels[x,y]);
      r := r - ((r div 100) * percentage);
      g := g - ((g div 100) * percentage);
      b := b - ((b div 100) * percentage);
      bmp.Canvas.Pixels[x,y] := RGB(r,g,b);
    end;
  end;
  bmp.SaveToFile(ExtractFilePath(sourcepath)+'ausgabe.bmp');
  edtDestinationImage.Text := ExtractFilePath(sourcepath)+'ausgabe.bmp';
  ShowMessage('Bild wurde um ' + IntToStr(percentage) + ' Prozent verdunkelt.');
end;


Alles jetzt ohne Fehlerbehandlung etc.


HenryHux - Di 19.04.11 19:43

Ok, sieht gut aus und klappt auch soweit.
Danke :)

lg


jaenicke - Di 19.04.11 22:36

Und wenn du eine echte Helligkeitsänderung ohne Farbverfälschungen haben willst, nimm am besten den HSV-Farbraum [http://www.delphipraxis.net/42054-rgb-hsv-und-hsv-rgb.html]. ;-)
Damit arbeite ich bei so etwas, so dass die Ergebnisse wirklich dem menschlichen Farbempfinden entsprechen. In Verbindung mit Scanline ist das auch recht schnell.


Dude566 - Di 19.04.11 22:43

Ich habe ja auch oben nur das geschrieben, was ich intuitiv ohne nachzuforschen als erstes machen würde. ;)