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

如何在Gtk4中从guchar*像素获取整数格式RGB颜色值

问题排查与修复方案

以下是你的Gtk4取色器代码中存在的关键问题及对应修复方法:

1. 通道取值逻辑错误(核心问题)

你在get_pixel函数中错误地将p[0]赋值给aa,但GdkPixbuf从Cairo ARGB32表面转换后,通道顺序为RGBA:p[0]是红色、p[1]是绿色、p[2]是蓝色、p[3]是Alpha。同时全局变量aa,gg,bb容易引发作用域问题,建议改为静态变量:

static int picked_r, picked_g, picked_b;

static void
get_pixel (GdkPixbuf *pixbuf, int x, int y)
{
    int width = gdk_pixbuf_get_width (pixbuf);
    int height = gdk_pixbuf_get_height (pixbuf);

    if ((x >= 0 && x < width) && (y >= 0 && y < height)){
        gint rowstride, n_channels;
        guchar *pixels, *p;

        n_channels = gdk_pixbuf_get_n_channels (pixbuf);
        rowstride = gdk_pixbuf_get_rowstride (pixbuf);
        pixels = gdk_pixbuf_get_pixels (pixbuf);

        p = pixels + y * rowstride + x * n_channels;
        picked_r = p[0]; // 红色通道
        picked_g = p[1]; // 绿色通道
        picked_b = p[2]; // 蓝色通道
        printf("Pixel Col: %d x %d | R:%u G:%u B:%u A:%u\n", x, y, p[0], p[1], p[2], p[3]);
    } else {
        printf("Pixel out of bounds!\n");
    }
}

2. 取色源与显示内容不一致

draw_function中仅注释了Pixbuf转Cairo上下文的逻辑,但未实际实现,导致绘图区域显示的内容和取色用的Pixbuf完全无关。需要补充绘制代码:

static void
draw_function (GtkDrawingArea *area,
               cairo_t        *cr,
               int             width,
               int             height,
               gpointer        data)
{
    GdkPixbuf *p = get_gradientData (width, height, current_r, current_g, current_b, 255);
    // 将Pixbuf绘制到Cairo上下文
    gdk_cairo_set_source_pixbuf(cr, p, 0, 0);
    cairo_paint (cr);
    g_object_unref (p);
}

3. 坐标与尺寸不匹配

点击事件中创建的Pixbuf是固定270x270,但绘图区域实际尺寸可能不同,导致坐标错位。需使用当前绘图区域的尺寸创建取色用Pixbuf,同时将浮点坐标转为整数:

static void click_pos_on_button_release (GtkGesture *click,
                                         int n_press,
                                         gdouble x,
                                         gdouble y,
                                         gpointer user_data)
{
    GtkWidget *area = GTK_WIDGET(user_data);
    int width = gtk_widget_get_width(area);
    int height = gtk_widget_get_height(area);
    
    g_print ("Clicked pos: %0.0f  %0.0f\n", x, y);
    GdkPixbuf *p = get_gradientData(width, height, current_r, current_g, current_b, 255); 
    get_pixel (p, (int)x, (int)y);
    g_object_unref (p);
    printf("Pixel:%d x %d | %d %d %d\n", (int)x, (int)y, picked_r, picked_g, picked_b);
}

4. 参数类型与命名冲突

  • get_gradientData的a参数是guchar类型(取值0-255),但你调用时传了浮点数1.0,会被截断为0,导致透明度异常,应传255表示完全不透明。
  • 全局变量r,g,b与函数参数重名,建议改为current_r, current_g, current_b,并设置合理初始值(比如255,0,0表示红色):
int current_r = 255, current_g = 0, current_b = 0;

5. 窗口与事件控制器初始化缺失

主函数中未创建主窗口,也未将手势控制器添加到绘图区域,补充后代码才能正常运行:

static void
activate (GtkApplication* app,
          gpointer        user_data)
{
    GtkWidget *window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "Color Picker");
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
    
    GtkWidget *area = gtk_drawing_area_new();
    gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (area),
                                    draw_function,
                                    NULL, NULL);
    
    GtkGesture *gesture_click = gtk_gesture_click_new ();
    g_signal_connect (gesture_click, "released", G_CALLBACK(click_pos_on_button_release), area);
    gtk_widget_add_controller(area, GTK_EVENT_CONTROLLER(gesture_click));
    
    gtk_window_set_child(GTK_WINDOW(window), area);
    gtk_widget_show (window);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:34:56