Pregunta

Últimamente me ha interesado representar mapas de bits sin comprimir en la memoria. Sin embargo, una cosa que no estoy seguro de cómo implementar correctamente es la transparencia binaria. Por ejemplo, empiezo con algo como esto:

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

Supongo que la forma más sencilla sería esta:

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

Pero eso parece un poco inútil (también podría agregar un canal alfa completo). La única otra posibilidad que se me ocurre es reservar uno de los colores como transparente, pero luego se pierde la capacidad de mostrar ese color. ¿Hay una manera estándar de hacer esto?

¿Cómo representan esto los formatos comunes (GIF, PNG de 8 bits, etc.)?

¿Fue útil?

Solución

Hay 16 millones de colores, designar uno de ellos como transparente no será una gran dificultad. A menos que su imagen sea de 16 megapíxeles, puede estar seguro de que ni siquiera usa todos los colores de 16M de todos modos, solo elija uno que no se use y conviértalo en el color de transparencia. Si tiene una imagen enorme que los usa a todos, seleccione la que menos se usa y cámbiela a un color adyacente, dejándola sin usar.

Como indicó, tratar de almacenar un solo bit por píxel con los datos de píxel RGB no es eficiente. Probablemente debería almacenar todos los píxeles RGB en un puntero y luego un mapa de bits de las mismas dimensiones H y V en otro puntero, o puede hacer una incrustación de croma. Puede almacenar los datos con R, G, B y mapa de bits de transparencia por separado como se mencionó anteriormente, pero eso generalmente es muy ineficiente cuando se trata de dibujarlos.

Otros consejos

Gif usa un color específico para transparente. (por ejemplo: supongamos que 0xFFFF00 es transparente, por lo que todos los píxeles con este color se mostrarán como transparentes). Este color no se pudo usar en esta imagen.
Png tiene un canal alfa, eso significa otro int que representa el valor alfa del píxel. (por ejemplo: 0 = totalmente transparente, 255 = opaco, 128 = semitransparente)

Comúnmente hay un cuarto canal Alfa para representar la transparencia.

es decir, en lugar de RBG, puede tener RGBA.

La transparencia binaria también se llama Chroma Keying. Usted designa un color como el color transparente y en su función de dibujo dibuja un píxel si su color no es la clave de croma (color transparente designado).

Se utiliza alfa por píxel cuando se realiza una transparencia de varios niveles, como sombras paralelas.

Puede almacenar la transparencia en una memoria separada, o incluso almacenar cada canal por separado, por ejemplo:

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

Luego asigne width * height / 8 bytes para el canal de transparencia, y suponiendo 8 bits por canal de color, puede acceder a los bits de esta manera:

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

Tenga en cuenta que el acceso a los bits se puede optimizar, esto es solo un ejemplo.

Otra solución: puede deslizar un poco uno de los canales de color y definir su estructura de esta manera:

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

Al almacenar o leer el canal rojo, debe escalar en consecuencia, p. red = (uint8_t) (((uint16_t) pix- > red * 8) / 7);

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top