|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1843
|
[C] Convertire RGB 32 bit a RGB 16 bit. Mi aiutate a capire il problema?
Devo fare questo esercizio ma non credo di averlo capito bene (indipendentemente dal linguaggio che comunque è il C):
Implementare la funzione: unsigned short ConvertRGB(unsigned int colorRGB); - colorRGB è il colore a 32 bit che si vuole convertire. - colorRGB è così formato: 8 bit di empty padding, 8 bit rosso, 8 bit verde, 8 bit blu - il colore restituito deve essere: 5 bit rosso, 6 bit verde, 5 bit blu Poi mi indica nei suggerimenti che in esadecimale RED:0x00FF0000, GREEN 0x0000FF00, BLUE 0x000000FF, WHITE 0x00FFFFFF, BLACK 0X00000000. Ora, il problema in cosa consiste? Io ho in memoria un unsigned int che contiene all'interno nei diversi byte i valori r,g,b e siccome sono blocchi di 8 bit saranno valori tra 0 e 255. Io devo convertirli in 5 bit per rosso e blu, cioè in valori da 0 a 31 ed in 6 bit il verde, cioè da 0 a 63. Supponiamo che esegua semplicemente delle proporzioni trasformando i numeri nel nuovo formato, poi come li memorizzo nel blocco di memoria corretto lavorando su un unico unsigned short? |
![]() |
![]() |
![]() |
#2 | |
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1843
|
Quote:
Ci sto ancora lavorando su ma l'and per cosa dovrebbe servire? |
|
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1843
|
Ho scritto questa porzione di codice:
Codice:
//0x (padding) (red) (green) (blue) unsigned int colorRGB = 0x00010203; colorRGB <<= 8; _Uint32t red = colorRGB >> 24; _Uint32t green = (colorRGB >> 16) & 0xff; _Uint32t blue = (colorRGB >> 8) & 0x0ff; cout << "Red: " << red << endl << endl; cout << "Green: " << green << endl << endl; cout << "Blue: " << blue << endl << endl; Però questo codice l'ho trovato su internet e non capisco esattamente l'and a cosa serva. Mi dovrebbe annullare il valore dei bit inutili ma l'and non mi pare possa fare questo (eppure funziona quindi non ho capito qualcosa). Se io ho un int iniziale di 32 bit e voglio prendere i bit da 8 a 16 eseguo uno switch a destra di 16 in modo da ritrovarmi i miei 8 bit a destra e poi i bit da 0 a 8 subito a sinistra. Questi bit da 0 a 8 poi li voglio annullare perchè non fanno parte dei bit che mi interessano e qui mi pare che si esegua l'and ma l'and con 0xff (cioè otto 1) da quello che so lascerebbe a 1 i bit già ad 1 ed a 0 i bit già a 0, dunque non cambierebbe niente. |
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1843
|
Quote:
11000011 & 0xf mi restituisce 00000011. Pensavo di dover iniziare da sinistra, quindi che 0xf fosse incolonnato con i primi due 1 e dunque restituisse 11000000 ma effettivamente non ha troppo senso. Ok adesso penso di aver capito, mi complica un po' la vita il fatto di dover convertire il rosso ed il blu in 5 bit mentre il verde in 6 però penso di potercela fare. Tanto per la cronaca avevo 15 minuti per fare questo esercizio, ci sono dietro da stamattina! ![]() I bitfield li studierò a parte, per ora questo esercizio è meglio che lo finisca così perchè nei test che mi hanno messo davanti ultimamente gli shift e gli and vengono usati moltissimo quindi è bene che mi abitui a gestirli. Grazie dell'aiuto, poi se finisco posto il codice. |
|
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
A me è venuta in mente una cosa del genere, non so quanto sia portabile però, per via dell'endianess.
Codice:
#include <stdio.h> #include <inttypes.h> union { uint32_t value; struct { uint8_t blue; uint8_t green; uint8_t red; uint8_t pad; } rgb; } color; int main(int argc, char *argv[]) { color.value = 0x00AABBCC; printf("rgb: %08x\n", color.value); printf("pad: %02x\n", color.rgb.pad); printf("red: %02x\n", color.rgb.red); printf("green: %02x\n", color.rgb.green); printf("blue: %02x\n", color.rgb.blue); return 0; }
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1843
|
Ok, ho finito. L'ho testata un po' e sembra dare il risultato corretto.
Ci saranno probabilmente modi più prestanti ed ora mi toccherà cercarli ma almeno mi sono studiato un po' di masking perchè ero veramente a secco. Codice:
//0x (padding) (red) (green) (blue) unsigned int colorRGB = 0x00533498; cout << "Color: " << bitset<32>(colorRGB) << endl << endl; //shinfting left of 8 positions to discard the first 8 bits used for padding colorRGB <<= 8; //storing the components of the RGB color _Uint32t red = colorRGB >> 24; _Uint32t green = (colorRGB >> 16) & 0xff; _Uint32t blue = (colorRGB >> 8) & 0x0ff; unsigned short convertedRGB = 0; //converting to 5 and 6 bits red >>= 3; //red will be stored in 5 bits green >>= 2; //green will be stored in 6 bits blue >>= 3; //blue will be stored in 5 bits cout << "------ 16 bit converted color components: " << endl << endl; cout << "Red: " << bitset<32>(red) << endl; cout << "Green: " << bitset<32>(green) << endl; cout << "Blue: " << bitset<32>(blue) << endl; cout << "-------------------- " << endl << endl; //positioning correctly the significant bits of r, g, b to operate a OR red <<= 11; //red must occupy positions 16-20 in the 32 bits long number green <<= 5; //green must occupy positions 21-26 in the 32 bits long number //blue = blue; //blue must occupy positions 27-31 in the 32 bits long number cout << "------ Shifted color components: " << endl << endl; cout << "Red: " << bitset<32>(red) << endl; cout << "Green: " << bitset<32>(green) << endl; cout << "Blue: " << bitset<32>(blue) << endl; cout << "-------------------- " << endl << endl; //obtaining the final converted RGB convertedRGB = red | green | blue; cout << "Color converted: " << bitset<16>(convertedRGB) << endl << endl; |
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Quote:
grazie comunque
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
|
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1843
|
Sto guardando la versione con i bitfields, sembra interessante l'idea.
Cosa significa? uint32 padding:8; A me mentre scrivevo il codice con le Union era venuto da usare degli uint8 invece che 32. |
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1843
|
Quote:
Ho scritto il codice usando i bitfields ma il risultato è sbagliato anche se di poco (c'è un bit a 0 di troppo). Codice:
union color32 { UINT32 value; struct { UINT32 padding:8; UINT32 red:8; UINT32 green:8; UINT32 blue:8; }; }; union color16 { UINT16 value; struct { UINT16 red:5; UINT16 green:6; UINT16 blue:5; }; }; int _tmain(int argc, _TCHAR* argv[]) { //0x (padding) (red) (green) (blue) //int (padding) (83) (52) (152) //expected result: 01010 001101 10011 unsigned int RGB32 = 0x00533498; cout << "Color: " << bitset<32>(RGB32) << endl << endl; //shift the color left to discard the padding RGB32 <<= 8; color32 color; color.value = RGB32; cout << "Color: " << bitset<32>(color.value) << endl << endl; color16 converted; converted.red = color.red/8; converted.green = color.green/8; converted.blue = color.blue/8; cout << "Color converted: " << bitset<16>(converted.value) << endl << endl; system("pause"); return 0; } Ultima modifica di -Ivan- : 11-11-2013 alle 17:38. |
|
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1843
|
Ok, così è corretta:
Codice:
//0x (padding) (red) (green) (blue) //int (padding) (83) (52) (152) //expected result: 01010 001101 10011 unsigned int RGB32 = 0x00533498; cout << "Color: " << bitset<32>(RGB32) << endl << endl; //shift the color left to discard the padding RGB32 <<= 8; color32 color; color.value = RGB32; color16 converted; converted.red = color.red >> 3; converted.green = color.green >> 2; converted.blue = color.blue >> 3; cout << "Color converted: " << bitset<16>(converted.value) << endl << endl; |
![]() |
![]() |
![]() |
#11 | |
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1843
|
Quote:
Stasera farò altri esercizi con le union e magari capisco se ho commesso qualche errore quando avrò più chiaro il meccanismo. Grazie. |
|
![]() |
![]() |
![]() |
#12 | |
Senior Member
Iscritto dal: Mar 2003
Città: Rimini
Messaggi: 1843
|
Quote:
![]() Ora ho modificato e funziona. Dunque, giusto per conferma se io volessi usare le union per poter avere un campo long potendo accedere anche alle sue parti considerandolo spezzato in 2 sarebbe: Codice:
union { long value; struct { int low; int high; } }; Grazie. |
|
![]() |
![]() |
![]() |
#13 | |
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Quote:
bitfields
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" Ultima modifica di Oceans11 : 12-11-2013 alle 13:52. Motivo: ref. |
|
![]() |
![]() |
![]() |
#14 |
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Non usate mai i bitfield, a meno che non sappiate come vengono gestiti dal compilatore, conoscete l'endianess del processore, ma soprattutto esattamente dove dovrà girare l'applicazione.
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
A te. La realtà è ben diversa. Vedi il tuo commento #21.
![]()
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
![]() |
![]() |
![]() |
#16 |
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
Gli errori capitano normalmente: a maggior ragione con cose il cui comportamento dipende da fattori esterni (alla rigorosa definizione del linguaggio).
I bitfield rientrano pienamente in questa categoria: evitateli.
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
![]() |
![]() |
![]() |
#17 | ||
Senior Member
Iscritto dal: Jan 2002
Città: Germania
Messaggi: 26110
|
E infatti si vede come si comporta bene coi colori...
Davvero, faccio fatica a credere che una delle caratteristiche meno portabili in assoluto sia fatta passare come l'esatto opposto, quando: - non è noto quanti bit verranno effettivamente riservati per un campo; - non è noto se il compilatore aggiungerà padding all'inizio e/o alla fine di ogni campo; - non è noto se il compilatore allocherà i campi di bit partendo dall'MSB o dall'LSB; - non è noto se l'int sarà con o senza segno; - dulcis in fundo, il compilatore potrebbe benissimo ignorare tutto e utilizzare una struct per implementare i campi di bit. A maggior ragione se vengono utilizzati per manipolare la memoria (ad esempio registri hardware mappati in memoria), bisognerebbe evitarli. Comunque visto che l'hai tirato in ballo, riporto cosa ne pensa lo standard ISO C. Quote:
![]() Quote:
__________________
Per iniziare a programmare c'è solo Python con questo o quest'altro (più avanzato) libro @LinkedIn Non parlo in alcun modo a nome dell'azienda per la quale lavoro Ho poco tempo per frequentare il forum; eventualmente, contattatemi in PVT o nel mio sito. Fanboys |
||
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 18:00.