整数类型以显示10位RGB用于显示

时间:2018-11-04 10:33:20

标签: c xorg

我很难找到任何有关如何在C中实现用于显示器的10位RGB输出的开发人员文档的信息,如果可能的话,主要针对Linux上的Xorg / Wayland并与Windows兼容。

当前,我正在处理的应用程序(暗表)正在使用uint8_t输出RGB值。 10位uint的类型是什么?是否可以通过代码检查GPU /编解码器的10位支持?

2 个答案:

答案 0 :(得分:1)

我已经用Google搜索了一下,以澄清10位RGB的含义。

在Wikipedia Color Depth – Deep color (30/36/48-bit)上,我发现:

  

某些早期的系统在一个32位字中放置了三个10位通道,未使用2位(或用作4级alpha通道)。

这似乎是我最合理的。

与此相关,红色有10位,绿色有10位,蓝色有10位,还有2位未使用(或保留给Alpha)。

这留下了两个问题:

  1. 是否存储RGBa或BGRa或aRGB? (我相信过去已经看到了所有这些变化。)

  2. 组合值是否存储为Little-Endian或Big-Endian?

在实际工作中遇到问题时,我根据一个假设进行了实现,呈现了一些测试模式,检查了它是否看起来像预期的那样,或者是否替换了相应的代码。零件的实施。没什么,我为此感到自豪,但是恕我直言,我毫不费力地获得了预期的结果。

因此,假设我将一种颜色存储为RGB三元组且其组件值在[0,1]范围内,则以下函数将其转换为aRGB:

uint32_t makeRGB30(float r, float g, float b)
{
  const uint32_t mask = (1u << 10u) - 1u;
  /* convert float -> uint */
  uint32_t rU = r * mask, gU = g * mask, bU = b * mask;
  /* combine and return color components */
  return ((rU & mask) << 20) | ((gU & mask) << 10) | (bU & mask);
}

这将导致具有以下位布局的值:

aaRRRRRR.RRRRGGGG.GGGGGGBB.BBBBBBBB

用于演示的小样本

#include <stdint.h>
#include <stdio.h>

uint32_t makeRGB30(float r, float g, float b)
{
  const uint32_t mask = (1u << 10u) - 1u;
  /* convert float -> uint */
  uint32_t rU = r * mask, gU = g * mask, bU = b * mask;
  /* combine and return color components */
  return ((rU & mask) << 20) | ((gU & mask) << 10) | (bU & mask);
}

int main(void)
{
  /* samples */
  const float colors[][3] = {
    { 0.0f, 0.0f, 0.0f }, /* black */
    { 1.0f, 0.0f, 0.0f }, /* red */
    { 0.0f, 1.0f, 0.0f }, /* green */
    { 0.0f, 0.0f, 1.0f }, /* blue */
    { 1.0f, 1.0f, 0.0f }, /* yellow */
    { 1.0f, 0.0f, 1.0f }, /* magenta */
    { 0.0f, 1.0f, 1.0f }, /* cyan */
    { 1.0f, 1.0f, 1.0f } /* white */
  };
  const size_t n = sizeof colors / sizeof *colors;
  for (size_t i = 0; i < n; ++i) {
    float *color = colors[i];
    uint32_t rgb = makeRGB30(color[0], color[1], color[2]);
    printf("(%f, %f, %f): %08x\n", color[0], color[1], color[2], rgb);
  }
  /* done */
  return 0;
}

输出:

(0.000000, 0.000000, 0.000000): 00000000
(1.000000, 0.000000, 0.000000): 3ff00000
(0.000000, 1.000000, 0.000000): 000ffc00
(0.000000, 0.000000, 1.000000): 000003ff
(1.000000, 1.000000, 0.000000): 3ffffc00
(1.000000, 0.000000, 1.000000): 3ff003ff
(0.000000, 1.000000, 1.000000): 000fffff
(1.000000, 1.000000, 1.000000): 3fffffff

Live Demo on ideone

答案 1 :(得分:1)

颜色通道的确切排列方式取决于API。它很可能是平面的(即每个通道一个单色图像),可以被打包(即将多个通道打包成一个数据字),也可以被交错(对于每个通道使用不同的表示形式)。

但是有一点可以肯定:对于不完全适合“本机”类型的任何频道格式,访问它都将需要进行一些调整。

要了解该字段的使用情况,请看一下Vulkan API的第一个版本指定的图像格式:https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s03.html –该文档还描述了如何精确地为每种格式排列了比特。