[英]Convert 16bit colour to 32bit
我有一个 16 位位图图像,每种颜色表示为一个短(2 个字节),我需要在 32 位位图上下文中显示它。 如何在 C++ 中将 2 字节颜色转换为 4 字节颜色?
输入格式在单个短(2 个字节)中包含每种颜色。
输出格式为 32 位 RGB。 这意味着我相信每个像素有 3 个字节?
我需要将短值转换为 RGB 颜色。
请原谅我对颜色的了解不足,这是我第一次进入图形编程世界。
通常一个 16 位像素是 5 位红色、6 位绿色和 5 位蓝色数据。 最小误差解决方案(即,保证输出颜色与输入颜色最接近)是:
red8bit = (red5bit << 3) | (red5bit >> 2);
green8bit = (green6bit << 2) | (green6bit >> 4);
blue8bit = (blue5bit << 3) | (blue5bit >> 2);
要了解此解决方案为何有效,让我们看一下红色像素。 我们的 5 位红色是某个分数fivebit/31
。 我们想把它转换成一个新的分数eightbit/255
。 一些简单的算术:
fivebit eightbit
------- = --------
31 255
产量:
eightbit = fivebit * 8.226
或者接近(注意波浪线 ≈):
eightbit ≈ (fivebit * 8) + (fivebit * 0.25)
该操作是乘以 8 和除以 4。Owch - 这两个操作可能会在您的硬件上永远运行。 幸运的是,它们都是 2 的幂,可以转换为移位操作:
eightbit = (fivebit << 3) | (fivebit >> 2);
相同的步骤适用于每像素 6 位的绿色,但您当然会得到相应不同的答案! 记住解决方案的快速方法是您从“短”像素中取出最高位并将它们添加到底部以制作“长”像素。 此方法同样适用于您需要映射到更高分辨率空间的任何数据集。 几个快速示例:
five bit space eight bit space error
00000 00000000 0%
11111 11111111 0%
10101 10101010 0.02%
00111 00111001 -1.01%
常见的格式包括 BGR0、RGB0、0RGB、0BGR。 在下面的代码中,我假设了 0RGB。 改变这很容易,只需修改最后一行中的移位量。
unsigned long rgb16_to_rgb32(unsigned short a)
{
/* 1. Extract the red, green and blue values */
/* from rrrr rggg gggb bbbb */
unsigned long r = (a & 0xF800) >11;
unsigned long g = (a & 0x07E0) >5;
unsigned long b = (a & 0x001F);
/* 2. Convert them to 0-255 range:
There is more than one way. You can just shift them left:
to 00000000 rrrrr000 gggggg00 bbbbb000
r <<= 3;
g <<= 2;
b <<= 3;
But that means your image will be slightly dark and
off-colour as white 0xFFFF will convert to F8,FC,F8
So instead you can scale by multiply and divide: */
r = r * 255 / 31;
g = g * 255 / 63;
b = b * 255 / 31;
/* This ensures 31/31 converts to 255/255 */
/* 3. Construct your 32-bit format (this is 0RGB): */
return (r << 16) | (g << 8) | b;
/* Or for BGR0:
return (r << 8) | (g << 16) | (b << 24);
*/
}
将三个(四个,当你有一个 alpha 层)值乘以 16 - 就是这样:)
您有 16 位颜色并希望将其设为 32 位颜色。 这为您提供了四乘以四位,您希望将其转换为四乘以八位。 您正在添加四位,但您应该将它们添加到值的右侧。 为此,将它们移位 4 位(乘以 16)。 此外,您可以通过添加 8 来补偿不准确度(您添加了 4 位,其值为 0-15,您可以取 8 的平均值来补偿)
更新这仅适用于每个通道使用 4 位并具有 Alpha 通道的颜色。
我在这里打多久,但我实际上有与ARGB颜色相同的问题,而是和没有一个答案是真正正确的:请记住,这个答案让我们想这样做一个稍微不同的情况的响应转换:
AAAARRRRGGGGBBBB
>>= AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB
如果您想保持相同的颜色比例,您只需进行交叉乘法:您想将 0 到 15 之间的值x
转换为 0 到 255 之间的值:因此您想要: y = 255 * x / 15
。
然而,255 = 15 * 17,它本身就是 16 + 1:你现在有y = 16 * x + x
这实际上与对位向左移动然后再次添加值(或更直观,复制值: 0b1101
变为0b11011101
)。
现在你有了这个,你可以通过执行以下操作来计算你的整数:
a = v & 0b1111000000000000
r = v & 0b111100000000
g = v & 0b11110000
b = v & 0b1111
return b | b << 4 | g << 4 | g << 8 | r << 8 | r << 12 | a << 12 | a << 16
此外,由于较低的位不会对最终颜色产生太大影响,而且如果不需要精确,您只需将每个分量乘以 16 即可获得一些性能:
return b << 4 | g << 8 | r << 12 | a << 16
(所有的左移值都很奇怪,因为我们之前没有费心做右移)
有一些关于模型的问题,比如它是 HSV 还是 RGB? 如果你想准备好,开火,瞄准,我会先试试这个。
#include <stdint.h>
uint32_t convert(uint16_t _pixel)
{
uint32_t pixel;
pixel = (uint32_t)_pixel;
return ((pixel & 0xF000) << 16)
| ((pixel & 0x0F00) << 12)
| ((pixel & 0x00F0) << 8)
| ((pixel & 0x000F) << 4);
}
这会映射 0xRGBA -> 0xRRGGBBAA,或者可能是 0xHSVA -> 0xHHSSVVAA,但它不会映射 0xHSVA -> 0xRRGGBBAA。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.