Zapis/Odczyt 6 bitowej struktury

0

Witam.
Robię zadanie na grafikę komputerową i napotkałem na problem. Muszę zapisać dane koloru (RGB -> 2 bity na pixel). Problem w tym, że nie mogę uzupełnić składowej zerami, aby dana zawierała jeden bajt. W chwili obecnej mam strukturę:

struct kolor {
unsigned r:2;
unsigned g:2;
unsigned b:2;
unsigned wolna:2;

}; 

Jednak muszę z niej wyrzucić ostatnią składową i jakoś mądrze to zapisać. Dane mapy bitowej przechowuję w tablicy

 kolor tablica_pixeli[3000000];

odczytywanej metodą scanline. Plik zawiera dane binarne z tablicy wyrzucone przez funkcję

 pliczek.write((char *) &buffer, sizeof(struct kolor)); 

W jaki sposób przejść na 6 bitów? Słyszałem o przesunięciu bitowym. Jest gdzieś to dobrze wyjaśnione?
Pozdrawiam,
Grzegorz

0

Niestety, nie ma bezpośrednio takiej możliwości. Tablicę i tak musisz traktować jako zespół 8-bitowych bajtów, więc żeby zapisać 6 bitów musisz najpierw wyliczyć prawdziwy (bajtowy) indeks w tablicy, i zmodyfikować jeden lub dwa bajty (bo twoje 6 bitów może trafiać na granicy dwóch bajtów).

0

Jeśli dobrze rozumiem, to Twoim zadaniem jest upakowanie 6-bitowych kawałków w ciągłej przestrzeni pamięci, tak, aby każdy z tych kawałków znajdował się obok siebie. Już na samym początku należy zauważyć, że tworzenie struktur o rozmiarze mniejszym niż jeden bajt jest praktycznie niemożliwe (czytaj: http://stackoverflow.com/questions/4626815/why-is-a-boolean-1-byte-and-not-1-bit-of-size).

Proponuję następujące rozwiązanie: należy zauważyć, że w przestrzeni 3 bajtów (24 bity) zmieszczą się 4 kawałki naszej małej struktury "kolor". Wyszukanie konkretnego i-tego koloru w tej tablicy będzie się sprowadzało do znalezienia takiego 3-bajtowego obszaru i wyłuskanie go za pomocą pewnych operacji na bitach. Aktualizacja danych i-tego koloru sprowadza się natomiast do znalezienia owego 3-bajtowego obszaru i wpakowanie do niego 6 bitów znowu za pomocą odpowiednich operacji na bitach.

Nie chciałbym Cię wyręczać w tej ciekawej (z perspektywy programisty) zabawie, więc spróbuj sam dojść do tego, jak zrealizować powyższe operacje. W razie problemów - pytaj.

0

W mojej implementacji operujemy na najmniejszym możliwym typie, który zmieści nasze cztery kolory, czyli int. Stąd rozmiar bufora musi być wielokrotnością 4 bajtów.

color_t GetColor(unsigned char* buffer, size_t idx)
{
    unsigned int masks[] = { 0x3f, 0xfc0, 0x3f000, 0xfc0000 };

    size_t chunk_offset = (idx / 4) * 3;
    unsigned int chunk = *reinterpret_cast<unsigned int*>(buffer + chunk_offset);

    size_t color_offset = idx % 4;
    unsigned char value = (chunk & masks[color_offset]) >> (color_offset * 6);

    return *reinterpret_cast<color_t*>(&value);
}
0
hfaua napisał(a):

Jeśli dobrze rozumiem, to Twoim zadaniem jest upakowanie 6-bitowych kawałków w ciągłej przestrzeni pamięci, tak, aby każdy z tych kawałków znajdował się obok siebie. Już na samym początku należy zauważyć, że tworzenie struktur o rozmiarze mniejszym niż jeden bajt jest praktycznie niemożliwe (czytaj: http://stackoverflow.com/questions/4626815/why-is-a-boolean-1-byte-and-not-1-bit-of-size).

Proponuję następujące rozwiązanie: należy zauważyć, że w przestrzeni 3 bajtów (24 bity) zmieszczą się 4 kawałki naszej małej struktury "kolor". Wyszukanie konkretnego i-tego koloru w tej tablicy będzie się sprowadzało do znalezienia takiego 3-bajtowego obszaru i wyłuskanie go za pomocą pewnych operacji na bitach. Aktualizacja danych i-tego koloru sprowadza się natomiast do znalezienia owego 3-bajtowego obszaru i wpakowanie do niego 6 bitów znowu za pomocą odpowiednich operacji na bitach.

Nie chciałbym Cię wyręczać w tej ciekawej (z perspektywy programisty) zabawie, więc spróbuj sam dojść do tego, jak zrealizować powyższe operacje. W razie problemów - pytaj.

Zapomniałem napisać, że do programu dochodzi mi kompresja byterun(narzucone w treści zadania) :-) Muszę zaoszczędzać jak najwięcej miejsca.

Jeżeli dobrze rozumiem to dobrym krokiem będzie:

  • usunięcie elementu wolna
  • zapis do pliku 4 struktur, przez co ich rozmiar wyniesie 3 bajty (pytanie teraz w co upakować :) )
  • przy odczycie wczytywać po 3 bajty i operacjami na bitach dostać się do danych (może ktoś mi polecić jakieś dobre materiały o tym? )

Jak więc załatwić tu problem kompresji byterun?

0

Załóżmy ,że masz zwykłą zmienną typu char(8 bitów). Zrób tak aby jej 6 bitów najmłodszych zawierała interesujące dane. Od najstarszego bitu(6 bit) do najmłodszego(1 bit) w kolejności R, G, B. Później iteruj przez te 6 bitów i za pomocą andowania sprawdź które bity są ustawione. Będzie to wyglądać mniej więcej tak:
char --> 01010101
Powyżej jest przykładowa zmienna typu char.
Musisz iterować od prawej do lewej i sprawdzać który bit jest ustawiony i później zinterpretować te 2 bity i wynik wsadzić do chara(maksymalna wartość będzie wynosić 3). Zatem wyjdą tak jakby 3 zmienne typu char które będa zawierać wartości od 0-3. Jeśli będziesz chciał zapisać do tej zmiennej po 2 bity dla RGB postąpisz analogicznie jak przy interpretowaniu tego.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.