0

如果我使用 Qt 执行以下操作:

  1. 在 QImage::Format_RGB32 中加载位图。
  2. 将其像素转换为 RGB565(没有 Qt 格式,所以我必须“手动”完成)。
  3. 创建一个与步骤 1 中加载的大小相同的新位图。
  4. 将 RGB565 缓冲区像素转换回 RGB88 到步骤 3 中创建的图像。
  5. 从第 4 步创建的图像看起来像第 1 步中的图像,但是如果您比较 RGB 值,它们并不完全相同。

重复步骤 2 到 5 会导致最终图像失去颜色 - 它似乎变得越来越暗。

这是我的转换函数:

qRgb RGB565ToRGB888( unsigned short int aTextel )
{
    unsigned char r = (((aTextel)&0x01F) <<3);
    unsigned char g = (((aTextel)&0x03E0) >>2);
    unsigned char b = (((aTextel)&0x7C00 )>>7);
    return qRgb( r, g, b, 255 );
}

unsigned short int RGB888ToRGB565( QRgb aPixel )
{
    int red = ( aPixel >> 16) & 0xFF;
    int green = ( aPixel >> 8 ) & 0xFF;
    int blue =  aPixel & 0xFF;

    unsigned short  B = (blue >> 3) & 0x001F;
    unsigned short  G = ((green >> 2) < 5) & 0x07E0;
    unsigned short  R = ((red >> 3) < 11) & 0xF800;

    return (unsigned short int) (R | G | B);
}

我从我的测试图像中发现的一个不能正确转换的例子是 4278192128,它从 RGB565 转换回 RGB888 为 4278190080。

编辑:我还应该提到原始源数据是 RGB565(我的测试 RGB888 图像是从中创建的)。我只是为了显示目的而转换为 RGB888,但之后想转换回 RGB565,而不是保留数据的两个副本。

4

1 回答 1

9

事先我想提一下,你的两个转换函数中的组件顺序是不一样的。在 565 -> 888 转换中,您假设红色分量使用低位 ( 0x001F),但在对红色分量的 5 位进行编码时,您将它们放在高位 ( 0xF800)。假设您想要一个类似于0xAARRGGBB(RGB565 中的二进制表示为 then 0bRRRRRGGGGGGBBBBB)的组件顺序,您需要更改RGB565ToRGB888方法中的变量名称。我在下面的代码中修复了这个问题。

您的 RGB565 到 RGB888 转换有问题。对于绿色通道,您提取 5 位,结果中只有 7 位而不是 8 位。对于蓝色通道,您采用以下位,这是一个后果性错误。这应该解决它:

QRgb RGB565ToRGB888( unsigned short int aTextel )
{
    // changed order of variable names
    unsigned char b = (((aTextel)&0x001F) << 3);
    unsigned char g = (((aTextel)&0x07E0) >> 3); // Fixed: shift >> 5 and << 2
    unsigned char r = (((aTextel)&0xF800) >> 8); // shift >> 11 and << 3
    return qRgb( r, g, b, 255 );
}

在另一个函数中,您不小心编写了小于运算符而不是左移运算符。这应该解决它:

unsigned short int RGB888ToRGB565( QRgb aPixel )
{
    int red   = ( aPixel >> 16) & 0xFF;  // why not qRed(aPixel) etc. ?
    int green = ( aPixel >> 8 ) & 0xFF;
    int blue  =   aPixel        & 0xFF;

    unsigned short  B =  (blue  >> 3)        & 0x001F;
    unsigned short  G = ((green >> 2) <<  5) & 0x07E0; // not <
    unsigned short  R = ((red   >> 3) << 11) & 0xF800; // not <

    return (unsigned short int) (R | G | B);
}

请注意,您可以使用已经存在的(内联)函数qRed,进行组件提取qGreenqBlue类似于qRgb从组件构建颜色。

另请注意,最后的位掩码RGB888ToRGB565是可选的,因为组件值在 8 位范围内,并且您通过首先右移然后左移值来裁剪它们。

于 2012-06-13T05:09:35.783 回答