将16位色转换为32位色

时间:2011-12-20 17:21:14

标签: iphone c++ c

我有一个16位的位图图像,每种颜色表示为一个短(2个字节),我需要在32位位图上下文中显示它。如何在C ++中将2字节颜色转换为4字节颜色?

输入格式包含单个短(2个字节)中的每种颜色。

输出格式为32位RGB。这意味着我相信每个像素有3个字节?

我需要将短值转换为RGB颜色。

请原谅我缺乏色彩知识,这是我第一次进入图形编程世界。

5 个答案:

答案 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

(所有的左移值都很奇怪,因为我们之前没有费心去做右移)