未能在开罗覆盖抗锯齿像素

时间:2016-09-15 21:24:44

标签: cairo antialiasing

在使用Cairo 1.14.6进行显示时,我发现用另一种颜色覆盖相同的路径并不一定会覆盖所有像素,并留下不良背景。

作为我的主张的证据,我从一个简短的自成一体的例子中提供了这个输出,其来源如下:

enter image description here

从左到右解释图像的六个部分:

  1. 原始形状用蓝色抚摸。
  2. 原始形状以RGBA白色覆盖。
  3. 原始形状以RGB白色覆盖。
  4. 使用CAIRO_OPERATOR_SOURCE模式以RGBA白色覆盖原始形状。
  5. 使用CAIRO_OPERATOR_SOURCE模式和CAIRO_ANTIALIAS_NONE以RGBA白色覆盖原始形状。
  6. 使用CAIRO_OPERATOR_SOURCE模式和CAIRO_ANTIALIAS_BEST以RGBA白色覆盖原始形状。
  7. 图像是根据以下代码生成的:

    #include "cairo/cairo.h"
    
    #define M_PI 3.14159265358979323846
    
    void draw_shape(cairo_t* cr, int x, int y) {
        cairo_arc(cr, 50 + x, 50 + y, 48, -M_PI, -M_PI / 2);
        cairo_stroke(cr);
        cairo_move_to(cr, x + 2, y + 2);
        cairo_line_to(cr, x + 48, y + 48);
        cairo_stroke(cr);
    }
    
    int main(int argc, char** argv) {
        int x = 0;
        int y = 0;
        cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 50);
        cairo_t* cr = cairo_create(surface);
    
        /* Draw a white background and a few shapes to overwrite */
        cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
        cairo_paint(cr);
        cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 1.0);
        draw_shape(cr, x, y); x += 50;
        draw_shape(cr, x, y); x += 50;
        draw_shape(cr, x, y); x += 50;
        draw_shape(cr, x, y); x += 50;
        draw_shape(cr, x, y); x += 50;
        draw_shape(cr, x, y); x += 50;
        x = 50;
    
        /* Leftmost shape is left unchanged for reference */
    
        /* Stroke in RGBA opaque white */
        cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
        draw_shape(cr, x, y); x += 50;
    
        /* Stroke in RGB white */
        cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
        draw_shape(cr, x + 0, y); x += 50;
    
        /* Stroke in opaque white without blending */
        cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
        draw_shape(cr, x, y); x += 50;
    
        /* Stroke in opaque white without blending, with no antialiasing */
        cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
        cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
        draw_shape(cr, x, y); x += 50;
    
        /* Stroke in opaque white without blending, with best antialiasing */
        cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
        cairo_set_antialias(cr, CAIRO_ANTIALIAS_BEST);
        draw_shape(cr, x, y); x += 50;
    
        /* Write the results to a file */
        cairo_surface_write_to_png(surface, "output.png");
    
        return 0;
    }
    

    对我来说,直接意义上覆盖相同的形状不会覆盖其所有像素,特别是如果我强制它进入非混合CAIRO_OPERATOR_SOURCE模式。在构成我的实际表面的帧缓冲区上的结果是相同的,所以这不是后端的问题。

    开罗通常非常擅长于此,我对此感到非常惊讶。难道没有办法在开罗完全覆盖抗锯齿形状吗?

1 个答案:

答案 0 :(得分:0)

我试图做的事情显然是不可能的。我将question发布到了Cairo邮件列表中,并提供了两个选项:

  1. 在绘制之前保留原始像素的副本:“消除锯齿涉及混合。如果您不想要消除锯齿,请将其关闭。” (Link
  2. 以更高的分辨率绘制:“唯一真正的解决方案是绘制更高的分辨率,覆盖范围四舍五入到每个像素正好为零或一个。” (Link
  3. 更具体地说:

      

    从第一张图中存储在像素中的所有内容都是   像素的百分比被形状覆盖。它不记得了   确切地覆盖了像素的哪些部分。

    由于抗锯齿必然涉及混合,并且由于开罗不记得子像素的哪个部分导致混合,因此无法知道如何撤消混合。