在GNOME/gdk/gtkmm/cairo下如何实现MS Windows TransparentBlt()等效功能
MFC TransparentBlt 移植到 gtkmm/Cairo 平台等效实现方案
gtkmm 原生的 copy_area() 方法不支持指定透明关键色,要实现和 MFC TransparentBlt() 一致的效果,可以选择以下两种适配方案:
方案一:预处理 Gdk::Pixbuf 加透明通道(兼容原有 copy_area 逻辑)
该方案适合不需要保留源位图原始内容的场景,性能更高,可直接复用现有代码逻辑:
// 定义你需要的透明关键色,这里对应示例中的RGB(255,255,255)白色 const guint8 key_r = 255, key_g = 255, key_b = 255; // 先给不带alpha通道的源Pixbuf添加alpha通道,通道数会变成4 if (image1->get_n_channels() == 3) { image1 = image1->add_alpha(false, 0, 0, 0); } int rowstride = image1->get_rowstride(); guint8* pixels = image1->get_pixels(); // 遍历要复制的区域像素,匹配关键色的像素设为全透明 for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { guint8* pixel = pixels + y * rowstride + x * 4; if (pixel[0] == key_r && pixel[1] == key_g && pixel[2] == key_b) { pixel[3] = 0; // alpha通道设为0,全透明 } else { pixel[3] = 255; // 不透明 } } } // 预处理完成后直接调用原有copy_area逻辑即可,透明像素会自动被跳过 image1->copy_area(0, 0, width, height, Total, position.x, position.y);
方案二:基于Cairo临时表面实现(不修改源位图)
如果需要保留源位图的原始内容,使用临时Cairo表面做中间处理即可:
// 目标上下文cr是对应TotalDC的Cairo::RefPtr<Cairo::Context>对象 const guint8 key_r = 255, key_g = 255, key_b = 255; // 创建和源位图尺寸一致的临时ARGB表面 Cairo::RefPtr<Cairo::ImageSurface> temp_surface = Cairo::ImageSurface::create( Cairo::FORMAT_ARGB32, width, height ); Cairo::RefPtr<Cairo::Context> temp_cr = Cairo::Context::create(temp_surface); // 将源Pixbuf绘制到临时表面 Gdk::Cairo::set_source_pixbuf(temp_cr, image1, 0, 0); temp_cr->paint(); unsigned char* surface_data = temp_surface->get_data(); int stride = temp_surface->get_stride(); // 遍历临时表面像素过滤关键色,注意Cairo ARGB32为小端存储,像素顺序为B、G、R、A for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { unsigned char* pixel = surface_data + y * stride + x * 4; if (pixel[2] == key_r && pixel[1] == key_g && pixel[0] == key_b) { pixel[3] = 0; } } } // 将处理后的临时表面绘制到目标位置 cr->set_source(temp_surface, position.x, position.y); cr->paint();
注意事项
- 方案一修改了源Pixbuf的内容,如果你后续还需要用到原始的源位图,不要使用该方案
- 两种方案都兼容GTK3、GTK4版本的gtkmm封装,无需依赖第三方库
内容的提问来源于stack exchange,提问作者Frank
相关产品推荐
相关产品推荐

