2009-11-28 6 views
1

Dernièrement, j'ai été intéressé par la représentation des bitmaps non compressés en mémoire. Cependant, une chose dont je ne suis pas sûr comment implémenter correctement est la transparence binaire. Par exemple, je commence avec quelque chose comme ceci:Comment représenter la transparence binaire?

struct RGBPixel { 
uint8_t red; 
uint8_t green; 
uint8_t blue; 
}; 

struct bitmap { 
struct RGBPixel *data; 
size_t width; 
size_t height; 
size_t bytesPerPixel; 
size_t bytewidth; 
/* etc. */ 
}; 

Je suppose que la façon la plus simple serait:

struct RGBPixel { 
uint8_t red; 
uint8_t green; 
uint8_t blue; 
bool transparent; 
}; 

Mais cela semble un peu inutile (vous pourriez aussi bien ajouter un canal alpha complet) . La seule autre possibilité que je peux penser est de réserver l'une des couleurs comme étant transparente, mais ensuite vous perdez la capacité d'afficher cette couleur. Existe-t-il un moyen standard de le faire?

Comment les formats courants (GIF, PNG 8 bits, etc.) représentent-ils cela?

Répondre

1

Il ya 16M couleurs, en désignant l'un d'entre eux comme transparent ne sera pas une grande difficulté. À moins que votre image ne soit de 16 mégapixels, vous pouvez être sûr qu'elle n'utilisera même pas toutes les couleurs de 16M de toute façon, il suffit d'en choisir une qui n'est pas utilisée et d'en faire la couleur de transparence. Si vous avez une énorme image qui les utilise tous, sélectionnez celle qui est la moins utilisée et remplacez-la par une couleur adjacente, ce qui la rend inutilisée. Comme vous l'avez indiqué, essayer de stocker un seul bit par pixel avec les données RVB de pixel n'est pas efficace. Vous devriez probablement soit stocker tous les pixels RVB dans un pointeur, puis un bitmap des mêmes dimensions H et V dans un autre pointeur, ou vous pouvez faire une incrustation chroma.Vous pouvez stocker les données avec R, G, B et bitmap de transparence séparément comme mentionné ci-dessus, mais c'est généralement très inefficace quand il s'agit de le dessiner.

+0

"il suffit de choisir celui qui n'est pas utilisé et en faire la couleur de transparence." Mais comment puis-je choisir cette couleur? Boucle à travers l'image et continuer à deviner une couleur jusqu'à ce que je trouve celui qui n'est pas utilisé? – Sam

+0

Commencez avec une couleur qui, selon vous, ne sera pas utilisée. En boucle, s'il est utilisé, souvenez-vous du décalage avec le pixmap où vous êtes, changez légèrement la couleur (peut-être incrémentez la valeur B, passez de G à R selon le cas) puis bouclez jusqu'à la fin du pixmap et commencez au début, si vous ne trouvez pas cette couleur, c'est celle-là. Sinon, répétez. Pour améliorer les performances du boîtier d'angle, sélectionnez 256 couleurs qui, selon vous, ne seront pas utilisées au démarrage et recherchez-les simultanément. Les chances de trouver tout sont en cours d'utilisation est assez faible, dans une image 4MP, c'est 1/4^256 ou environ 1 en 1e25. –

1

Gif utilise une couleur spécifiée pour transparent. (par exemple: disons que 0xFFFF00 est transparent, donc tous les pixels avec cette couleur seront affichés comme transparents.) Cette couleur n'a pas pu être utilisée dans cette image.
Png a un canal alpha, c'est-à-dire un autre int qui représente la valeur alpha du pixel. (par exemple: 0 = entièrement transparent, 255 = opaque, 128 = semi-transparent)

+0

De quelle couleur est-il utilisé? – Sam

+1

Gif utilise la couleur indexée et non la couleur directe. Chaque pixel est donc codé comme l'une des 256 couleurs différentes, ce qui constitue un index dans une table de recherche de couleurs rgb. Si vous voulez avoir de la transparence, il vous suffit de réduire l'image à 255 couleurs, puis l'indice restant est utilisé pour indiquer la transparence. –

+0

ce droit @ Southern Hospitality, je voulais seulement montrer les 2 façons de définir certains pixels transparents. – TheHippo

0

Généralement, il existe un quatrième canal alpha pour représenter la transparence.

Au lieu de RBG, vous pouvez avoir RGBA.

0

La transparence binaire est également appelée Incrustation chromatique. Vous définissez une couleur comme couleur transparente et, dans votre fonction de dessin, dessinez un pixel si sa couleur n'est pas la couleur chromatique (couleur transparente désignée).

Le pixel alpha est utilisé lorsque vous effectuez des transparences à plusieurs niveaux, telles que les ombres portées.

0

Vous pouvez stocker la transparence dans la mémoire séparée, ou même stocker chaque canal séparément, par exemple:

struct bitmap { 
uint8_t *red; 
uint8_t *green; 
uint8_t *blue; 
uint8_t *transparency; 
// or packed: uint8_t *RGB, *transparency; 
size_t width; 
size_t height; 
}; 

leur attribuons width*height/8 octets pour le canal de transparence, et en supposant 8 bits par canal de couleur, vous pouvez accéder à des bits comme ceci:

bool get_transparency(struct bitmap* bmp, size_t x, size_t y) { 
    size_t idx = y * bmp->width + x; 
    size_t tidx = idx >> 3; // = idx/8 
    uint8_t t8 = (uint8_t)(idx & 7); // = idx % 8 
    uint8_t mask = 1 << t8; 
    return (bmp->transparency[tidx] & mask) != 0; 
} 

Remarque, l'accès aux bits peut être optimisé, ce n'est qu'un exemple.

Une autre solution: vous pouvez glisser un peu de l'un des canaux de couleur, et de définir votre struct comme ceci:

struct RGBPixel { 
uint8_t red : 7; 
uint8_t transparency : 1; 
uint8_t green; 
uint8_g blue; 
}; 

Lors de la mémorisation ou la lecture du canal rouge, vous avez à l'échelle en conséquence, par exemple red = (uint8_t)(((uint16_t)pix->red * 8)/7);

Questions connexes