3

我试图了解从中获得的数据XGetImage是如何在内存中处理的:

XImage img = XGetImage(display, root, 0, 0, width, height, AllPlanes, ZPixmap);

现在假设我想分解红色、蓝色、绿色通道中的每个像素值。我怎样才能以便携的方式做到这一点?以下是一个示例,但它取决于 XServer 的特定配置,并且并非在所有情况下都有效:

for (int x = 0; x < width; x++)
    for (int y = 0; y < height; y++) {
        unsigned long pixel = XGetPixel(img, x, y);   
        unsigned char blue = pixel & blue_mask;
        unsigned char green = (pixel & green_mask) >> 8;
        unsigned char red = (pixel & red_mask) >> 16;
        //...    
    }

在上面的示例中,我假设RGB通道的特定顺序pixel以及像素是 24 位深度:事实上,我有img->depth=24img->bits_per_pixels=32(屏幕也是 24 位深度)。但这不是一般情况。

作为第二步,我想摆脱 XGetPixel 并直接使用或描述 img->data。我需要知道的第一件事是,是否有任何东西Xlib可以准确地为我提供解释图像是如何从img->data现场开始构建所需的所有信息,它们是:

  1. 每个像素中 R、G、B 通道的顺序;
  2. 每个像素的位数;
  3. 每个通道的位数;
  4. 如果可能,相应的FOURCC
4

2 回答 2

4

shift 是掩码的一个简单函数:

    int get_shift (int mask) {
      shift = 0;
      while (mask) {
        if (mask & 1) break;
        shift++;
        mask >>=1;
      }
      return shift;
    }

每个通道中的位数只是其掩码中的 1 位数(计算它们)。通道顺序由移位确定(如果红移为 0,则第一个通道为 R 等)。

我认为 bits_per_pixel 的有效值为 1、2、4、8、15、16、24 和 32(15 和 16 位是相同的每像素格式 2 个字节,但前者有 1 位未使用)。我认为除了 24 和 32 bpp 之外,任何人都不值得花时间支持任何东西。

X11 不关心媒体文件,所以没有 4CC 代码。

于 2013-01-13T22:18:16.160 回答
2

这可以从XImage结构本身中读取。

  1. 每个像素中 R、G、B 通道的顺序;

这包含在XImage结构的这个字段中:

int byte_order;          /* data byte order, LSBFirst, MSBFirst */

它告诉你它是 RGB 还是 BGR(因为它只取决于机器的字节序)。

  1. 每个像素的位数;

可以从这个字段中获得:

int bits_per_pixel;      /* bits per pixel (ZPixmap) */

这基本上是每个通道掩码中设置的位数:

unsigned long red_mask;      /* bits in z arrangement */
unsigned long green_mask;
unsigned long blue_mask;

  1. 每个通道的位数;

见上文,或者您可以使用@nm 答案中的代码自己计算位数。

是的,如果他们也将位移常数放入该结构中会很棒,但显然他们决定不这样做,因为无论如何像素都以“标准顺序”(RGB)与字节对齐。Xlib 确保在从 X 服务器检索数据时为您将其转换为该顺序,即使它们在内部以不同的格式存储在服务器端。所以它总是 RGB 格式,字节对齐,但根据机器的字节顺序,an 中的字节unsigned long可以以相反的顺序出现,因此该byte_order字段可以告诉你。

因此,为了提取这些通道,只需在使用 , 和 屏蔽后使用,和移位08只需确保根据 移位正确的字节,它应该可以正常工作。16red_maskgreen_maskblue_maskbyte_order

于 2019-05-12T08:54:49.300 回答