Konwertowanie bitmapy do skali szarości

Adam Boduch

Od razu zaznaczam, że ten algorytmy może być wolny na słabszych maszynach lub dużych bitmapach, ale działa :)

Całość opierać się będzie na funkcji konwertującej kolor do skali szarości.

 { Pobrano z grupy dyskusyjnej: pl.comp.lang.delphi }
function GetGrayColor (Color: TColor): TColor;
const RConst = 77;
      GConst = 150;
      BConst = 29;
var Index: Integer;
begin
  Index := Byte (Longint (Word (GetRValue (Color)) * RConst +
                 Word (GetGValue (Color)) * GConst +
                 Word( GetBValue(Color)) * BConst) shr 8);
  Result := RGB (Index, Index, Index);
end;

No i właściwie to jest główna funkcja, na której opierać się będzie nasz program. Funkcja ta pobiera z koloru podanego jako parametr trzy różne barwy: czerwony ( GetRValue ), zielony ( GetGValue ), niebieski ( GetBValue ). Następnie pobrane wartości są mnożone przez stałe. Mieszając te kolory ze sobą otrzymujemy kolor szary.

Oto procedura wykorzystująca powyższą funkcję:

procedure TForm1.Button1Click(Sender: TObject);
var
  B : TBitmap;
  I, J : Integer;
begin
  B := TBitmap.Create;
  B.LoadFromFile('C:\Moje dokumenty\obrazek.bmp');

  for I := 0 to B.Width do
    for J := 0 to B.Height do
      B.Canvas.Pixels[i, j] := GetGrayColor(B.Canvas.Pixels[i, j]);

  Canvas.Draw(0, 0, B);
  B.Free;
end;

Ta procedura każdy piksel przetwarza przez funkcję, która wcześniej napisaliśmy. Na tej podstawie otrzymujemy bitmapę w skali szarości, którą później wyświetlamy na formie.

9 komentarzy

A jak zrobić w drugą stronę? ;) To byłoby zdecydowanie ciekawsze.

a mozna zrobic srednia z liczb R G i B tego koloru, tylko wyjdzie troche inaczej (chyba bedzie troche ciemniejsze)

W związku z wrażliwością i możliwościami percepcyjnymi oka przyjmuje się, że kolory nie są odbierane jednakowo. Zgodnie z zasadami przyjętymi w grafice (nie tylko komputerowej), ludzkie oko w sposób szczególny oddaje kolor zielony. Stąd wzór (0.0 - niewrażliwość na kolor, 1.0 wrażliwość maksymalna):
luminancja = 0.3R + 0.59G + 0.11*B

Jeśli przeliczycie ułamki na bajty, to 0.59 odpowiada wartości około 150; a więc zmiana odcienia zieleni na obrazku ma największy wpływ na jego jasność w skali szarości.

no wlasnie.. nie czaje tu tylko tego dlaczego akurat 77, 150 i 29 w tych stałych?

nie lepiej zrobic na scanline?

Ja tam zawsze wyliczam średnią z kolorów R, G, B.

Po co sie meczyc ms. Delphi cie wyreczy. Standardowo w delphi zaimplementowane sa funkcje do zamiany bmp do skali szarosci...

A wyobraźsobie, że może to kogoś interesować. Nie dawno miałem do zrobienia projekt z grafiki robiący podobne rzeczy!
A tu jest prosto i na temat

a skąd sie wzieły te stałe i to wyrażanie podstawione do Index?? :D