繁体   English   中英

使用C ++在微控制器上显示位图图形

[英]Display bitmap graphics on a microcontroller using C++

我正在使用十六进制格式的888到565格式的位图。 因此,我试图在使用SDL的模拟器上显示位图,帧缓冲区的重定为16位。

一个位图数据(第一行)看起来像这样

0x42, 0x4D, 0xFE, 0x82, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x36, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0x7B, 0x0, 0x0, 0x0, 0x5A, 0x0, 0x0, 0x0, 0x1, 0x0, 0x18, 0x0, 0x0, 0x0, 

现在,我试图在SDL上使用C ++绘制该位图,但是我得到了带有扫描线的垃圾图像,看起来间距没有正确计算。

void Rasterizer::DrawBitmap(int w, int h, int x, int y, int transparent)
{
    if (!bitmap)
        return;

    const uint8_t bytesPerPixel = 2;
    uint16_t bytesPerRow = (bytesPerPixel * h ); // bytes Per Row including padding to 4 byte row boundary
    uint16_t paddingSize = bytesPerRow - (bytesPerPixel * w); // paddingSize for each row
    uint16_t pixel;
    uint16_t row, column;


    for (row = 0; row < h; row++) {
        for (column = 0; column < w; column++) {
            pixel = bitmap[row + column* bytesPerRow]<<8;
            pixel |= bitmap[1+row + column* bytesPerRow] & 0xFF;
            SetPixel(x+column, y+row, pixel);
        }
    }

}



void Rasterizer::SetPixel(int x, int y, uint16_t color)
{
    m_FrameBuffer[y * m_Width + x] = color;
}

在此处输入图片说明

0x42, 0x4D

前2个字节是BM ,仅是位图文件头,总共54个字节。 它不是第一行的一部分。

大小为0x7B x 0x5A像素

到最后,您有0x18 0x00 ,它是24,用于24位位图,而不是16位

因此,您必须跳过54个字节,并将其读取为24位

int width_in_bytes = ((width * 24 + 31) / 32) * 4 * height;
for(int row = height - 1; row >= 0; row--)
{
    for(int col = 0; col < width; col++)
    {
        int i = row * width_in_bytes + col * 3;
        unsigned char blu = bitmap[54 + i + 0];
        unsigned char grn = bitmap[54 + i + 1];
        unsigned char red = bitmap[54 + i + 2];
        int pixel = red | ((uint16_t)grn << 8) | ((uint32_t)blu << 16);
        SetPixel(row, col, pixel);
    }
}

如果设备期望使用16位位图,则首先尝试获取16位位图。 例如,在进行屏幕截图时,Windows允许使用16位格式。

SDL也支持SDL_PIXELFORMAT_RGB565 如果您在Windows中进行编码,则GDI +是另一种选择。

如果您的源位图是24位,并且您想要转换为16位565格式,请根据以下MCVE编写公式

24位位图的颜色范围为0-255,而16位位图的颜色范围为0-31(对于565格式,绿色为0-63)。 您必须对颜色进行规范化,例如将红色值乘以31/255。 然后将值移位以放入16位整数。

16位位图格式在像素开始之前需要3种颜色(总共12个字节)。 这些颜色包含有关565格式的信息。

#include <Windows.h>
#include <stdint.h>
#include <iostream>
#include <fstream>
#include <vector>

int main()
{
    HBITMAP hbitmap = (HBITMAP)LoadImage(NULL, "24bit.bmp",
        IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    if(!hbitmap)
        return 0;

    BITMAP bm;
    GetObject(hbitmap, sizeof(bm), &bm);
    if(bm.bmBitsPixel != 24)
    {
        DeleteObject(hbitmap);
        std::cout << "Expecting 24-bit bitmap\n";
        return 0;
    }

    BYTE *source = (BYTE*)bm.bmBits;
    int w = bm.bmWidth;
    int h = bm.bmHeight;

    //calculate width in bytes (wb) for source and destination
    DWORD wb_src = ((w * 24 + 31) / 32) * 4;
    DWORD wb_dst = ((w * 16 + 31) / 32) * 4;

    int size = wb_dst * h;
    std::vector<BYTE> dest(size);
    for(int r = 0; r < h; r++)
    {
        for(int c = 0; c < w; c++)
        {
            int src = r * wb_src + c * 3;
            int dst = r * wb_dst + c * 2;

            uint16_t blu = (uint16_t)(source[src + 0] * 31.f / 255.f);
            uint16_t grn = (uint16_t)(source[src + 1] * 63.f / 255.f);
            uint16_t red = (uint16_t)(source[src + 2] * 31.f / 255.f);

            uint16_t res = (red) | (grn << 5) | (blu << 11);
            memcpy(&dest[dst], &res, 2);
        }
    }

    //prepare header files for 16-bit file
    BITMAPINFOHEADER bi = { sizeof(bi), w, h, 1, 16, BI_BITFIELDS };
    BITMAPFILEHEADER bf = { (WORD)'MB', 54 + 12 + wb_dst * h, 0, 0, 54 };

    std::ofstream of("16bit.bmp", std::ios::binary);
    if(of)
    {
        //add file header
        of.write((char*)&bf, sizeof(bf));
        of.write((char*)&bi, sizeof(bi));

        //color table
        COLORREF c1 = 31;
        COLORREF c2 = 63 << 5;
        COLORREF c3 = 31 << 11;
        of.write((char*)&c1, 4);
        of.write((char*)&c2, 4);
        of.write((char*)&c3, 4);

        //add pixels
        of.write((char*)&dest[0], dest.size());
    }

    DeleteObject(hbitmap);

    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM