view ostc45_icon.cpp @ 12:ac837fe1d590

Switch implementation for reqex class and added RFCOMM as label for Bluetooth based connection by Linux
author Ideenmodellierer
date Mon, 12 Jan 2026 13:58:41 +0000
parents 6fba58c4964b
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;
}