1

最近我对在内存中表示未压缩的位图很感兴趣。但是,我不确定如何正确实施的一件事是二进制透明度。例如,我从这样的事情开始:

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

但这似乎有点浪费(您不妨添加一个完整的 Alpha 通道)。我能想到的唯一另一种可能性是将其中一种颜色保留为透明,但随后您将失去显示该颜色的能力。有没有标准的方法来做到这一点?

常见格式(GIF、8 位 PNG 等)如何表示这一点?

4

5 回答 5

1

有1600万种颜色,指定其中一种为透明不会是什么大难事。除非您的图像是 16 兆像素,否则您可以确定它甚至不会使用所有 1600 万种颜色,只需选择一种未使用的颜色并将其设置为透明色。如果您确实有一张使用它们的巨大图像,请选择使用最少的图像并将其更改为相邻的颜色,使其未使用。

正如您所指出的,尝试使用像素 RGB 数据存储每个像素的单个位效率不高。您可能应该将所有 RGB 像素存储在一个指针中,然后将相同 H 和 V 尺寸的位图存储在另一个指针中,或者您可以进行色度键控。如上所述,您可以使用 R、G、B 和透明度位图分别存储数据,但是在绘制数据时通常效率很低。

于 2009-11-28T16:50:15.437 回答
1

Gif 使用指定的颜色来表示透明。(例如:假设 0xFFFF00 是透明的,因此具有此颜色的所有像素都将显示为透明。)此颜色无法在此图像中使用。
Png 有一个 alpha 通道,这意味着另一个 int 表示像素的 alpha 值。(例如:0 = 完全透明,255 = 不透明,128 = 半透明)

于 2009-11-28T15:07:51.027 回答
0

二进制透明度也称为色度键控。您将一种颜色指定为透明颜色,并在绘图函数中绘制一个像素,如果其颜色不是色度键(指定透明颜色)。

当您进行多级透明度(例如阴影)时,将使用每像素 Alpha。

于 2009-11-28T15:22:39.500 回答
0

您可以将透明度存储在单独的内存中,甚至可以单独存储每个通道,例如:

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

于 2009-11-28T15:36:31.110 回答
0

通常有第四个 Alpha 通道来表示透明度。

即,而不是RBG,你可以有RGBA。

于 2009-11-28T15:09:42.257 回答