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

在GTK 4.0(C语言)中绘制像素数组的最简方法

在GTK 4.0中从浮点RGB数组显示图像

要直接从内存中的浮点RGB数组(width × height × 3)显示图像,你需要将浮点数据转换为GTK 4支持的图像格式,再通过GdkMemoryTexture创建纹理,最终用GtkImage展示。以下是具体实现步骤和示例代码:

核心步骤

  • 浮点数据转8位无符号整数:GTK的图像纹理通常使用8位通道(0-255),所以需要将0-1范围的浮点值映射为对应的整数(超出范围的要做截断)。
  • 创建内存纹理:使用gdk_memory_texture_new()直接从转换后的内存缓冲区创建GdkTexture,这是GTK 4推荐的高效方式。
  • 绑定到GtkImage:将创建好的纹理设置到GtkImage即可显示。

示例代码(C语言)

#include <gtk/gtk.h>
#include <stdint.h>
#include <math.h>

// 将浮点RGB数组转换为8位RGB数据,并创建GtkImage
GtkWidget* create_image_from_float_rgb(int width, int height, const float* float_rgb) {
    // 计算总像素数和字节数
    int pixel_count = width * height;
    size_t buffer_size = pixel_count * 3 * sizeof(uint8_t);
    
    // 分配8位RGB缓冲区
    uint8_t* rgb_buffer = g_malloc(buffer_size);
    
    // 浮点转8位:将0-1的浮点数映射到0-255,超出范围的截断
    for (int i = 0; i < pixel_count * 3; i++) {
        float val = float_rgb[i];
        val = CLAMP(val, 0.0f, 1.0f); // 确保值在0-1之间
        rgb_buffer[i] = (uint8_t)(val * 255.0f + 0.5f); // 四舍五入
    }
    
    // 创建内存纹理:格式为R8G8B8,无alpha通道
    GdkTexture* texture = gdk_memory_texture_new(
        width,
        height,
        GDK_MEMORY_R8G8B8,
        g_bytes_new_take(rgb_buffer, buffer_size), // 传递缓冲区并转移所有权
        width * 3 // 每行字节数(RGB三通道,所以是width*3)
    );
    
    // 创建GtkImage并设置纹理
    GtkWidget* image = gtk_image_new_from_texture(texture);
    
    // 释放纹理引用(GtkImage会持有自己的引用)
    g_object_unref(texture);
    
    return image;
}

// 测试用主函数
int main(int argc, char* argv[]) {
    gtk_init(&argc, &argv);
    
    // 生成测试用浮点RGB数组:渐变红色
    int width = 200;
    int height = 200;
    float* test_rgb = g_malloc(width * height * 3 * sizeof(float));
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            float r = (float)x / width;
            float g = (float)y / height;
            float b = 0.5f;
            test_rgb[(y * width + x) * 3 + 0] = r;
            test_rgb[(y * width + x) * 3 + 1] = g;
            test_rgb[(y * width + x) * 3 + 2] = b;
        }
    }
    
    // 创建窗口和图像
    GtkWidget* window = gtk_window_new();
    gtk_window_set_title(GTK_WINDOW(window), "Float RGB Image");
    gtk_window_set_default_size(GTK_WINDOW(window), width, height);
    
    GtkWidget* image = create_image_from_float_rgb(width, height, test_rgb);
    gtk_window_set_child(GTK_WINDOW(window), image);
    
    // 释放测试数据
    g_free(test_rgb);
    
    // 关闭窗口时退出程序
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    
    gtk_main();
    return 0;
}

关键说明

  • 数据格式转换:必须将浮点值严格限制在0-1范围内再转换,避免出现超出0-255的无效像素值。
  • GdkMemoryTexture:GTK 4引入的这个类专门用于从内存创建纹理,比旧的GdkPixbuf更高效,适合直接处理内存缓冲区。
  • 内存管理:使用g_bytes_new_take()传递缓冲区时,GdkTexture会接管缓冲区的所有权,不需要手动释放;如果不想转移所有权,可以用g_bytes_new(),但之后要自己管理内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 06:40:19