Chapter 91 · 图像与纹理

图像加载

xge_image 是 CPU 端像素容器,支持从文件或内存加载 PNG/JPG/BMP 等格式,可访问原始像素数据。

91

概念

xge_image 是纯 CPU 端的像素缓冲区(RGBA32),用于加载、解码、像素操作。 它不直接参与 GPU 渲染——需要上传为 xge_texture 后才能绘制。 典型流程:ImageLoad → GetPixels(可选处理)→ TextureCreateFromImage → Draw。

API 速查

函数说明
int xgeImageLoad(xge_image pImage, const char* sPath)从文件加载图像
int xgeImageLoadEx(xge_image pImage, const char* sPath, uint32_t iFlags)带标志加载
int xgeImageLoadMemory(xge_image pImage, const void* pData, int iSize)从内存加载
int xgeImageLoadMemoryEx(xge_image pImage, const void* pData, int iSize, uint32_t iFlags)内存加载 + 标志
void* xgeImageGetPixels(xge_image pImage)获取像素指针(RGBA)
void xgeImagePremultiply(xge_image pImage)预乘 Alpha
void xgeImageFree(xge_image pImage)释放图像

编译本章示例

gcc -O2 -I. -o ch91.exe ch91_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch91.exe

示例:加载并显示图片

// 声明图像对象(栈上结构体)
xge_image_t img;
memset(&img, 0, sizeof(img));

// 从文件加载
if (xgeImageLoad(&img, "assets/logo.png") != 0) {
    xgeLogWrite(XGE_LOG_ERROR, "加载失败");
    return;
}

// 访问像素(可选:如翻转、调色)
uint8_t* pixels = (uint8_t*)xgeImageGetPixels(&img);
// img.iWidth, img.iHeight 为尺寸

// 上传为 GPU 纹理
xge_texture_t tex;
xgeTextureCreateFromImage(&tex, &img);

// 绘制
xgeDraw(&tex, 100, 100);

// 释放 CPU 图像(纹理已独立)
xgeImageFree(&img);

完整代码

将以下代码保存为 ch91_main.c,编译后运行即可看到图像加载与显示效果:

#include "xge.h"
#include <string.h>

static xge_image_t g_img;
static xge_texture_t g_tex;
static int g_loaded = 0;
static xge_font g_font = NULL;

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x081114FF);

    if (g_loaded) {
        // 居中绘制纹理
        float x = ((float)xgeGetWidth() - g_img.iWidth) * 0.5f;
        float y = ((float)xgeGetHeight() - g_img.iHeight) * 0.5f;
        xgeDraw(&g_tex, x, y);
    } else {
        xgeTextDraw(g_font, "Image load failed!",
            300.0f, 280.0f, 0xFF4444FF)
    }

    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch91 - Image Load & Display";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);

    xgeFontLoad(&g_font, "Roboto.ttf", 20.0f);

    // 加载图像
    memset(&g_img, 0, sizeof(g_img));
    if (xgeImageLoad(&g_img, "assets/logo.png") == 0) {
        // 上传为 GPU 纹理
        xgeTextureCreateFromImage(&g_tex, &g_img);
        // 释放 CPU 像素(纹理已独立)
        xgeImageFree(&g_img);
        g_loaded = 1;
    }

    xgeRun(onFrame, NULL);

    if (g_loaded)
        xgeTextureFree(&g_tex);
    xgeFontFree(g_font);
    xgeUnit();
    return 0;
}

代码讲解

  • ImageLoad:从文件解码图像为 RGBA32 像素,支持 PNG/JPG/BMP 格式。
  • TextureCreateFromImage:将 CPU 像素上传为 GPU 纹理,之后可独立于原图像使用。
  • ImageFree:释放 CPU 端像素内存,已创建的纹理不受影响。
  • 居中绘制:用窗口尺寸减去图像尺寸除以 2 计算居中坐标。

要点与陷阱

  • 格式:内部统一解码为 RGBA32,无论源文件是 PNG/JPG/BMP。
  • Premultiply:若渲染管线使用预乘混合,加载后调用 xgeImagePremultiply。
  • 内存加载:适合从资源包/网络读取的数据,pData 在调用期间必须有效。
  • 生命周期:ImageFree 释放像素;已创建的 Texture 不受影响。

进阶练习

  1. 实现图片查看器:加载 → 缩放 → 绘制到窗口中心。
  2. 像素操作:将图像转为灰度后上传纹理。
图像加载效果
图:图像加载渲染效果