Skalowanie obrazka i kanał alfa

0

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.

0

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;
0

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 :).

0

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.

0

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.

1 użytkowników online, w tym zalogowanych: 0, gości: 1