如何表示二进制透明度?

问题描述 投票:0回答:5

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

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

c png bitmap transparency gif
5个回答
2
投票

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

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


2
投票

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


1
投票

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

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


0
投票

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

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


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

© www.soinside.com 2019 - 2024. All rights reserved.