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

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 等)如何表示这一点?

有帮助吗?

解决方案

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

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

其他提示

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

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

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

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

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

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

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-&gt; red * 8)/ 7);

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top