使用xxd将图片资源编译进程序并且使用cairo库读取和使用

⌚Time: 2025-06-25 18:32:00

👨‍💻Author: Jack Ge

使用xxd工具将png图片编译成c语言数组,通过 Cairo 的流式接口来加载这些内存中的 PNG 数据。

首先用 xxd 工具生成头文件:

xxd -i image.png > image.h

这会生成类似这样的头文件:

unsigned char image_png[] = {
  0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
  0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
  // ... 更多数据 ...
};
unsigned int image_png_len = 12345;

Cairo 读取内存中的图片

#include "image.h"  // 包含生成的xxd头文件
#include <cairo.h>

static unsigned int pos = 0;
// 读取回调函数
static cairo_status_t read_png_from_memory(void *closure,
                                         unsigned char *data,
                                         unsigned int length)
{
    
    // 检查是否读取越界
    if (pos + length > image_png_len) {
        return CAIRO_STATUS_READ_ERROR;
    }
    
    // 复制数据到Cairo提供的缓冲区
    memcpy(data, image_png + pos, length);
    pos += length;
    
    return CAIRO_STATUS_SUCCESS;
}

// 从内存创建Cairo表面
cairo_surface_t* create_surface_from_embedded_png()
{
    // 重置读取位置(如果需要多次调用)
    pos = 0;
    
    // 创建表面
    cairo_surface_t *surface = cairo_image_surface_create_from_png_stream(
        read_png_from_memory,
        NULL);  // 不需要额外数据,使用全局变量
    
    // 检查是否成功
    if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
        cairo_surface_destroy(surface);
        return NULL;
    }
    
    return surface;
}

之后使用create_surface_from_embedded_png返回的这个cairo_surface_t *绘制图片就行了


cairo_surface_t *image = create_surface_from_embedded_png();

其效果等于直接从文件中加载的函数

cairo_surface_t *image = cairo_image_surface_create_from_png("assets/fmbg.png");