Cześć,
Bardzo rzadko proszę o pomoc na forum, ale z tym problemem nie mogę sobie poradzić od kilku dni.
Piszę funkcję do skalowania bitmapy. Jest ona zapisana w pamięci jako zwykła tablica bajtów. Każde 4 kolejne bajty to wartości kolorów odpowiednio RGBA (zakres od 0 do 255). Jak widać obrazki mają kanał alfa.
Weźmy sobie prosty algorytm zmniejszania obrazka dwukrotnie, który po prostu przekształca każdy kwadrat obrazka 2x2 piksele na 1 piksel z uśrednionym kolorem dla każdego kanału. Jeśli nie ma przezroczystości, to wszystko działa ok.
Teraz mamy sobie obrazek 2x2 piksele, którego 2 lewe piksele mają kolor RGBA=00FF00FF (kolor zielony, nieprzezroczysty), a prawe RGBA=FF000000 (kolor czerwony, ale całkiem przezroczysty, więc niewidoczny). Po przeskalowaniu powyższym algorytmem otrzymujemy jednopikselowy obrazek o kolorze RGBA=7F7F007F. Mamy więc półprzezroczysty żółty obrazek. Ale skoro wcześniej widoczny był tylko kolor zielony to chcę, żeby po przeskalowaniu obrazek też był widoczny tylko zielony.
I tu właśnie mam problem. Zna ktoś może jakieś fajne rozwiązanie? Może w ogóle kanał alfa powinno się traktować inaczej niż pozostałe kolory? Teoretycznie mogę zmienić dwa prawe piksele na przezroczyste zielone, ale przy większych i wielokolorowych obrazkach to już chyba nie jest takie proste do wykonania.
Najczęściej stosuje się zapis taki że wartości kanałów RGB są <= Alpha
I tak dla koloru białego z przezroczysością 0.5 masz 7F7F7F7F W takim zapisie kolor czerwony przezroczysty (FF000000) nie ma sensu (zresztą wyrażenie "przezroczysty czerwony" rzadko posiada sens). W tym zapisie kolor przezroczysty to 00000000 i po wymieszaniu zielonego z przezroczystym otrzymasz 007F007F.
Jeśli jednak z jakiś powodów chcesz wykorzystywać całe 8-bitowe spektrum dla kanałow RGB nawet kiedy masz kolor o prześwicie np 20% to funkcja mieszająca powinna wyglądać mniej więcej tak:
wynik.R=(kolor1.R*kolor1.A+kolor2.R*kolor2.A)/(kolor1.A+kolor2.A); //i tak dla G i B
wynik.A=(kolor1.A+kolor2.A)/2;
Przyznam, że tego pierwszego sposobu (RGB<=A) do końca nie rozumiem. Co jeśli chciałbym mieć półprzezroczysty kolor niebieski? Miałby ona wartość 0000FF7F, czyli składowa B>A.
Druga metoda wydaje mi się dużo fajniejsza i właśnie ją zastosowałem.
Bardzo dziękuję za pomoc :).
Jeśli chcesz półprzezroczysty kolor niebieski to jest nim 00007F7F. Generalnie jeśli w tym zapisie chcesz uzyskac kolor X o przezroczystości A to musisz składowe X-a pomnożyć przez A. Ta meoda jest często stosowana ponieważ w większości wypadków dzięki takiej postaci przechowywania możemy zaoszczedzić kilka operacji przy przekstałceniach.
Dzięki, już rozumiem. Zastanowię się, czy tego nie zastosować bo całej mojej biblioteki (taką swoją do grafiki 2d piszę). Jeśli miałaby być szybsza, to może warto pozmieniać trochę kodu.