Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[LPC1768][SPFD5408B] - ikonki

mariuszterba 19 Maj 2014 13:33 2046 26
  • #1 19 Maj 2014 13:33
    mariuszterba
    Poziom 10  

    Jestem w trakcie opanowywania obsługi TouchPanela opartego na XPT 2046. Na razie obsługa nie jest zbyt profesjonalna bo oparta na pętli while zamiast przerwania, lecz to aktualnie jest mało istotne.
    Napisałem program, która wyświetla ikonę(obrazek) i kiedy zostanie wciśnięty obszar gdzie się znajduję ma zmienić "kolory". Jednak moja funkcja nie jest taka jakbym oczekiwał ponieważ cała ikona w raz z tłem przechodzi w kolory niebieski, bo taki algorytm znalazłem gdzieś w sieci. Oczekiwałbym żeby zachowywała się podobnie jak w windowsie. Jak to zrobić ?
    Main:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    LCD_ShowIcon:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0 26
  • #2 21 Maj 2014 14:35
    mariuszterba
    Poziom 10  

    Pomyślałem, aby zastosować przezroczystość dla ikony która aktualnie jest aktywna korzystam z następującego wzoru aby obliczyć kolor:
    [LPC1768][SPFD5408B] - ikonki
    Kod odpowiedzialny za wyświetlenie wygląda tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dla alfa = 1.0 wyświetlany obraz wygląda tak:
    [LPC1768][SPFD5408B] - ikonki
    a powinno być w miejscu "smug" rysowane tło. Dla alfa > 0 rysowany jest podobnie tylko odcienie się zmieniają.
    Natomiast dla alfa = 0 ikona rysowana jest prawidłowo czyli rysowana jest cała zakrywając tło.
    Gdzie popełniam błąd ?

    0
  • #3 21 Maj 2014 18:08
    el2010tmp
    Poziom 25  

    mariuszterba napisał:
    tmp_kolor = (alfa * (float)kolor_tla) + (1.0 - alfa) * (float)red;
    red = (uint8_t)tmp_kolor;
    tmp_kolor = (alfa * (float)kolor_tla) + (1.0 - alfa) * (float)green;
    green = (uint8_t)tmp_kolor;
    tmp_kolor = (alfa * (float)kolor_tla) + (1.0 - alfa) * (float)blue;
    blue = (uint8_t)tmp_kolor;

    }
    kolor = (red << 11) | (green << 5) | (blue << 0); // skladanie koloru do R5G6B5

    Dlaczego nie maskujesz bitów, tak jak powyżej?
    Przy składaniu w ten sposób musisz mieć gotowe R5G6B5 a nie R5G8B8.

    0
  • #4 21 Maj 2014 20:17
    mariuszterba
    Poziom 10  

    Chyba wiem o co Ci chodzi. Masz na myśli

    Code:
    kolor = ((red << 11) & 0x1F) | ((green << 5) & 0x3F) | ((blue << 0) & 0x1F);

    ?
    Jak wrócę do domu sprawdzę.

    0
  • #5 22 Maj 2014 09:00
    mariuszterba
    Poziom 10  

    Jest lepiej widać zarysy tła ale jeszcze nie to.

    0
  • #6 22 Maj 2014 09:14
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Nie ma się co dziwić, bo ta linijka którą przedstawiłeś jest całkowicie błędna i w efekcie otrzymujesz jedynie składową niebieską.

    Zrób to po prostu porządnie, czyli wg takiego schematu:
    - rozbij piksel na poszczególne składowe,
    - rozbij kolor tła na poszczególne składowe,
    - zmodyfikuj poszczególne składowe piksela i tła używając alfa,
    - zsumuj poszczególne składowe tła z poszczególnymi składowymi piksela (w efekcie uzyskasz nowe składowe punktu na ekranie),
    - złóż składowe w 16-bitową wartość.

    To naprawdę jest proste, tylko Ty połączyłeś i zmiksowałeś ze sobą kroki, przez co w efekcie otrzymujesz bezsens. Porada którą udzielił Ci el2010tmp jest moim zdaniem błędna, choć zacytowany przez niego fragment Twojego kodu oczywiście również jest błędny.

    4\/3!!

    0
  • #7 22 Maj 2014 17:07
    el2010tmp
    Poziom 25  

    Freddie Chopin napisał:
    Porada którą udzielił Ci el2010tmp jest moim zdaniem błędna

    Faktycznie :D
    Nie zauważyłem, kolor_tla również należy rozbić.

    mariuszterba napisał:
    kolor = ((red << 11) & 0x1F) | ((green << 5) & 0x3F) | ((blue << 0) & 0x1F);

    Najpierw maskuj, później przesuwaj.

    0
  • #8 22 Maj 2014 19:02
    mariuszterba
    Poziom 10  

    Udało się, na zdjęciu "ikonki" odpowiedno z alfa równym 0.9, 0.7, 0.4, 0.1:
    [LPC1768][SPFD5408B] - ikonki

    Prawidłowa funkcja wygląda tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Początkowo prototyp funkcji wyglądał tak:
    Code:
    void LCD_ShowIcon2(uint16_t x, uint16_t y, tImage *image, uint8_t stan, float alfa);

    wywoływałem LCD_ShowIcon2( 0, 0 , &rss2, 1, 0.9 ); jednak nie wiedzieć czemu ostatni argument alfa przekazany do funkcji chyba zawierał wartość 0 bo ikona całkowicie zakrywał tło.
    Zmieniłem na postać:
    Code:
    void LCD_ShowIcon2(uint16_t x, uint16_t y, tImage *image, uint8_t stan, float *przezroczystosc);

    wywołuję w podany niżej sposób i działa
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jakieś pomysły dlaczego float przekazany przez wartość działał źle, natomiast przekazany przez wskaźnik prawidłowo ?

    0
  • #9 22 Maj 2014 20:18
    Freddie Chopin
    Specjalista - Mikrokontrolery
  • #10 22 Maj 2014 21:37
    el2010tmp
    Poziom 25  

    mariuszterba napisał:
    // obliczanie przezroczystosci
    tmp_kolor = (alfa * (float)red_tlo) + ((1.0 - alfa) * (float)red);
    red = (uint8_t)tmp_kolor;
    tmp_kolor = (alfa * (float)green_tlo) + ((1.0 - alfa) * (float)green);
    green = (uint8_t)tmp_kolor;
    tmp_kolor = (alfa * (float)blue_tlo) + ((1.0 - alfa) * (float)blue);
    blue = (uint8_t)tmp_kolor;

    kolor = (red << 11) | (green << 5) | (blue << 0); // skladanie koloru do R5G6B5

    Nadal niema maskowania i składowe na młodszych bitach mogą być przekłamane.
    Napisz np.:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Co do float przez wartość to pokaż tą źle działającą wersję bo problem co najmniej "dziwny".

    0
  • #11 22 Maj 2014 23:29
    Freddie Chopin
    Specjalista - Mikrokontrolery

    el2010tmp napisał:
    Nadal niema maskowania i składowe na młodszych bitach mogą być przekłamane.

    Maskowanie jest przecież zbędne. Jeśli alfa ma wartość 0-1 to sumaryczne składowe nigdy nie wyjdą większe niż 5 lub 6 bitów, bo to niemożliwe. Taka zależność wynika wprost z zastosowanego wzoru.

    uint8_t skladowa1 = 0x1F;
    uint8_t skladowa2 = 0x1F;
    float alfa = 0.7;
    uint8_t suma = skladowa1 * alfa + skladowa2 * (1 - alfa);

    suma zawsze będzie mniejsza niż 0x1F jeśli tylko alfa mieści się w zakresie 0-1.

    4\/3!!

    0
  • #12 23 Maj 2014 11:01
    mariuszterba
    Poziom 10  

    Działa przekazywanie float przez wartość. W końcu zrobiłem jawną deklarację void LCD_ShowIcon2(uint16_t x, uint16_t y, tImage *image, uint8_t stan, float alfa); w pliku nagłówkowym i kompilator sypnął błędami w main. Okazało się, że dalej w kodzie miałem stare wywołanie tej funkcji kiedy przekazywanie parametrów kończyło się na stan.

    Chciałbym obsłużyć "pełny" kanał alfa, lecz z prób z LCD Image Conventer wnioskuję że jej nie obsługuję - jak się mylę proszę o wyprowadzenie mnie z błędu.
    Na tapetę poszedł GIMP, wygląda że zapisuję kanał alfa lecz nie rozumiem poniższego zapisu:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Co oznacza zapis \wartość ?

    0
  • #14 23 Maj 2014 13:24
    mariuszterba
    Poziom 10  

    Zapis rozumiem w następujący sposób. Trzy następujące po sobie składowe punktu RED = \377, GREEN = \377, BLUE = \377, następnie wartość kanału alfa ALFA = \0 Reasumując punkt ma kolor biały i nie ma być widoczny bo alfa 0.
    Z tym, że dalszej częśći tablicy mam

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Co oznaczają wartości \244S^, \244M, \246Sl, \253~ ?

    0
  • #15 23 Maj 2014 13:33
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Nic nie oznaczają - to po prostu litery czy znaczki, które przecież mają jakiś kod ASCII. Zapewne w niektórych miejscach użyty jest zapis ósemkowy, bo te znaki akurat nie mają odpowiednika "na klawiaturze". Do zapisu ósemkowego wchodzą tylko 3 cyfry, kolejne znaki są już interpretowane osobno.

    Może da się tam zmienić format kodowania, aby zapisał to jaki tablicę hexów czy coś takiego?

    4\/3!!

    0
  • #16 23 Maj 2014 21:08
    Badmaneq
    Poziom 23  

    mariuszterba napisał:
    Chciałbym obsłużyć "pełny" kanał alfa, lecz z prób z LCD Image Conventer wnioskuję że jej nie obsługuję - jak się mylę proszę o wyprowadzenie mnie z błędu.


    Ależ LCD Image Converter obsługuje kanał alfa. Jest jedno ale, należny w opcjach konwersji zrobić nowy "filtr", który nauczy program jak zapisać przezroczystość.
    W menu Options klikasz Conversion po czym pojawia się okno, w nim w Preset wybierasz Color R8G8B8.
    Później wybierasz zakładkę Matrix, w wierszu Source masz m. in. A7 - A0 zaznaczasz właśnie A7 - A0. Na zaznaczeniu klikasz prawym przyciskiem myszy pojawią się opcje wyboru, wybierz Add "Left Shift" << 0 pojawi się nowy wiersz Operation 4 z wartościami A7 - A0.
    W wierszu Used ustaw wartości 1 dla A7 - A0.
    Teraz zapisz filtr np. pod nazwą Color AR8G8B8.
    W efekcie powinieneś mieć coś podobnego jak na rysunku
    [LPC1768][SPFD5408B] - ikonki

    0
  • #17 25 Maj 2014 21:16
    Samuraj
    Poziom 35  

    mariuszterba napisał:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Proponuje z całego równania wyrzucić float'y. Zobaczysz jaka równica w szybkości działania.

    0
  • #18 26 Maj 2014 12:48
    mariuszterba
    Poziom 10  

    @Samuraj: W jaki sposób pozbyć się liczb zmienno przecinkowych ?

    0
  • #19 26 Maj 2014 13:33
    gaskoin
    Poziom 38  

    Alfe można wyrazić w wartościach 0-255. Tylko, że trzeba podzielić przez 255 wynik tego, co jest przez nią mnożone.

    0
  • #20 26 Maj 2014 14:11
    Samuraj
    Poziom 35  

    I tak tez LCD Image Converter zapisuje alfe.
    Tak na szybko to powinno wyglądać jakoś tak:

    tmp_kolor = ((alfa * green_tlo) + ((255 - alfa) * green))>>8

    0
  • #21 26 Maj 2014 17:16
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Szczególnie to ">> 8" na końcu jest niezbędne, bo kompilator na pewno sam by nie wpadł na taką optymalizację jakby napisac "/ 256".

    4\/3!!

    0
  • #22 27 Maj 2014 10:18
    mariuszterba
    Poziom 10  

    Panowie przy próbie przejścia na liczby całkowite na wyświetlaczu jak się dobrze przyjrzeć pojawia się delikatne przyciemnienie w miejscu gdzie alfa jest równa 0.
    Aktualnie zostałem przy float i funkcja wygląda tak, dla danych wygenerowanych przez LCD Image Converter, gdzie na pierwszej pozycji jest wartość alfa, na drugiej wartość składowej czerwonej, następnie zielonej oraz niebieskiej:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Ikonka jest idealnie przezroczysta tak jak na zdjęciu
    [LPC1768][SPFD5408B] - ikonki

    Natomiast wersja gdzie pojawia się bardzo delikatne przyciemnienie dla wartości alfa równych 0 wygląda tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Maskowanie kolor = ((red & 0x1F) << 11) | ((green & 0x3F) << 5) | (blue & 0x1F) nic nie daje. Nie dołączam zdjęcia ponieważ na zdjęciu nie można dostrzec przyciemnienia.

    0
  • #23 27 Maj 2014 10:24
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Tak się kończą cudowne optymalizacje typu ">> 8". Aby te działania były prawidłowe, dzielić należy przez 255, a nie 256 (co jest równoznaczne z przesunięciem o 8).

    4\/3!!

    0
  • #24 27 Maj 2014 10:38
    gaskoin
    Poziom 38  

    Bo miałeś podzielić przez 255 a nie przez 256.

    Skoro alpha zawiera się w przedziale [0, 1], to 1-alpha zawiera się w przedziale [1, 0]

    No i teraz zmieniasz przedziały:

    Skoro alpha zawiera się w przedziale [0, 255], to 255-alpha zawiera się w przedziale [255, 0] i żeby pasowały przedziały dzielisz przez 255.

    0
  • #25 27 Maj 2014 12:04
    mariuszterba
    Poziom 10  

    Kiedy dzielę przez 255 jest ok.
    "Znalazłem" kolejny problem dla danych wygenerowanych przez LCD Image Converter, mianowicie ich objętość, bo każdy piksel zajmuję aż 4 bajty. Dlatego szukam algorytmu, który nie obciąża uC i da się łatwo zaimplementować.

    0
  • #26 27 Maj 2014 19:28
    Badmaneq
    Poziom 23  

    Kompresja była całkiem niedawno poruszana w temacie https://www.elektroda.pl/rtvforum/viewtopic.php?t=2723046
    Sam wykorzystuję kod, który wymłodził dziechu. LCD Image Converter pozwala korzystać z kompresji RLE. W opcjach programu masz zakładkę Image i tam odhaczasz RLE Compression.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #27 16 Lip 2014 08:54
    mariuszterba
    Poziom 10  

    Dziękuję wszystkim za bardzo pomocne odpowiedzi. Temat zamykam.

    0