• cario库——C++画图


    RGBA

    • rgb:红绿蓝

      • rgb(0,0,0):黑色
      • rgb(255,255,255):白色
    • rgba:红绿蓝+透明度(0:完全透明,1:完全不透明)

      • rgba(255,255,255,0)则表示完全透明的白色;
      • rgba(0,0,0,1)则表示完全不透明的黑色;
      • rgba(0,0,0,0)则表示完全不透明的白色,也即是无色

    Cario库是一个用于图形绘制的开源C++库,主要用于处理2D图形的渲染和绘制。Cario库通过使用矢量图形来实现高质量的渲染,这意味着图形可以按照任意缩放级别进行绘制而不会产生锯齿或像素化。

    头文件:#include

    1. 多个(x,y)坐标点,连成线

    示例:
    	#include 
    	// 创建一个画布
    	cairo_surface_t* surface;
    	// 创建画布之后,需要一个管理员,即上下文
    	cairo_t* cr;
    	
    	// 创建基于PNG图像文件
    	surface = cairo_image_surface_create_from_png("./one.png"); // (CAIRO_FORMAT_A8, _param_width, _param_height);
    	// _get_width()和_get_height()是用于获取图像表面宽度和高度的函数
    	int w = cairo_image_surface_get_width(surface);
    	int h = cairo_image_surface_get_height(surface);
    
    	//
    	cr = cairo_create(surface);
    	cairo_set_source_rgb(cr, 1, 1, 0);  //1,1,0表示黄色(1,0,0 表示红色)
    	cairo_set_line_width(cr, 3);  // 设置前线条宽度设置为指定的值。它接受2个参数,第一个参数是 Cairo 上下文对象,第二个参数是线条宽度
    	
    	// 定义一个面,一个面包含N个点
    	vector<point_int> all_point ;
    	// 每个点的结构体,
    	sturct point_int
    	{
    		int x;
    		int y;
    	};
    	// 绘制原始边界
    	if (all_point.size() > 0)
    	{
    			// 绘制原始边界
    			// cairo_move_to(cr, x, y) 函数将当前绘图点移动到坐标为(x, y) 的位置
    			cairo_move_to(cr, all_point[m].x, all_point[m].y);
    			for (int i = 1; i < all_point.size(); i++)
    			{
    				//cairo_line_to(cr, x, y) 函数会从当前绘图点绘制一条到(x, y) 坐标点的直线。
    				if (all_point[i].x > w)
    				{
    					all_point[i].x = w;
    				}
    				if (all_point[i].y > h)
    				{
    					all_point[i].y = h;
    				}
    				cairo_line_to(cr, all_point[i].x, all_point[i].y);
    			}
    			// 再次连线到起始点,使其闭合起来,也可以使用 cairo_close_path() 函数
    			cairo_line_to(cr, all_point.at(0).x, all_point.at(0).y);
    			//cairo_close_path() 函数用于将当前路径的最后一个点连接到路径起点,从而封闭路径。
    			cairo_close_path(cr);
    			//cairo_stroke() 函数则是用于描边并显示出路径的函数。
    			cairo_stroke(cr);
    		}
    
    		// _write_to_png() 函数用于将 Cairo 库中的 cairo_surface_t 对象保存为 PNG 文件,需要指定 PNG 文件的路径。
    		cairo_surface_write_to_png(surface, "./result.png");
    
    		// cairo_destroy() 和 cairo_surface_destroy() 函数则分别用于释放绘图环境和绘图表面的内存资源。
    		cairo_destroy(cr);
    		cairo_surface_destroy(surface);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • cairo_image_surface_create_from_png()是用于创建基于PNG图像文件创建表面的函数之一
      该函数将指定路径上的 PNG 文件读入一个新表面中,返回的指针就是新创建的cairo_surface_t类型的表面。如果读取 PNG 文件失败或文件格式不正确,则函数返回一个 NULL 指针。

    • cairo_create()是用于创建新上下文对象的函数,该函数创建和返回一个新的 Cairo 上下文对象,该对象链接到指定的表面(cairo_surface_t类型)。使用该对象,您可以执行各种绘图操作,包括绘制线条、矩形、文本、图像等。

    2. 画圆

    1. cairo_arc(cr, centerX, centerY, radius, 0, 2 * M_PI);
    2. cairo_arc 是Cairo库提供的函数,用于绘制一段圆弧。在这里,它被用来绘制一个完整的圆。
    3. cr 是Cairo渲染上下文,这是你之前创建并初始化的渲染上下文。
    4. centerX和 centerY是圆的中心坐标,表示在渲染上下文中绘制圆的位置。
    5. radius 是圆的半径,表示圆的大小。
    6. 0 是起始角度,这里是0弧度,表示圆的起始点。
    7. 2 * M_PI是结束角度,表示圆的结束点。SU_PI(可能是一个常数或宏定义)通常等于圆周率π的两倍,因此2 * SU_PI 表示一个完整的圆。
    8. cairo_stroke(m_cairo_render.m_cr);:
    9. cairo_stroke 函数是Cairo库的函数,用于在渲染上下文中描边已经绘制的图形。
    #include 
    #define M_PI       3.14159265358979323846   // pi
    // 定义一个绘制圆的函数
    void drawCircle(cairo_t *cr, double centerX, double centerY, double radius) {
        // 开始绘制路径
        cairo_new_path(cr);
        // 移动到圆心
        cairo_move_to(cr, centerX, centerY);
        // 绘制圆形
        cairo_arc(cr, centerX, centerY, radius, 0, 2 * M_PI);
        // 关闭路径
        cairo_close_path(cr);
        // 设置填充颜色
        cairo_set_source_rgb(cr, 0, 0, 0); // 黑色
        // 填充圆形
        cairo_fill(cr);
    }
    
    int main() {
        // 创建Cairo绘图上下文
        cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 400, 400);
        cairo_t *cr = cairo_create(surface);
        // 绘制圆形
        double centerX = 200.0;
        double centerY = 200.0;
        double radius = 100.0;
        drawCircle(cr, centerX, centerY, radius);
        // 保存绘图到文件
        cairo_surface_write_to_png(surface, "./circle.png");
        // 清理资源
        cairo_destroy(cr);
        cairo_surface_destroy(surface);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    实现效果
    在这里插入图片描述

    3. 填充颜色

    #define M_PI       3.14159265358979323846   // pi
    #include 
    // 定义一个绘制六边形的函数
    void drawHexagon(cairo_t* cr, double centerX, double centerY, double sideLength) {
        // 计算六边形的顶点坐标
        double x[6];
        double y[6];
        for (int i = 0; i < 6; ++i) {
            x[i] = centerX + sideLength * cos(i * M_PI / 3);
            y[i] = centerY + sideLength * sin(i * M_PI / 3);
        }
    
        // 开始绘制路径
        cairo_new_path(cr);
        // 移动到第一个顶点
        cairo_move_to(cr, x[0], y[0]);
    
        // 依次连接六个顶点
        for (int i = 1; i < 6; ++i) {
            cairo_line_to(cr, x[i], y[i]);
        }
    
        // 关闭路径
        cairo_close_path(cr);
        // 设置线段粗细
        cairo_set_line_width(cr, 3.0);
        // 设置内部填充颜色
        cairo_set_source_rgba(cr, 1.0, 1.0, 0.0, 1.0); // 黄色
        // 填充六边形
        cairo_fill_preserve(cr);
        // 设置边框颜色
        cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); // 黑色
        // 绘制边框
        cairo_stroke(cr);
    
    }
    
    int main() {
        // 创建Cairo绘图上下文
        cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 400, 400);
        cairo_t* cr = cairo_create(surface);
    
        // 绘制六边形
        double centerX = 200.0;
        double centerY = 200.0;
        double sideLength = 100.0;
        drawHexagon(cr, centerX, centerY, sideLength);
    
        // 保存绘图到文件
        cairo_surface_write_to_png(surface, "../hexagon3.png");
    
        // 清理资源
        cairo_destroy(cr);
        cairo_surface_destroy(surface);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    效果

    在这里插入图片描述

    在 Cairo 绘图库中,cairo_stroke(cr) 和 cairo_stroke_preserve(cr) 是两个不同的函数,它们的行为稍有不同。

    cairo_stroke(cr):
        这个函数用于绘制当前路径的线段,也就是描绘路径的轮廓。
        在执行 cairo_stroke(cr) 后,路径将被清除,不再保留,因此你不能再在同一个路径上执行其他操作(如填充)。
        用于绘制路径的轮廓,并清除路径,以便进行其他绘图操作。
    
    cairo_stroke_preserve(cr):
        这个函数与 cairo_stroke(cr) 的区别在于它绘制路径的线段,但不清除路径,因此路径保持在当前上下文中,你可以随后在相同路径上执行其他操作,比如填充。
        用于绘制路径的轮廓,但路径仍然保持在上下文中,可用于后续绘制操作。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    所以,如果你想在同一个路径上同时绘制边框和填充,你应该使用 cairo_stroke_preserve(cr) 来先绘制边框,然后再进行填充,而不是 cairo_stroke(cr),因为后者会清除路径,使填充无法进行。

    在 Cairo 绘图库中,cairo_fill(cr) 和 cairo_fill_preserve(cr) 也是两个有明显区别的函数:

    1.cairo_fill(cr):

    这个函数用于填充当前路径的内部区域。
    执行完 cairo_fill(cr) 后,路径将被清除,不再保留。也就是说,你不能再在同一个路径上执行其他操作(如描边)。
    主要用于填充路径的内部并清除路径,以便进行其他绘图操作。
    
    • 1
    • 2
    • 3

    2.cairo_fill_preserve(cr):

    与 cairo_fill(cr) 的区别在于它填充路径的内部,但不清除路径。所以路径仍然存在于当前的上下文中,
    这允许你随后在相同的路径上执行其他操作,比如描边。
    主要用于填充路径的内部,但路径仍然存在于上下文中,可用于后续绘制操作。
    
    • 1
    • 2
    • 3

    所以,如果你想在同一个路径上同时进行填充和描边,你应该使用 cairo_fill_preserve(cr) 进行填充,然后再描边。这与先前我提到的 cairo_stroke_preserve(cr) 的工作方式相似,但它是用于填充而不是描边的。

    4. 曲线图

        double x = 25.6, y = 128.0;
        double x1 = 102.4, y1 = 230.4, x2 = 153.6, y2 = 25.6, x3 = 230.4, y3 = 128.0;
        // 画曲线图
        cairo_move_to(cr, x, y);
        cairo_curve_to(cr, x1, y1, x2, y2, x3, y3);
        cairo_set_line_width(cr, 10.0);
        cairo_stroke(cr);
        // 曲线坐标对应的直线
        cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.8);
        cairo_set_line_width(cr, 6.0);
        cairo_move_to(cr, x, y);   
        cairo_line_to(cr, x1, y1);
        cairo_line_to(cr, x2, y2);
        cairo_line_to(cr, x3, y3);
        cairo_stroke(cr);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    效果

    在这里插入图片描述

  • 相关阅读:
    Kubernetes实战(五)-pod之间网络请求实战
    Linux 5.19内核终于接纳了Zstd压缩固件更新
    事件驱动的微服务、CQRS、SAGA、Axon、Spring Boot
    Spring Cloud Eureka:服务注册与发现
    webpack原理篇(五十八):实战开发一个简易的webpack
    09 数据库查询(3) | OushuDB 数据库使用入门
    网站全灰,仅需一行css代码
    js显示隐藏密码框
    从0到1搭建大数据平台之数据存储
    【java】mybatis拦截器实现单表对于geometry类型字段的新增查询更新
  • 原文地址:https://blog.csdn.net/mankeywang/article/details/131713505