Я немного погуглил, чтобы уточнить, что может означать 10-битный RGB.
В Википедии Глубина цвета & ndash; Глубокий цвет (30/36/48 бит) Я нашел:
Некоторые более ранние системы помещали три 10-битных канала в 32-битное слово, причем 2 бита не использовались (или использовались как 4-уровневый альфа-канал).
, который казался мне наиболее разумным.
Кроме того, есть 10 бит для красного, 10 бит для зеленого и 10 бит для синего, + 2 бита не используются (или зарезервированы для альфы).
Это оставляет два открытых вопроса:
Хранится ли RGBa или BGRa или aRGB? (Я считаю, что я видел все эти вариации в прошлом.)
Имеет ли составленное значение для хранения 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