rust 实现图像绕中心点旋转任意角度
use env_logger::Env;
use image::RgbaImage;
use log::{info, LevelFilter};
use nalgebra as na;
use std::env;
use std::fs::File;
use std::path::Path;
use std::thread::sleep;
use std::time::Duration;
fn generate_matrix(theta: f64, pos: (f64, f64)) -> na::Matrix3<f64> {
let (x0, y0) = pos;
let c = f64::cos(theta.to_radians());
let s = f64::sin(theta.to_radians());
let mut matrix = na::Matrix3::zeros();
matrix[(0, 0)] = c;
matrix[(0, 1)] = -s;
matrix[(1, 0)] = s;
matrix[(1, 1)] = c;
matrix[(0, 2)] = -c * x0 + s * y0 + x0;
matrix[(1, 2)] = -c * y0 - s * x0 + y0;
matrix[(2, 2)] = 1.0;
matrix
}
fn main() {
// env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
let target = Box::new(File::create("log.txt").expect("Can't create file"));
env_logger::Builder::new()
.filter_level(LevelFilter::Info)
.write_style(env_logger::fmt::WriteStyle::Always)
.target(env_logger::Target::Pipe(target))
.init();
// 获取命令行参数
let args: Vec<String> = env::args().collect();
// 检查参数数量
if args.len() != 4 {
info!(
"Usage: {} <image_path> <rotation_angle> <output_path>",
args[0]
);
return;
}
// 解析参数
let image_path = &args[1];
let output_path = &args[2];
let rotation_angle: f64 = match args[3].parse() {
Ok(angle) => angle,
Err(_) => {
info!("Error: Invalid rotation angle");
return;
}
};
// 加载图像
let img = match image::open(&Path::new(image_path)) {
Ok(img) => img.to_rgba8(), // Ensure the image is in RGBA format
Err(err) => {
info!("Error: {}", err);
return;
}
};
info!("Image width {}, height{}", img.width(), img.height());
// 获取图像的中心点
let center = na::Point2::new((img.width() / 2) as f32, (img.height() / 2) as f32);
info!("Image center {}", center);
info!("rotation_angle {}", rotation_angle);
let mut x_min = 0;
let mut x_max = 0;
let mut y_min = 0;
let mut y_max = 0;
// 计算旋转矩阵
let rotation_matrix = generate_matrix(rotation_angle, (center.x.into(), center.y.into()));
// 遍历旋转后的图像像素,找到最小的x和y
for y in 0..img.height() {
for x in 0..img.width() {
info!("-----------");
info!("point to trans x:{:.2}, y:{:.2}", x, y);
let point_after_rotate =
rotation_matrix.transform_point(&na::Point2::new(x as f64, y as f64));
info!(
"point_after_rotate x:{:.2}, y:{:.2}",
point_after_rotate.x, point_after_rotate.y
);
if point_after_rotate.x < x_min as f64 {
x_min = point_after_rotate.x as i32;
}
if point_after_rotate.y < y_min as f64 {
y_min = point_after_rotate.y as i32;
}
if (point_after_rotate.x as i32) > x_max {
x_max = point_after_rotate.x as i32;
}
if (point_after_rotate.y as i32) > y_max {
y_max = point_after_rotate.y as i32;
}
}
}
let new_img_width = (x_max - x_min).try_into().unwrap();
let new_img_height = (y_max - y_min).try_into().unwrap();
info!(
"new_img_width {}, new_img_height{}",
new_img_width, new_img_height
);
// 创建一个新的空白图像用于存储旋转后的图像
let mut rotated_img = RgbaImage::new(new_img_width, new_img_height);
let rotation_matrix_inv = rotation_matrix.try_inverse().unwrap();
// 计算旋转后的图像像素点在原图像中的位置
for y in y_min..y_max {
for x in x_min..x_max {
let point_in_origin_img =
rotation_matrix_inv.transform_point(&na::Point2::new(x.into(), y.into()));
info!(
"point_in_origin_img x:{:.2}, y:{:.2}",
point_in_origin_img.x, point_in_origin_img.y
);
if point_in_origin_img.x >= 0.0
&& point_in_origin_img.x < (img.width() as f32).into()
&& point_in_origin_img.y >= 0.0
&& point_in_origin_img.y < (img.height() as f32).into()
{
rotated_img.put_pixel(
(x + x_min.abs()) as u32, // 图像的坐标从0开始,所以要加上x_min的绝对值
(y + y_min.abs()) as u32,
*img.get_pixel(point_in_origin_img.x as u32, point_in_origin_img.y as u32),
);
}
}
}
// 保存旋转后的图像
if let Err(err) = image::DynamicImage::ImageRgba8(rotated_img).save(&Path::new(output_path)) {
info!("Error: {}", err);
return;
}
info!("Image rotated successfully and saved to {}", output_path);
}
使用:
.\image_rotate.exe C:\Users\xxx\Desktop\a.png C:\Users\itfanr\xxx\b.png 30
转载请注明原文链接:https://www.cnblogs.com/itfanr/p/17894182.html
公众号:小弧光黑板报