如何在32-bpp显示器上高效渲染24-bpp图像?

时间:2013-12-24 19:05:47

标签: c++ c bitmap osdev

首先,我在内核上下文编程,因此不存在现有的库。事实上,这段代码将进入我自己的库中。

两个问题,一个比另一个更重要:

  1. 正如标题所示,我怎样才能有效地将24-bpp图像渲染到32-bpp设备上,假设我有帧缓冲区的地址?
  2. 目前我有这段代码:

    void BitmapImage::Render24(uint16_t x, uint16_t y, void (*r)(uint16_t, uint16_t, uint32_t))
    {
        uint32_t imght = Math::AbsoluteValue(this->DIB->GetBitmapHeight());
        uint64_t ptr = (uint64_t)this->ActualBMP + this->Header->BitmapArrayOffset;
    
        uint64_t rowsize = ((this->DIB->GetBitsPerPixel() * this->DIB->GetBitmapWidth() + 31) / 32) * 4;
    
        uint64_t oposx = x;
        uint64_t posx = oposx;
        uint64_t posy = y + (this->DIB->Type == InfoHeaderV1 && this->DIB->GetBitmapHeight() < 0 ? 0 : this->DIB->GetBitmapHeight());
    
    
        for(uint32_t d = 0; d < imght; d++)
        {
            for(uint32_t w = 0; w < rowsize / (this->DIB->GetBitsPerPixel() / 8); w++)
            {
                r(posx, posy, (*((uint32_t*)ptr) & 0xFFFFFF));
                ptr += this->DIB->GetBitsPerPixel() / 8;
                posx++;
            }
            posx = oposx;
            posy--;
        }
    }
    

    r是一个函数指针,指向接受x,y和颜色参数的PutPixel-esque。 显然这段代码非常慢,因为一次绘制一个像素绝不是一个好主意。

    对于我的32-bpp渲染代码(我也有一个问题,稍后会有更多内容)我可以很容易地将Memory :: Copy()位图数组(我在这里加载bmp文件)添加到帧缓冲区。 但是,如何使用24bpp图像执行此操作?在一个24bpp的显示器上,这样可以,但我正在使用一个32bpp的显示器。

    我现在能想到的一个解决方案是创建另一个位图数组,它基本上包含0x00(颜色)的值以及用于绘制到屏幕的用途 - 我不认为这是非常好的,所以我正在寻找更好的选择。

    下一个问题: 2.由于显而易见的原因,我们不能简单地将整个数组的Memory :: Copy()放到帧缓冲区上,下一个最好的方法就是逐行复制它们。

    有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

基本上是这样的:

for (uint32_t l = 0; l < h; ++l) // l line index in pixels
{
    // srcPitch is distance between lines in bytes
    char*     srcLine = (char*)srcBuffer + l * srcPitch; 
    unsigned* trgLine = ((unsigned*)trgBuffer) + l * trgPitch;

    for (uint32_t c = 0; c < w; ++c) // c is column index in pixels
    {
        // build target pixel. arrange indexes to fit your render target (0, 1, 2)
        ++(*trgLine) = (srcLine[0] << 16) | (srcLine[1] << 8)
           | srcLine[2] | (0xff << 24);
        srcLine += 3;
    }
}

一些注意事项:   - 更好地写入与渲染缓冲区不同的缓冲区,以便立即显示图像。   - 像你一样使用像素放置功能非常(非常非常)慢。