Jak zmienić kolorowy obrazek (BMP) na niekolorowy w odcieniach szarości

Marco_99
Ten artykuł został przeznaczony do usunięcia. Powody możesz znaleźć na stronie: [[Artykuły do usunięcia]].

Na formę wstaw Image1, w zdarzeniu np.: Button1Click poniższy kod:

var 
WysObr, SzeObr, sr : Integer; 
Kolor : TColor; 
R, G, B :byte; 

begin 
 WysObr := Image1.Height - 1; 
 SzeObr := Image1.Width - 1; 
  
 for SzeObr := 0 to Image1.Width do 
 for WysObr := 0 to Image1.Height do 
  
Begin 
  Kolor := Image1.Picture.Bitmap.Canvas.Pixels[SzeObr, WysObr]; 
  R := GetRValue(Kolor); 
  G := GetGValue(Kolor); 
  B := GetBValue(Kolor);
  sr:= (R+G+B) div 3; 
  Image1.Picture.Bitmap.Canvas.Pixels[SzeObr, WysObr] := RGB(sr, sr, sr); 
 end;

16 komentarzy

Marooned, proszę Cię... litości... ja to doskonale rozumiem. Tylko kiedy Ty zrozumiesz, że to nie mój tekst? Ja go tylko poprawiłem, bo poprzednia wersja była kompletną bzdurą. Zresztą... zobacz sobie na historię zmian... Dla mnie możesz sobie to wywalić nawet. Pozdro.

Czarownik: to co napisał mirekpil, czyli

Gray := Round(0.30 * P.R + 0.59 * P.G + 0.11 * P.B);

ma większy sens niż Twoje (r+g+b)/3.
Zobacz jak kolor odbiera oko ludzkie oraz jak kolor przesyłany jest np. w sygnale TV, a zrozumiesz, dlaczego (r+g+b)/3 to kiepski pomysł.

Sama też implementacja jest mierna - Pixels ?! to trwa wieki.. ja bym to usunął bądź połączył ze wspomnianymi większymi artykułami.

w tym Linku co Adam dał jest ta procedurka i to znacznie szybsza na ScanLine -Skala Szarości pozatym Adam B. Napisał już taki kod na pixelach (ze 2 arty takie widzałem jeszcze) i to poprawny bo ten wyciąga średnią a oko ludzkie nie odbiera barw jednakowo wię ten robi psełdoskalę szarości , powoli robi sie bałagan i trzeba uporzadkować :)
jak będe miał czas i chęci to rozwinę tego mojego arta o nowe funkcje ...
i implementacje C++

no wiadomo... ;) ja tylko ten tekst poprawiłem :)

to trzeba zmienić albo usunąć!!

sorry, ale właściwie to co to jest?? zastępujesz r i g wartościami b. nie sprawdzałem efektu i jakoś nie mam zamiaru. powiem za to tyle, że odcienie szarości otrzymuje się ze średniej piksela, czyli (r+g+b)/3. nie rozumię sensu tego, co ty przedstawiłeś...

Lepszy efekt można uzyskać :

procedure TForm1.Button1Click(Sender: TObject);
type
  PPixelRec = ^TPixelRec;
  TPixelRec = packed record
    B: Byte;
    G: Byte;
    R: Byte;
    Reserved: Byte;
  end;
var
  X: Integer;
  Y: Integer;
  P: PPixelRec;
  Gray: Byte;
  BMP : TBitmap ;
begin
  Bmp := TBitmap.Create;
  Bmp.Assign(Image1.Picture.Bitmap);
  Bmp.PixelFormat := pf32Bit;
  for Y := 0 to (Bmp.Height - 1) do
  begin
    P := Bmp.ScanLine[Y];
    for X := 0 to (Bmp.Width - 1) do
    begin
      Gray := Round(0.30 * P.R + 0.59 * P.G + 0.11 * P.B);
      P.R := Gray;
      P.G := Gray;
      P.B := Gray;
      Inc(P);
    end;
  end;
Image1.Canvas.StretchDraw(Rect(0,0,Image1.Width,Image1.Height),bmp) ; 
{ jeśli wcześniej użyłeś :Image1.Picture.LoadFromFile(nazwa); to musisz zmienić na  StretchDraw, a przy okazji będziesz mógł konwertować również jpg, ico, wmf i emf }
bmp.Free ;
end;

Nie zapomnij w 'uses' dopisać 'jpeg' ...

:-)

with Image1.Picture do
begin
Graphic := TJPEGImage.Create;
Graphic.LoadFromFile('sth.jpg');
TJPEGImage(Graphic).GrayScale := True;
end;

:-)

Regards to all ...

Zmieńcie na takie coś

WysObr := obrazek.Picture.Height - 1;
SzeObr := obrazek.Picture.Width - 1;

for SzeObr := 0 to obrazek.Picture.Width do
for WysObr := 0 to obrazek.Picture.Height do

to wtedy będziecie mieli cały obrazek w skali szarości.Bo jesli ktoś go nie skalował a nie mieści sie na TImage to szare jest tylko to co widać a tak nie

A w jaki sposób można to samo zrobić z plikami jpg? Albo może jest taki komponent dokonywujący takiej konersji, bo chyba zrobienie takiego cuda z plikiem jpg zajęłoby więcej linii kodu i byłoby wolniejsze :D

Operacje na .Pixlels są niesamowicie wolne. Korzystajcie z scanLine()

Dryobates dziękuję za uwagi, poprawiłem błędy.

Po pierwsze: Ten kod zamienia obrazek kolorowy na czarno-biały(a nie negatyw - ten powstaje przez not) i w dodatku bierze jedynie niebieską wartość, co powoduje utracenie informacji o kolorze niebieskim (jeżeli weźmiemy R zamiast B to utracimy o czerwonym, a jeżeli G to o zielonym. Tyle tylko, że na niebieski oczy najsłabiej reagują. To jest metoda "niesprawiedliwa" wobec niebieskiego).
Po drugie: zamieniłeś Wysokość z Szerokością :)

Właśnie tego szukałem ;]