RHEL6.4+Cairo1.8.8环境下实现cairo_surface_set_device_scale等效功能问询
高画质等效实现cairo_surface_set_device_scale方案
画质差根因
当前使用的后处理缩放方案是对已渲染完成的位图做拉伸,默认采用低质量的最近邻插值,所以画质远低于原生接口。原生cairo_surface_set_device_scale的核心逻辑是修改surface的坐标变换矩阵,在内容绘制阶段就应用矢量缩放,而非对成品位图做二次拉伸。
实现方案
方案1:未向目标surface绘制内容(最优,100%对齐原生效果)
该方案不需要创建新surface,完全复用cairo原生矢量绘制能力,画质和原生接口完全一致:
// 自定义缩放参数存储的唯一key static cairo_user_data_key_t g_device_scale_key; // 完全匹配要求的函数原型 void cairo_surface_set_device_scale (cairo_surface_t *surface, double x_scale, double y_scale) { double *scale_params = malloc(2 * sizeof(double)); scale_params[0] = x_scale; scale_params[1] = y_scale; // 将缩放参数绑定到surface,surface销毁时自动释放内存 cairo_surface_set_user_data(surface, &g_device_scale_key, scale_params, free); } // 配套工具函数:每次基于目标surface创建cairo_t后调用,自动应用缩放 void cairo_apply_device_scale(cairo_t *cr, cairo_surface_t *target_surface) { double *scale_params = cairo_surface_get_user_data(target_surface, &g_device_scale_key); if (scale_params != NULL) { cairo_scale(cr, scale_params[0], scale_params[1]); } }
使用时只需在所有创建cairo_t的代码后新增一行调用cairo_apply_device_scale即可,原有绘制逻辑不需要任何修改。
方案2:已绘制完成的surface做缩放
如果是已经渲染好的位图surface需要缩放,优化原有缩放函数的滤波配置即可大幅提升画质:
cairo_surface_t *high_quality_scale_surface(cairo_surface_t *src_surface, int orig_width, int orig_height, double x_scale, double y_scale) { int new_width = orig_width * x_scale; int new_height = orig_height * y_scale; cairo_surface_t *dst_surface = cairo_surface_create_similar(src_surface, cairo_surface_get_content(src_surface), new_width, new_height); cairo_t *cr = cairo_create(dst_surface); // 为源surface创建pattern并设置最高质量滤波 cairo_pattern_t *src_pattern = cairo_pattern_create_for_surface(src_surface); cairo_pattern_set_filter(src_pattern, CAIRO_FILTER_BEST); cairo_scale(cr, x_scale, y_scale); cairo_set_source(cr, src_pattern); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); // 释放资源 cairo_pattern_destroy(src_pattern); cairo_destroy(cr); return dst_surface; }
该实现采用双三次插值做缩放,画质接近原生接口效果。
内容的提问来源于stack exchange,提问作者famedoro
相关产品推荐
相关产品推荐

