当前位置: 首页 > news >正文

<Rust><iced><resvg>基于rust使用iced构建GUI实例:使用resvg库实现svg转png

前言
本文是使用rust库resvg来将svg图片转为png图片。

环境配置
系统:windows
平台:visual studio code
语言:rust
库:resvg

代码分析

resvg是一个基于rust的svg渲染库,其官方地址:
An SVG rendering library

resvg库的核心是svg的渲染,但本文暂且不关注如何渲染svg,本文关注如何将svg转为png格式,官方有提供演示代码。

本文参考官方示例,将代码稍作修改,并结合rust的文件库rfd,编写一个简单的程序,可以导入svg图片,然后转为png图片,并保存。

首先看一下核心的转换代码:
官方代码:

fn main() {let args: Vec<String> = std::env::args().collect();if args.len() != 3 {println!("Usage:\n\tminimal <in-svg> <out-png>");return;}let tree = {let mut opt = usvg::Options::default();// Get file's absolute directory.opt.resources_dir = std::fs::canonicalize(&args[1]).ok().and_then(|p| p.parent().map(|p| p.to_path_buf()));opt.fontdb_mut().load_system_fonts();let svg_data = std::fs::read(&args[1]).unwrap();usvg::Tree::from_data(&svg_data, &opt).unwrap()};let pixmap_size = tree.size().to_int_size();let mut pixmap = tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height()).unwrap();resvg::render(&tree, tiny_skia::Transform::default(), &mut pixmap.as_mut());pixmap.save_png(&args[2]).unwrap();
}

本地使用时,简单封装成一个函数,如下:

///
/// svg转png
/// 
pub fn svgtopng(svgpath: &str,destimgpath: &str,
)
{let mut opt=resvg::usvg::Options::default();opt.resources_dir=std::fs::canonicalize(svgpath).ok().and_then(|p| p.parent().map(|p| p.to_path_buf()));opt.fontdb_mut().load_system_fonts();let svgdata=std::fs::read(svgpath).unwrap();let tree=resvg::usvg::Tree::from_data(&svgdata,&opt).unwrap();let pixmap_size = tree.size().to_int_size();let mut pixmap = resvg::tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height()).unwrap();resvg::render(&tree, resvg::tiny_skia::Transform::default(), &mut pixmap.as_mut());pixmap.save_png(destimgpath).unwrap();
}

转换的程序就好了,然后我们结合rust的GUI库iced来编写一个简单的带UI的转换程序,所以,我们还需要添加iced库,看一下toml文件:

[package]
name = "gui-serial"
version = "0.1.0"
edition = "2021"[dependencies]iced={version="0.12.1"}
iced_widget={version="0.12.3",features=[]}
serialport="4.3.0"
clap="4.5.7"image="0.25.1"resvg={version="0.42.0",features=[]}

关于iced以及rfd库的使用,此处不再赘述,可以参考本人的另外的博文:
Rust UI开发(三):iced如何打开图片(对话框)并在窗口显示图片?

我直接把主程序的代码贴在这:

use std::{io::{self,Write}, process::CommandArgs};use eximg::codecs::png;
use imgtoicon::image_to_icon;
use resvg::usvg::filter::Merge;
use serialport::{DataBits,StopBits,Parity};
//use clap::{value_parser, Arg, ArgAction, Command};
mod ser;
mod imgtoicon;
mod resvgpro;
use iced::{Application, Command, Element, Font, Renderer, Settings, Subscription};
use iced_widget::{container,button,text,column,row,svg,image};use rfd::FileDialog;extern  crate resvg;
extern crate image as eximg;#[derive(Debug,Clone)]
enum Message{Cvt,Open,Save,
}
struct Serial{portname:String,baudrate:u32,databits:DataBits,stopbits:StopBits,parity:Parity,timeout:u64,openfile:String,destfile:String,
}
fn main() ->iced::Result {let myicon=imgtoicon::image_to_icon("..\\gui-serial\\img\\mainicon4.png");let myfont="微软雅黑";Serial::run(Settings{id:Some("mw".to_string()),window:iced::window::Settings{size:iced::Size{width:800.0,height:600.0},min_size:Some(iced::Size { width: 200.0, height: 200.0 }),max_size:Some(iced::Size { width: 1000.0, height: 800.0 }),position:iced::window::Position::Specific(iced::Point::new(100.0,100.0)),icon:Some(myicon),level:iced::window::Level::Normal,..Default::default()},default_font:Font::with_name(myfont),..Default::default()})}impl Application for Serial{type Executor = iced::executor::Default;type Message = Message;type Flags = ();type Theme = iced::Theme;fn new(flags: Self::Flags) -> (Self, Command<Self::Message>) {(Self{portname:String::from("COM1"),baudrate:9600,databits:DataBits::Eight,stopbits:StopBits::One,parity:Parity::None,timeout:1000,openfile:String::from(""),destfile:String::from(""),},Command::none())}fn title(&self) -> String {String::from("串口调试工具-rs")}fn update(&mut self, message: Self::Message) -> Command<Self::Message> {match message{Message::Cvt=>{resvgpro::svgtopng(&self.openfile,&self.destfile)}Message::Open=>{if let Some(file)=FileDialog::new().set_title("打开文件").add_filter("svg", &["svg"]).pick_file(){self.openfile=file.display().to_string();}else{println!("打开文件失败")};}Message::Save=>{if let Some(file)=FileDialog::new().set_title("保存文件").add_filter("png", &["png"]).save_file(){let filestr=file.display().to_string();resvgpro::svgtopng(&self.openfile, &filestr);self.destfile=filestr;}else{println!("保存文件失败")};}}Command::none()}fn subscription(&self) -> Subscription<Self::Message> {Subscription::none()}fn view(&self) -> Element<'_, Self::Message, Self::Theme, crate::Renderer> {//let btn1=button("转换").on_press(Message::Cvt);let btn2=button("打开").on_press(Message::Open);let btn3=button("转换并保存").on_press(Message::Save);let svghandle=svg::Handle::from_path(&self.openfile);let pnghandle=image::Handle::from_path(&self.destfile);let col1=column![btn2,text(format!("打开文件路径:{}",&self.openfile)).size(15),btn3,text(format!("保存文件路径:{}",&self.destfile)).size(15),//btn1,row![svg(svghandle).content_fit(iced::ContentFit::Contain).width(300),image(pnghandle).content_fit(iced::ContentFit::Contain).width(300),].padding(5).spacing(20),].padding(5).spacing(5);let cont=container(col1).padding(5);cont.into()}
}

实例演示:
在这里插入图片描述

相关文章:

  • 数据仓库的实际应用示例-广告投放平台为例
  • 解决Qt中 -lGL无法找到的问题
  • Java数据类型与运算符
  • 小游戏app看广告app开发案例
  • NodeJs实现对本地 mysql 数据库的增删改查
  • Flink 窗口函数
  • 网络编程5----初识http
  • 类AAAAAAAAAAAA迭代
  • SpringBoot使用Redisson实现可重入分布式锁
  • 如何正确理解和评估品牌价值?
  • C语言循环中获取之前变量的值
  • fataadmin导出Exel文件图片太大
  • 雷池社区版自动SSL
  • Go语言 获取服务器资源磁盘Disk情况
  • Vue3DraggableResizable知识点
  • 0x05 Python数据分析,Anaconda八斩刀
  • 30天自制操作系统-2
  • 5、React组件事件详解
  • CentOS从零开始部署Nodejs项目
  • css选择器
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • Python3爬取英雄联盟英雄皮肤大图
  • SwizzleMethod 黑魔法
  • 程序员最讨厌的9句话,你可有补充?
  • 初探 Vue 生命周期和钩子函数
  • 从0实现一个tiny react(三)生命周期
  • 大主子表关联的性能优化方法
  • 记一次用 NodeJs 实现模拟登录的思路
  • 利用DataURL技术在网页上显示图片
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 中文输入法与React文本输入框的问题与解决方案
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • (1)SpringCloud 整合Python
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (笔试题)分解质因式
  • (创新)基于VMD-CNN-BiLSTM的电力负荷预测—代码+数据
  • (第30天)二叉树阶段总结
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (五)关系数据库标准语言SQL
  • (转载)Linux网络编程入门
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET CLR基本术语
  • .net core 连接数据库,通过数据库生成Modell
  • .NET Core引入性能分析引导优化
  • .Net mvc总结
  • .Net 垃圾回收机制原理(二)
  • .NET4.0并行计算技术基础(1)
  • .NET企业级应用架构设计系列之应用服务器
  • /dev/sda2 is mounted; will not make a filesystem here!