Domanda

Ultimamente mi sono interessato a rappresentare bitmap non compresse in memoria. Tuttavia, una cosa che non sono sicuro di come implementare correttamente è la trasparenza binaria. Ad esempio, inizio con qualcosa del genere:

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. */
};

Suppongo che il modo più semplice sarebbe questo:

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

Ma sembra un po 'dispendioso (potresti anche aggiungere un canale alfa completo). L'unica altra possibilità a cui riesco a pensare è quella di riservare uno dei colori come trasparente, ma poi perdi la possibilità di visualizzare quel colore. Esiste un modo standard per farlo?

In che modo rappresentano i formati comuni (GIF, PNG a 8 bit, ecc.)

È stato utile?

Soluzione

Ci sono 16 milioni di colori, designandone uno trasparente non sarà un grosso problema. A meno che la tua immagine non sia di 16 megapixel, puoi essere sicuro che non usa nemmeno tutti i colori da 16M, basta sceglierne uno che non viene utilizzato e renderlo il colore della trasparenza. Se disponi di un'immagine enorme che le utilizza tutte, seleziona quella meno utilizzata e modificala in un colore adiacente, rendendola inutilizzata.

Come hai indicato, il tentativo di memorizzare un singolo bit per pixel con i dati pixel RGB non è efficiente. Probabilmente dovresti o memorizzare tutti i pixel RGB in un puntatore e quindi una bitmap delle stesse dimensioni H e V in un altro puntatore, oppure puoi eseguire il chroma keying. È possibile archiviare i dati con R, G, B e bitmap di trasparenza separatamente come indicato sopra, ma in genere è molto inefficiente quando si tratta di disegnarli.

Altri suggerimenti

Gif usa un colore specificato per il trasparente. (ad es .: supponiamo che 0xFFFF00 sia trasparente, quindi tutti i pixel con questo colore verranno visualizzati come trasparenti.) Questo colore non può essere usato in questa immagine.
Png ha un canale alfa, che significa un altro int che rappresenta il valore alfa del pixel. (ad esempio: 0 = completamente trasparente, 255 = opaco, 128 = semitrasparente)

Comunemente esiste un quarto canale alfa per rappresentare la trasparenza.

vale a dire. invece di RBG, puoi avere RGBA.

La trasparenza binaria è anche chiamata Chroma Keying. Si designa un colore come colore trasparente e nella funzione di disegno si disegna un pixel se il suo colore non è la chiave di crominanza (designato colore trasparente).

L'alfa per pixel viene utilizzata quando si esegue la trasparenza a più livelli, ad esempio ombreggiature.

È possibile memorizzare la trasparenza in una memoria separata o persino memorizzare ciascun canale separatamente, ad esempio:

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;
};

Quindi alloca width * height / 8 byte per il canale di trasparenza, e ipotizzando 8 bit per canale di colore puoi accedere ai bit in questo modo:

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;
}

Nota, l'accesso ai bit può essere ottimizzato, questo è solo un esempio.

Un'altra soluzione: puoi scorrere un po 'di uno dei canali di colore e definire la tua struttura in questo modo:

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

Quando si memorizza o si legge il canale rosso, è necessario ridimensionare di conseguenza, ad es. red = (uint8_t) (((uint16_t) pix- > red * 8) / 7);

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top