如何在自研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
相关产品推荐
相关产品推荐

