Delphi - Transformacje grafiki - Przezroczystość
Sun, 9 January 2005
Wstęp
Tak jak obiecałem, zajmiemy się dzisiaj nakładaniem obrazków. Spróbujemy nałożyć na siebie dwa obrazki, w sposób, aby oba były jednocześnie widoczne. Użyjemy przezroczystości. A przezroczystość to przecież nic innego jak średnia kolorów danych pikseli z obu obrazków.
Kod tego efektu jest przejrzysty i krótki, a efekt zadziwiający. To jest właśnie szczególna cecha efektów graficznych. Niewielkim nakładem pracy możemy stworzyć ciekawe filtry.
Cóż, nie pozostaje mi nic innego jak zacząć - a więc - do dzieła! ;)
Piszemy program
- Przygotuj dwa obrazki (nazwij je "obrazek1.bmp" i "obrazek2.bmp" i umieść na dysku C: ). Możesz nazwać je inaczej, ale będziesz to musiał uwzględnić również w kodzie programu (zmienić ścieżkę).
- Na formularzu umieść przycisk (paleta Standard).
- Kliknij dwukrotnie na przycisk. Zostaniesz przeniesiony do edytora kodu.
- Do listy uses dodaj słówkoMath.
- Wygenerowaną przed chwilą procedurę uzupełnij następująco:
procedure TForm1.Button1Click(Sender: TObject); var bitmapa1, bitmapa2, bitmapa3 : TBitmap; x, y : integer; r1, g1, b1: byte; r2, g2, b2: byte; kolor : TColor; kolor_sredni : TColor; begin // Utworzenie bitmap (bitmapy 1 i 2 to bitmapy wejściowe, a bitmapa 3 jest bitmapą wyjściową (przetworzoną)) bitmapa1 := TBitmap.Create; bitmapa2 := TBitmap.Create; bitmapa3 := TBitmap.Create; // Wczytanie obrazków bitmapa1.LoadFromFile('C:\obrazek1.bmp'); bitmapa2.LoadFromFile('C:\obrazek2.bmp'); // Bitmapa wyjściowa (bitmapa3) powinna mieć rozmiary takie jak większy z obrazków. bitmapa3.Width := Max(bitmapa1.Width, bitmapa2.Width); bitmapa3.Height := Max(bitmapa1.Height, bitmapa2.Height); // Pętla która "przejeżdża" nam po wierszach for y:=0 to bitmapa3.Height-1 do // Pętla która "przejeżdża" nam po pikselach danego wiersza for x:=0 to bitmapa3.Width-1 do begin // Pobieramy kolor aktualnego piksela, z aktualnego wiersza obrazka1 kolor := bitmapa1.Canvas.Pixels[x,y]; // Rozkładamy pobrany kolor na składowe (r-czerwony, g-zielony, b-niebieski) r1 := GetRValue(kolor); g1 := GetGValue(kolor); b1 := GetBValue(kolor); // Pobieramy kolor aktualnego piksela, z aktualnego wiersza obrazka2 kolor := bitmapa2.Canvas.Pixels[x,y]; // Rozkładamy pobrany kolor na składowe (r-czerwony, g-zielony, b-niebieski) r2 := GetRValue(kolor); g2 := GetGValue(kolor); b2 := GetBValue(kolor); // Oblicz średnią kolorów danych pikseli z obu obrazków (składowa1 + składowa2)/2 kolor_sredni := RGB( (r1+r2) div 2, (g1+g2) div 2, (b1+b2) div 2 ); // Narysuj piksel o obliczonym kolorze średnim na bitmapie wyjściowej bitmapa3.Canvas.Pixels[x,y] := kolor_sredni; end; // Po ukończeniu, wyświetl wynik (bitmapę wyjściową) na formie Form1.Canvas.Draw(0, 0, bitmapa3); end;
Nie przejmuj się długością kodu, bo jego większość zajmują komentarze ;) Kod nie jest trudny i jeśli się wczytasz - zrozumiesz zasadę działania. Wiecie po co był nam potrzebny moduł Math ? Bez niego nie zadziałała by funkcja MAX, która z dwóch podanych na wejście liczb zwraca tą większą. Analogicznie istnieje również funkcja MIN, która z dwóch podanych na wejście liczb zwróci tą mniejszą (to tak na marginesie ;). Funkcję MAX można było oczywiście zapisać w postaci warunków, ale wiecie - lenistwo ;) Zmienną "bitmapa3" musimy powiększyć do rozmiarów większego obrazka (z tych dwóch załadowanych). Jeślibyśmy tego nie zrobili, wówczas mogłoby się zdarzyć, że pętla przechodziłaby przez nieistniejące piksele obrazka wyjściowego. Mniejsza z tym. W pętli najpierw pobieramy kolor danego piksela (na którym właśnie stoi pętla) z pierwszego obrazka, potem "rozbieramy" ;) go na 3 składowe. Następnie pobieramy kolor danego piksela z drugiego obrazka (również go rozkładamy na składowe). Obliczamy średnią składowych składających się na kolor. Średnią obliczamy w ten sposób iż bierzemy np. 5 liczb, dodajemy je do siebie i wynik dzielimy przez ilość liczb (czyli przez 5). Tutaj sytuacja jest podobna. Składową z pierwszego obrazka dodajemy do składowej z drugiego obrazka i dzielimy przez ilość dodanych składowych (czyli 2). Takie małe przypomnienie.
Kolejnym krokiem jest narysowanie piksela w wybranym miejscu na bitmapie wyjściowej (bitmapa3) o obliczonym kolorze średnim.
Do tej pory wszystko odbywało się w pamięci (nawet rysowanie) (tak jest najwydajniej). Gdy pętla jednak zakończy działanie, wówczas następuje wyświetlenie bitmapy na formie przy pomocy procedury Draw().
Zakończenie
Na koniec pozostało mi życzyć Wam Wesołych Świąt i szczęśliwego Nowego Roku. Jak zwykle do artykułu dołączam kod źródłowy omawianego dziś efektu. Dzięki za poświeconą uwagę! Kod źródłowy, dołączony do artykułu znajdziecie w tym miejscu.





Podobne artykuly:
- Delphi - Transformacje grafiki - Przyjaśnianie i przyciemnianie
- Delphi - Transformacje grafiki - Odcienie szarości
- Delphi - Transformacje grafiki - Efekt fali cosinusoidalnej
- Delphi - Transformacje grafiki - Wstęp
- Delphi - Transformacje grafiki - Odbicia lustrzane
- Delphi - Efekt fali
- KillAd
Skomentuj
Komentarze czytelników
-
- Niko
- Wed, 3 July 2013, 20:20
- W lazarusie nie chce działać
niewiem czemu ?
-
- TomRiddle
- Fri, 17 September 2010, 13:39
- Można ten kod przerobić tak, żeby forma była przeźroczysta, dzięki:
Transparent := True;
TransparentColor := clSkyBlue;
Color := clSkyBlue
I żeby ta bitmapa pobierała obraz z pulpitu??