Отображение растровой графики на микроконтроллере с использованием C ++ - PullRequest
0 голосов
/ 30 мая 2018

Я использую растровое изображение формата от 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, 

Сейчас я пытаюсь нарисовать это растровое изображение с использованием C ++ на SDL, но получаю мусорное изображение с линиями сканирования, похоже, что шаг не рассчитан правильно.

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;
}

enter image description here

1 Ответ

0 голосов
/ 30 мая 2018

0x42, 0x4D

Первые 2 байта - B и M, это всего лишь заголовок файла растрового изображения, который в сумме составляет 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.GDI + - это еще один вариант, если вы кодируете в Windows.

Если исходное растровое изображение является 24-разрядным, и вы хотите преобразовать его в 16-разрядный формат 565, напишите формулу на основе MCVE ниже

*24-битное растровое изображение 1026 * имеет диапазон цветов от 0 до 255, тогда как 16-битное изображение имеет диапазон цветов от 0 до 31 (0-63 для зеленого в случае формата 565).Вы должны нормализовать цвет, например, умножив значение красного на 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;
}
...