如何表示二进制透明度?

发布于 2024-08-13 00:19:09 字数 553 浏览 7 评论 0原文

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

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

Lately I've been interested in representing uncompressed bitmaps in memory. However, one thing I'm not sure how to implement properly is binary transparency. E.g., I start out with something like this:

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

I suppose the simplest way would be this:

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

But that seems a bit wasteful (you might as well add a full alpha channel). The only other possibility I can think of is to reserve one of the colors as being transparent, but then you lose the ability to display that color. Is there a standard way to do this?

How do common formats (GIF, 8-bit PNG, etc.) represent this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

无戏配角 2024-08-20 00:19:09

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

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

There are 16M colors, designating one of them as transparent will not be a big hardship. Unless your image is 16 megapixels, you can be sure it doesn't even use all 16M colors anyway, just pick one that isn't used and make it the transparency color. If you do have a huge image that uses them all, select the one that is least used and change it to an adjacent color, making it unused.

As you indicated, trying to store a single bit per pixel with the pixel RGB data isn't efficient. You should probably either store all the RGB pixels in one pointer and then a bitmap of the same H and V dimensions in another pointer, or you can do chroma keying. You could store the data with R,G,B and transparency bitmap separately as mentioned above but that's generally very inefficient when it comes to drawing it.

扎心 2024-08-20 00:19:09

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

Gif uses a specified color for transparent. (e.g.: lets say 0xFFFF00 is transparent, so all pixels with this color will be display as transparent.) This color could not be used in this image.
Png has an alpha channel, that means another int which represents the alpha value of the pixel. (e.g: 0 = fully transparent, 255 = opaque, 128 = half-transparent)

小姐丶请自重 2024-08-20 00:19:09

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

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

Binary transparency is also called Chroma Keying. You designate a colour as the transparent colour and in your drawing function draw a pixel if its colour is not the chroma key (designated transparent colour).

Per pixel alpha is used when you do multi-level transparency such as drop shadows.

待"谢繁草 2024-08-20 00:19:09

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

即您可以使用 RGBA 来代替 RBG。

Commonly there is a fourth Alpha channel to represent transparency.

i.e. instead of RBG, you can have RGBA.

依 靠 2024-08-20 00:19:09

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

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->红色 * 8 ) / 7 );

You could store the transparency in separate memory, or even store each channel separately, e.g.:

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

Then allocate width*height / 8 bytes for the transparency channel, and assuming 8 bits per color channel you can access the bits like this:

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, accessing the bits can be optimized, this is just an example.

Another solution: you could swipe a bit of one of the color channels, and define your struct like this:

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

When storing or reading the red channel, you have to scale accordingly, e.g. red = (uint8_t)( ( (uint16_t)pix->red * 8 ) / 7 );

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文