이진 투명성을 나타내는 방법은 무엇입니까?
-
06-07-2019 - |
문제
최근에 나는 메모리에서 압축되지 않은 비트 맵을 나타내는 데 관심이있었습니다. 그러나 제대로 구현하는 방법을 잘 모르겠습니다. 이진 투명성입니다. 예를 들어, 나는 다음과 같은 것으로 시작합니다.
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. */
};
가장 간단한 방법은 다음과 같습니다.
struct RGBPixel {
uint8_t red;
uint8_t green;
uint8_t blue;
bool transparent;
};
그러나 그것은 약간 낭비적인 것 같습니다 (당신은 전체 알파 채널을 추가 할 수도 있습니다). 내가 생각할 수있는 유일한 가능성은 색상 중 하나를 투명한 것으로 예약하는 것이지만, 그 색상을 표시하는 능력을 잃어 버리는 것입니다. 이 작업을 수행하는 표준 방법이 있습니까?
일반적인 형식 (GIF, 8 비트 PNG 등)은 이것을 어떻게 표현합니까?
해결책
16m 색상이 있으며 그중 하나를 투명하게 지정하는 것은 큰 어려움이 아닙니다. 이미지가 16 메가 픽셀이 아닌 한, 어쨌든 16m 색상을 모두 사용하지 않아도 사용하지 않은 색상을 선택하고 투명도 색상으로 만들 수 있습니다. 모두 사용하는 거대한 이미지가있는 경우 사용되지 않은 이미지를 선택하여 인접한 색상으로 변경하여 사용하지 않습니다.
지시 한 바와 같이, 픽셀 RGB 데이터로 픽셀 당 단일 비트를 저장하는 것은 효율적이지 않습니다. 아마도 모든 RGB 픽셀을 한 포인터에 저장 한 다음 다른 포인터에 동일한 H 및 V 치수의 비트 맵을 저장하거나 크로마 키링을 수행 할 수 있습니다. 위에서 언급 한 것처럼 데이터를 R, G, B 및 Transparency Bitmap과 함께 저장할 수 있지만 일반적으로이를 그릴 때 매우 비효율적입니다.
다른 팁
GIF는 투명에 지정된 색상을 사용합니다. (예 : 0xffff00이 투명하다고 가정 해 보겠습니다. 따라서이 색상이있는 모든 픽셀은 투명하게 표시됩니다.)이 색상은이 이미지에서 사용할 수 없습니다.
PNG에는 알파 채널이 있습니다. 즉, 픽셀의 알파 값을 나타내는 또 다른 int를 의미합니다. (예 : 0 = 완전히 투명, 255 = 불투명, 128 = 반 트랜스 펜트)
일반적으로 투명성을 나타내는 네 번째 알파 채널이 있습니다.
즉, RBG 대신 RGBA를 가질 수 있습니다.
이진 투명성을 Chroma Keying이라고도합니다. 색상을 투명한 색상으로 지정하고 드로잉 기능에서 색상이 Chroma 키 (지정된 투명한 색상)가 아닌 경우 픽셀을 그립니다.
픽셀 당 알파는 드롭 그림자와 같은 다단계 투명성을 수행 할 때 사용됩니다.
투명성을 별도의 메모리에 저장하거나 각 채널을 개별적으로 저장할 수도 있습니다.
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;
};
그런 다음 할당하십시오 width*height / 8
투명도 채널의 바이트 및 컬러 채널 당 8 비트를 가정하면 다음과 같은 비트에 액세스 할 수 있습니다.
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;
}
비트에 액세스하는 것은 최적화 될 수 있습니다. 이것은 예입니다.
또 다른 해결책 : 컬러 채널 중 하나를 약간 스 와이프하고 구조물을 다음과 같이 정의 할 수 있습니다.
struct RGBPixel {
uint8_t red : 7;
uint8_t transparency : 1;
uint8_t green;
uint8_g blue;
};
빨간색 채널을 저장하거나 읽을 때는 그에 따라 스케일링해야합니다. red = (uint8_t)( ( (uint16_t)pix->red * 8 ) / 7 );