view ostc45_icon.cpp @ 5:115cfa4a3239 default tip

Added icon upload function for OSTC 4/5 For the upload the same process as the one for the firmware update is used => CRC functionality has been copied from the ostc_pack SW
author Ideenmodellierer
date Tue, 30 Dec 2025 21:41:02 +0100
parents
children
line wrap: on
line source

#include "ostc45_icon.h"


//OSTC45_Icon::OSTC45_Icon() {}


#pragma pack(push, 1)
struct BMPFileHeader
{
    uint16_t bfType;
    uint32_t bfSize;
    uint16_t bfReserved1;
    uint16_t bfReserved2;
    uint32_t bfOffBits;
};

struct BMPInfoHeader
{
    uint32_t biSize;
    int32_t  biWidth;
    int32_t  biHeight;
    uint16_t biPlanes;
    uint16_t biBitCount;
    uint32_t biCompression;
    uint32_t biSizeImage;
    int32_t  biXPelsPerMeter;
    int32_t  biYPelsPerMeter;
    uint32_t biClrUsed;
    uint32_t biClrImportant;
};
#pragma pack(pop)

BmpToArray::BmpToArray(const QString& filename)
{
    loadBMP(filename);
}

void BmpToArray::loadBMP(const QString& filename)
{
    QFile file(filename);
    int dstY;
    QByteArray rowBuffer;
    bool topDown = false;
    BMPFileHeader fileHeader;
    BMPInfoHeader infoHeader;

    if (!file.open(QIODevice::ReadOnly))
        throw std::runtime_error("Cannot open BMP file");

    if (file.read(reinterpret_cast<char*>(&fileHeader),
                  sizeof(BMPFileHeader)) != sizeof(BMPFileHeader))
        throw std::runtime_error("Failed to read BMP file header");

    if (file.read(reinterpret_cast<char*>(&infoHeader),
                  sizeof(BMPInfoHeader)) != sizeof(BMPInfoHeader))
        throw std::runtime_error("Failed to read BMP info header");

    if (fileHeader.bfType != 0x4D42)
        throw std::runtime_error("Not a valid BMP file");

    if (infoHeader.biBitCount != 8)
        throw std::runtime_error("Only 8-bit BMP supported");
    if (infoHeader.biCompression != 0)
        throw std::runtime_error("Compressed BMP not supported");

    if(infoHeader.biWidth > 800)
        throw std::runtime_error("Only BMP with 800 or less horizontal pixels supported");

    if(infoHeader.biHeight > 480)
        throw std::runtime_error("Only BMP with 480 or less vertical pixels supported");

    // Width / Height
    width = infoHeader.biWidth;
    height = infoHeader.biHeight;

    if ((int32_t)height < 0) {
        height = -((int32_t)height);
        topDown = true;
    }

    // Palette
    uint32_t colorCount = infoHeader.biClrUsed;
    if (colorCount == 0) colorCount = 256;
    if (colorCount > 256) colorCount = 256;

    clut.resize(colorCount);

    for (uint32_t i = 0; i < colorCount; ++i)
        file.read(reinterpret_cast<char*>(&clut[i]), 4);

    // CLUT in 32-Bit transform 0x00RRGGBB
    clut32.resize(255, 0);

    for (uint32_t i = 0; i < colorCount && i < 255; ++i)
    {
        clut32[i] =
            (clut[i].r << 16) |
            (clut[i].g << 8) |
            (clut[i].b);
    }

    // Pixel-Data
    if (!file.seek(fileHeader.bfOffBits))
        throw std::runtime_error("Failed to seek to pixel data");

    pixelData.resize(width * height);

    size_t rowSize = (width + 3) & ~3; // 4-Byte alignment

    rowBuffer.resize(rowSize);

    for (int y = 0; y < height; ++y)
    {
        if (file.read(rowBuffer.data(), rowSize) != rowSize)
            throw std::runtime_error("Failed to read BMP pixel row");

        if (topDown)
        {
            dstY = height - 1 - y;
        }
        else
        {
            dstY = y;
        }

        for (int x = 0; x < width; ++x)
        {
            pixelData[x * height + dstY] =
                static_cast<uint8_t>(rowBuffer[x]);
        }
    }


}
QByteArray BmpToArray::getTransferBytes() const
{
    QByteArray out;

    out.reserve(clut32.size() * 4 + pixelData.size());

    // CLUT (32 Bit, Little Endian)
    for (uint32_t color : clut32)
    {
        out.append(static_cast<char>( color        & 0xFF));
        out.append(static_cast<char>((color >> 8)  & 0xFF));
        out.append(static_cast<char>((color >> 16) & 0xFF));
        out.append(static_cast<char>((color >> 24) & 0xFF));
    }

    // Pixel (8 Bit)
    out.append(reinterpret_cast<const char*>(pixelData.data()),
               pixelData.size());

    return out;
}

void BmpToArray::getImageXY(uint32_t* x, uint32_t* y)
{
    *x = width;
    *y = height;
}