Pourquoi répliquer les bits supérieurs de RGB565 lors de la conversion en RGBA8888?

7

J'ai vu dans les bases de code de certains logiciels d'infographie que parfois les bits supérieurs des données d'image au format RGB565 sont répliqués dans les bits inférieurs lors de la conversion au format RGBA8888 à profondeur plus élevée.

J'ai trouvé par exemple le commentaire de l'utilisateur "eq" dans ce fil gamedev.net :

Je préfère répliquer les bits supérieurs dans les bits inférieurs non définis:
R8 = (R5 << 3) | (R5 >> 2);

Cependant, je ne comprends pas la raison derrière.

À quoi sert la réplication de ces bits dans les données converties?

essuyer
la source
1
Sans réplication des bits, les LSB seront à 0, donc pour la valeur maximale de 0x1f (max pour 5 bits), il s'élargirait à 0xf8 lors de la conversion en 8 bits. Ce que vous voulez est 0xff donc la plage de 0x00-> 0x1f sera mappée sur 0x00-> 0xff au lieu de 0x00-> 0xf8.
PaulHK
2
@PaulHK Veuillez poster cela comme réponse. Il est complet en l'état, mais en tant que commentaire, il n'est pas possible de le rechercher.
Dan Hulme
Oui merci @PaulHK cela répond correctement à ma question
essuyez

Réponses:

7

Sans réplication des bits, les LSB seront à 0, donc pour la valeur maximale de 0x1f (max pour 5 bits), elle s'étendrait à 0xf8 lors de la conversion en 8 bits. Ce que vous voulez est 0xff donc la plage de 0x00-> 0x1f sera mappée sur 0x00-> 0xff au lieu de 0x00-> 0xf8. Sans fusionner le LSB, vous ne pourriez pas convertir 0x1f, 0x1f, 0x1f en blanc (0xff, 0xff, 0xff). Soit dit en passant, c'est la même chose que N * 0xff / 0x1f.

Example: 

left shift only (<< 3)
%---00001 -> %00001000     (0x01 -> 0x08)
%---10000 -> %10000000     (0x10 -> 0x80)
%---11111 -> %11111000     (0x1f -> 0xf8)

merging MSB to LSB 
%---00001 -> %00001000     (0x01 -> 0x08)
%---10000 -> %10000100     (0x10 -> 0x84)
$---11111 -> %11111111     (0x1f -> 0xff)
PaulHK
la source
7

Il existe en fait une raison mathématique raisonnablement bonne pour effectuer la réplication de bits:

Notez d'abord que la chaîne de n bits, , représente en fait la valeur et nous voulons produire la chaîne de m bits, , où et NN2n1Mn<m

N2n1M2m1

Nous échelonnons d'abord le numérateur et le dénominateur avec et cela se simplifie en

N.(2n+1)(2n1)(2n+1)M2m1
N.(2n+1)22n1M2m1

Dans votre cas, et et nous pouvons "arrêter" ici, mais mais le processus peut être répété, (ad nauseum), si m >> n.n{5,6}m=8

Nous faisons ensuite l'approximation ... qui simplifie en

N.(2n+1)22nM2m
N.(2n+1)22nmM

Notez que équivaut à répéter la chaîne de n bits, pour créer une chaîne de 2n bits, et la division décale les LSB de pour laisser un résultat de M bits.N.(2n+1)2nm

QED

Bien sûr, le calcul «correct» est mais cette approximation, en général , fonctionne la plupart du temps. Bien sûr, il y a des moments où il est inexact, mais IIRC seulement d'un bit et relativement rarement.M=((2m1)N2n1+12

Simon F
la source
2
Merci pour une explication détaillée avec de belles formules. J'étais curieux de connaître l'erreur introduite par l'approximation, j'ai donc fait ce graphique qui compare les deux formules: desmos.com/calculator/cvaqofyvbf . Cependant, je préfère la réponse de PaulHK car elle est plus facile à comprendre.
essuyez
1
Petit problème, si m> = 2n, vous devez changer votre équation "d'approximation". Par exemple, si n = 1, vous devez répéter la chaîne 8 fois (c.-à-d. Exécuter log2 (8) = 3 étapes). Bien sûr, si vous remplissez avec "10 ... 0" au lieu de tous les zéros, vous aurez en moyenne une erreur plus faible, mais perdez les extrêmes. "Cependant, je préfère la réponse de PaulHK" :-) Eh bien, il n'y a pas de comptabilité pour le goût 8P.
Simon F