Pergunta

Ultimamente eu tenho interesse em representar bitmaps descompactado na memória. No entanto, uma coisa que eu não tenho certeza de como implementar corretamente é a transparência binário. Por exemplo, eu começar com algo como isto:

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

Eu suponho que a maneira mais simples seria a seguinte:

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

Mas isso parece um desperdício de bits (assim como você pode adicionar um canal alfa completo). A única outra possibilidade que eu posso pensar é para reservar uma das cores como sendo transparente, mas, em seguida, você perde a capacidade de exibir essa cor. Existe uma maneira padrão para fazer isso?

Como fazer formatos comuns (GIF, 8-bit PNG, etc.) representam isso?

Foi útil?

Solução

Existem 16 mil cores, designando um deles como vontade transparente não ser um grande sofrimento. A menos que sua imagem é de 16 megapixels, você pode ter certeza que nem sequer usar todas as cores 16M de qualquer maneira, basta escolher um que não é usado e torná-la a cor transparência. Se você tem uma imagem grande que usa-los todos, selecionar o que é menos usado e alterá-lo para uma cor adjacente, tornando-se não utilizado.

Como você indicou, tentando armazenar um único bit por pixel com os dados de pixel RGB não é eficiente. Você provavelmente deve armazenar todos os pixels do RGB em um ponteiro e, em seguida, um bitmap das mesmas H e V dimensões em outro ponteiro, ou você pode fazer chroma key. Você pode armazenar os dados com R, G, B e bitmap transparência separadamente, como mencionado acima, mas que geralmente é muito ineficiente quando se trata de desenhá-lo.

Outras dicas

Gif usa uma cor especificada para transparente. (Por exemplo .: digamos 0xFFFF00 é transparente, para que todos os pixels com esta cor será exibido como transparente.) Esta cor não poderia ser usado nesta imagem.
PNG tem um canal alfa, o que significa uma outra int que representa o valor alfa do pixel. (Por exemplo: 0 = totalmente transparente, opaco 255 =, 128 = semi-transparente)

Normalmente existe um quarto canal alfa para representar a transparência.

i. em vez de RBG, você pode ter RGBA.

transparência

binário também é chamado Chroma Keying. Você designa uma cor como a cor transparente e em sua função de desenho desenhar um pixel se a sua cor não é a chave chroma (cor transparente designado).

Por alfa pixel é usado quando você faz transparência multi-nível, como sombras.

Você pode armazenar a transparência na memória separado, ou mesmo armazenar cada canal separadamente, por exemplo:.

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

Em seguida, alocar width*height / 8 bytes para o canal de transparência, e assumindo 8 bits por canal de cor você pode acessar os bits assim:

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

Note, acessar os bits podem ser otimizados, este é apenas um exemplo.

Outra solução: você pode roubar um pouco de um dos canais de cor, e definir a sua estrutura como esta:

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

Quando guardar ou lendo o canal vermelho, você tem que escala em conformidade, por exemplo, red = (uint8_t)( ( (uint16_t)pix->red * 8 ) / 7 );

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top