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

