Oślepiony przez światło
Zacznijmy od przypomnienia sobie, że każdy z naszych pikseli (piłeczek pingpongowych) zawiera trójkolorową diodę LED zwaną NeoPikselem. Co więcej, każdy NeoPiksel zawiera czerwone, zielone i niebieskie subpiksele, z których każdy może być sterowany 256 różnymi poziomami od 0 (0x00 w systemie szesnastkowym = 0% = całkowicie wyłączony) do 255 (0xFF w systemie szesnastkowym = 100% = całkowicie włączony).
Nie wiem jak wy, ale ja zawsze, gdy pracuję nad takim projektem, to w mojej głowie pojawiają się pytania i zdaję sobie sprawę, że jest wiele rzeczy, których nie wiem. Na przykład, załóżmy, że chcemy podświetlić jeden z naszych pikseli w 100% na czerwono. Załóżmy teraz, że sąsiedni piksel zostanie podświetlony na 100% zielono i 100% niebiesko, co da kolor cyjanowy. Czy oznacza to, że cyjanowy piksel jest dwa razy jaśniejszy od czerwonego? Czy to z kolei oznacza, że tak naprawdę powinniśmy podświetlić zielone i niebieskie subpiksele na 50% (128 w systemie dziesiętnym = 0x80 w systemie szesnastkowym), aby uzyskać taką samą jasność jak czerwony piksel?
Podobnie, jeśli weźmiemy inny piksel, który sąsiaduje z naszym oryginalnym czerwonym pikselem i zaświecimy wszystkie trzy subpiksele, aby wygenerować biel, czy oznacza to, że naprawdę powinniśmy ustawić czerwone, zielone i niebieskie subpiksele na 33% (85 w systemie dziesiętnym = 0x55 w systemie szesnastkowym), aby uzyskać taką samą jasność jak czerwony piksel?
Pomyślałem, że dobrym pomysłem będzie przetestowanie tego rozwiązania. Jak być może pamiętasz z poprzedniego odcinka, nasze NeoPiksele są połączone ze sobą jako pojedynczy ciąg o numerach od 1 do 144 (jest też „ofiarny” piksel 0, którego używamy jako konwertera poziomu napięcia, ale nie odgrywa on żadnej roli w widocznej części wyświetlacza).
Uważamy, że nasza tablica jest macierzą (X,Y) z pozycjami X (poziomymi) i Y (pionowymi) ponumerowanymi od 0 do 11 oraz z pikselem (0,0) w lewym dolnym rogu. Stworzyliśmy również prostą funkcję o nazwie GetNeoNum(), która przyjmuje wartości X i Y jako argumenty i określa numer odpowiedniego NeoPiksela w łańcuchu.
Jako pierwszy test dla wyjaśnienia zagadki jasności/kontrastu stworzyłem prosty szkic (program), który wypełnia zewnętrzne piksele 100% bielą, a wewnętrzny kwadrat 4×4 pikseli 100% czerwienią (rysunek 1a). Następnie zmniejszamy otaczającą biel do 33%. Następnie szkic wypełnia zewnętrzne piksele w 100% kolorem czerwonym, a wewnętrzny kwadrat w 100% kolorem białym (rysunek 1b). Ponownie zmniejszamy poziom bieli do 33%. Następnie wykonujemy całą sekwencję w kółko. Jeśli chcesz, możesz pobrać ten szkic i zapoznać się z nim w wolnym czasie (jest to plik CB-Aug20-01.txt – dostępny do pobrania, wraz z pozostałymi trzema plikami omówionymi w tej kolumnie, na stronie PE we wrześniu 2020 r.). Dla waszej przyjemności stworzyłem również krótki film pokazujący to wszystko w akcji (www.youtube.com).
Na marginesie, być może pamiętasz, że twórcy biblioteki NeoPixel firmy Adafruit udostępnili nam dwa sposoby określania koloru piksela. Załóżmy, że nasz ciąg nazywa się Neos i że chcemy ustawić kolor powiązany z pikselem 42, aby składowe koloru czerwonego, zielonego i niebieskiego wynosiły odpowiednio 128, 0 i 255 (byłyby to 0x80, 0x00 i 0xFF w systemie szesnastkowym).