You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自研Hobby OS的帧缓冲区中正确显示TGA图像?

解决TGA图像在Hobby OS中显示失真的问题

1. 修复TGA头结构体定义错误

你的tga_header存在字段顺序、注释错误,这会导致读取的图像宽高、格式信息完全错位,是失真的核心原因。正确的32位无压缩TGA头结构如下:

#include <stdint.h>

struct tga_header {
    uint8_t id_length;         // 图像ID字段长度,无需时设为0
    uint8_t color_map_type;    // 颜色表类型,0表示无颜色表
    uint8_t image_type;        // 图像编码类型,2=无压缩真彩色
    uint16_t color_map_origin; // 颜色表起始索引,无颜色表设为0
    uint16_t color_map_length; // 颜色表长度,无颜色表设为0
    uint8_t color_map_depth;   // 颜色表位深,无颜色表设为0
    uint16_t x_origin;         // 图像X起始坐标,设为0
    uint16_t y_origin;         // 图像Y起始坐标,设为0
    uint16_t width;            // 图像宽度
    uint16_t height;           // 图像高度
    uint8_t bits_per_pixel;    // 像素位深,固定32
    uint8_t descriptor;        // 描述符:位0-3为Alpha位数(8),位6-7控制垂直翻转
} __attribute__((packed));

错误点:

  • 原结构体将y_origin误注释为高度,且width与height顺序颠倒,导致宽高读取完全错误
  • 字段名pixeltype应为descriptor,十进制40(0x28)对应Alpha位深8、垂直翻转开启的格式

2. 修正像素格式转换

TGA 32位像素采用BGRA字节顺序,而多数显示函数(如你的putpixel)期望RGBA顺序,需添加转换逻辑:

uint32_t convert_bgra_to_rgba(uint32_t bgra) {
    uint8_t b = (bgra >> 24) & 0xFF;
    uint8_t g = (bgra >> 16) & 0xFF;
    uint8_t r = (bgra >> 8) & 0xFF;
    uint8_t a = bgra & 0xFF;
    return (r << 24) | (g << 16) | (b << 8) | a;
}

3. 反转图像行顺序

TGA默认从左下角存储像素行,而你的draw_icon从左上角绘制,导致图像上下颠倒。修正后的绘制函数:

static void draw_icon(int x, int y, int w, int h, uint32_t *img) {
    int l, i;
    // 从最后一行开始读取,对应屏幕左上角
    for (l = h - 1; l >= 0; l--) {
        uint32_t *row = img + l * w;
        for (i = 0; i < w; i++) {
            uint32_t rgba = convert_bgra_to_rgba(row[i]);
            putpixel(x + i, y + (h - 1 - l), rgba);
        }
    }
}

4. 修正display_tga函数

void display_tga(struct tga_header *base)
{
    // 校验合法TGA格式:无ID、无颜色表、无压缩真彩色、32位深
    if (base->id_length != 0 || base->color_map_type != 0 || base->image_type != 2
        || base->color_map_origin != 0 || base->color_map_length != 0 || base->color_map_depth != 0
        || base->x_origin != 0 || base->y_origin != 0 || base->bits_per_pixel != 32)
        return;

    // 定位像素数据起始地址
    uint32_t *img = (uint32_t*)((uint8_t*)base + sizeof(struct tga_header));
    draw_icon(700, 50, base->width, base->height, img);
}

内容的提问来源于stack exchange,提问作者pwhx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 16:16:12