首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >比较16 bpp与32 bpp位图转换

比较16 bpp与32 bpp位图转换
EN

Stack Overflow用户
提问于 2021-04-16 21:46:35
回答 1查看 32关注 0票数 0

我得到了一个16bpp的位图

我通过下面的代码将其转换为32bpp:

代码语言:javascript
复制
void Rgb555ToRgb8(const UChar* bitmapData, UInt32 width, UInt32 height, UChar* buf)
{

    UInt32 dst_bytes_per_row = width * 4;
    UInt32 src_bytes_per_row = ((width * 16 + 31) / 32) * 4;

    UInt16 red_mask = 0x7C00;
    UInt16 green_mask = 0x3E0;
    UInt16 blue_mask = 0x1F;

    for (UInt32 row = 0; row < height; ++row)
    {
        UInt32 dstCol = 0, srcCol = 0;

        do
        {
            UInt16 rgb = *(UInt16*)(bitmapData + row * src_bytes_per_row + srcCol);

            UChar red_value = (rgb & red_mask) >> 10;
            UChar green_value = (rgb & green_mask) >> 5;
            UChar blue_value = (rgb & blue_mask);

            buf[row*dst_bytes_per_row + dstCol] = blue_value << 3;
            buf[row*dst_bytes_per_row + dstCol + 1] = green_value << 3;
            buf[row*dst_bytes_per_row + dstCol + 2] = red_value << 3;
            buf[row*dst_bytes_per_row + dstCol + 3] = rgb >> 15;

            srcCol += 2;
            dstCol += 4;

        } while (srcCol < src_bytes_per_row);
    }
}

转换结果如下: 2:https://i.stack.imgur.com/1ajO7.png

我还尝试通过GdiPlus转换此图像:

Gdiplus::Bitmap* bmp = new Gdiplus::Bitmap(w,h,PixelFormat32bppRGB);

生成的图像是

请注意,这两个结果看起来并不完全相同(例如,GdiPlus结果中的背景是白色的)。如何修改代码以匹配GdiPlus结果?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-16 23:29:46

有两个问题需要解决:

未使用的位

当从5比特信息移动到8比特信息时,您将获得额外的3比特。在实现时,代码没有使用这个额外的范围,并且偏向于较暗的颜色分量。这是对blue_value << 3实际功能的说明:

代码语言:javascript
复制
5 bits per channel    8 bits per channel

bbbbb              -> bbbbb000

为了解决这个问题,最低有效的3位需要随着通道值的增加而增长。一个简单的(仍然是somewhat inaccurate)是只将最高有效的3位复制到最低有效的3位,即

代码语言:javascript
复制
buf[row*dst_bytes_per_row + dstCol]     = (blue_value  << 3) | (blue_value  >> 2);
buf[row*dst_bytes_per_row + dstCol + 1] = (green_value << 3) | (green_value >> 2);
buf[row*dst_bytes_per_row + dstCol + 2] = (red_value   << 3) | (red_value   >> 2);

精确的映射可能会涉及更多,例如

代码语言:javascript
复制
blue_value = static_cast<UChar>((blue_value * 255.0) / 31.0 + 0.5);

这将从5位转换为最接近理想值的相应8位值,包括上面的位移位解决方案中偏移1/255的4个值。

如果选择后者,则可以构建一个存储映射值的查找表。这个表只有32个条目,每个条目一个字节,所以它可以放入单个缓存线中。

Alpha通道

假设源图像的MSB确实被解释为alpha值,那么您也需要将其移动到目标位置。由于源只有1比特的信息,所以原始转换很简单:

代码语言:javascript
复制
buf[row*dst_bytes_per_row + dstCol + 3] = rgb & (1 << 15) ? 255 : 0;

这可能是也可能不是所需的全部。Windows假定预乘alpha,即颜色通道的存储值必须预乘alpha值(有关参考,请参见BLENDFUNCTION )。

如果alpha值为255,则颜色通道值已正确。如果alpha值为0,则需要将所有颜色通道乘以0(或仅设置为0)。转换不会产生任何其他alpha值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67126397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档