代码之家  ›  专栏  ›  技术社区  ›  Aurélien Pierre

显示10位RGB的整数类型

  •  1
  • Aurélien Pierre  · 技术社区  · 6 年前

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

    目前,我正在开发的应用程序(darktable)正在使用 uint8_t

    2 回复  |  直到 6 年前
        1
  •  2
  •   Scheff's Cat    6 年前

    我在google上搜索了一下10位RGB的含义。

    在维基百科上 Color Depth – Deep color (30/36/48-bit)

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

    我觉得这是最合理的。

    与此相应,红色有10位,绿色有10位,蓝色有10位,+2位未使用(或为Alpha保留)。

    这就留下了两个问题:

    1. 合成值是存储在小端还是大端?

    当我在实际工作中遇到这个问题时,我基于一个假设做了一个实现,呈现了一些测试模式,检查它是否像预期的那样,如果没有交换resp。实现中的部分。没什么,我很自豪,但是,嗯,我用最少的努力得到了预期的结果。

    因此,假设将颜色存储为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

        2
  •  1
  •   datenwolf    6 年前

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

    但是有一点是肯定的:对于任何不完全适合“本机”类型的通道格式,访问它时必须进行一些微调。

    想知道怎么做 该字段是,只需查看Vulkan API的第一个版本指定的图像格式: https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s03.html 该文档还描述了每种格式的位的精确排列方式。