我有一个16位的位图图像,每种颜色表示为一个短(2个字节),我需要在32位位图上下文中显示它。如何在C ++中将2字节颜色转换为4字节颜色?
输入格式包含单个短(2个字节)中的每种颜色。
输出格式为32位RGB。这意味着我相信每个像素有3个字节?
我需要将短值转换为RGB颜色。
请原谅我缺乏色彩知识,这是我第一次进入图形编程世界。
答案 0 :(得分:8)
通常,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 - 两种操作都可能在您的硬件上永远 。幸运的是,它们都是两个权力,可以转换为轮班操作:
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%
答案 1 :(得分:3)
常见格式包括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);
*/
}
答案 2 :(得分:1)
将三个(四个,当你有一个alpha图层)的值乘以16时 - 就是这样:)
您有一个16位颜色,并希望使其成为32位颜色。这为您提供四位四位,您希望将其转换为八位的四倍。您要添加四位,但应将它们添加到值的右侧。为此,将它们移位四位(乘以16)。此外,您可以通过添加8来补偿一点不准确(您正在添加4位,其值为0-15,您可以取平均值8来补偿)
更新这仅适用于每个频道使用4位且具有Alpha通道的颜色。
答案 3 :(得分:0)
有关模型的一些问题,如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 - &gt; 0xRRGGBBAA,或者可能是0xHSVA - &gt; 0xHHSSVVAA,但它不会做0xHSVA - &gt; 0xRRGGBBAA。
答案 4 :(得分:0)
我在战斗结束后很久就在这里,但实际上我在 ARGB 颜色代替时遇到了同样的问题,而且没有一个答案是正确的:记住这个答案对略有不同的情况做出了回应,我们希望在这种情况下进行这种转换:
AAAARRRRGGGGBBBB
>>= AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB
如果您想保持相同的颜色比例,您只需进行交叉乘法:您想将 0 到 15 之间的值 x
转换为 0 到 255 之间的值:因此您想要:y = 255 * x / 15
。
然而,255 = 15 * 17,它本身就是 16 + 1:你现在有 y = 16 * x + x
这实际上与将 for 位向左移动然后再次添加值(或更直观地,复制值: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
(所有的左移值都很奇怪,因为我们之前没有费心去做右移)