图片像素转HTML渲染器
项目简介
该项目实现了将图片逐像素转换为 HTML 网格的功能。每个像素会被渲染为一个带样式的 <span>
标签,通过背景色和文本内容还原图片的视觉效果。
功能特点
- 图片读取与处理:支持多种图片格式(如 PNG、JPG 等)。
- 尺寸调整:按指定宽度重新调整图片大小,自动保持宽高比。
- HTML 生成:逐像素生成 HTML,每个像素以
<span>
元素表示,颜色与图片像素一致,支持自定义内容符号。 - 模板化支持:支持自定义 HTML 文件和像素元素的模板。
环境要求
Rust
最新稳定版image
crate 进行图片处理
项目结构
.
├── src/
│ ├── main.rs # 主程序代码
├── template/
│ ├── html # HTML 模板文件
│ └── element # 元素模板文件
├── girl.png # 输入图片示例文件
├── out.html # 输出HTML文件(运行后生成)
├── Cargo.toml # 项目依赖配置
准备工作
添加依赖
在 Cargo.toml 文件中添加以下依赖:
[dependencies]
image = "0.25.5"
模板准备
- 主体
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Generated by image_to_ascii v0.1.0</title>
</head>
<body>
<div style="font-family: monospace, fixed; font-weight: bold;">
{body}
</div>
</body>
</html>
- 像素模板
<span style="color:rgba({color});background-color:rgba({background-color})">{inner-text}</span>
代码
use std::error::Error;
use std::fs;
use image::{DynamicImage, GenericImageView, Pixel};
use image::imageops::FilterType;
// 图片缩放比例
const RATIO: f32 = 0.2;
// html模板
const HTML_TEMPLATE_PATH: &str = "template/html";
// 元素模板
const ELEMENT_TEMPLATE_PATH: &str = "template/element";
// 输入图片路径
const IMG_PATH: &str = "girl.png";
// 输出html路径
const HTML_PATH: &str = "out.html";
fn main() -> Result<(), Box<dyn Error>> {
// 读取模板
let html_template = fs::read_to_string(HTML_TEMPLATE_PATH)?;
let element_template = fs::read_to_string(ELEMENT_TEMPLATE_PATH)?;
// 读取图片
let img = image::open(IMG_PATH)?;
let resized_img = resize_img(&img);
let (width, height) = resized_img.dimensions();
let mut body: Vec<String> = vec![];
for h in 0..height {
for w in 0..width {
let element = element_template.clone();
// 获取每个像素点的颜色
let rgba = resized_img.get_pixel(w, h).to_rgba();
// 填充颜色到css样式
let element = element.replace("{color}", format!("{},{},{},{}", rgba[0], rgba[1], rgba[2], rgba[3]).as_str());
let element = element.replace("{background-color}", format!("{},{},{},{}", rgba[0], rgba[1], rgba[2], rgba[3]).as_str());
let element = element.replace("{inner-text}", "@");
body.push(element);
}
// 每行像素遍历完成后添加换行标签
body.push(String::from("</br>"));
}
let html = html_template.replace("{body}", &*body.join(""));
fs::write(HTML_PATH, html)?;
Ok(())
}
// 调整图片大小
fn resize_img(img: &DynamicImage) -> DynamicImage {
let (width, height) = img.dimensions();
let new_width = width as f32 * RATIO;
let new_height = height as f32 * RATIO;
img.resize(new_width as u32, new_height as u32, FilterType::Nearest)
}
示例输出
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image to HTML</title>
</head>
<body>
<span style="color: rgba(255,0,0,255); background-color: rgba(255,0,0,255);">@</span>
<span style="color: rgba(0,255,0,255); background-color: rgba(0,255,0,255);">@</span>
<span style="color: rgba(0,0,255,255); background-color: rgba(0,0,255,255);">@</span>
...
</body>
</html>