Целочисленный тип для отображения 10-битного RGB для отображения - PullRequest
0 голосов
/ 04 ноября 2018

У меня много трудностей, чтобы найти любую документацию для разработчиков о том, как реализовать в C 10-битный RGB-вывод для дисплеев, в основном для Xorg / Wayland в Linux и, если возможно, совместимый с Windows.

В настоящее время приложение, над которым я работаю (darktable), использует uint8_t для вывода значений RGB. Каким будет тип для 10-битной уинты? Есть ли способ проверить поддержку 10-битного GPU / кодека из кода?

Ответы [ 2 ]

0 голосов
/ 04 ноября 2018

Точный способ организации цветовых каналов зависит от API. Он вполне может быть плоским (то есть одним моно-изображением на канал), он может быть упакован (то есть упаковывать несколько каналов в одно слово данных), он может чередоваться (используя разные представления для каждого канала).

Однако одно можно сказать наверняка: для любого формата канала, который не совсем соответствует «нативному» типу, для доступа к нему должно произойти какое-то битовое переплетение.

Чтобы понять, как обширно это поле, просто посмотрите на форматы изображений, указанные в самой первой версии Vulkan API: https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s03.html - этот документ также описывает, как точно биты расположены для каждого формата.

0 голосов
/ 04 ноября 2018

Я немного погуглил, чтобы уточнить, что может означать 10-битный RGB.

В Википедии Глубина цвета & ndash; Глубокий цвет (30/36/48 бит) Я нашел:

Некоторые более ранние системы помещали три 10-битных канала в 32-битное слово, причем 2 бита не использовались (или использовались как 4-уровневый альфа-канал).

, который казался мне наиболее разумным.

Кроме того, есть 10 бит для красного, 10 бит для зеленого и 10 бит для синего, + 2 бита не используются (или зарезервированы для альфы).

Это оставляет два открытых вопроса:

  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

Демонстрация в реальном времени на ideone

...