feat: Implement crush and save to png

This commit is contained in:
2026-02-28 01:09:51 +08:00
parent 1f8a2859f9
commit 6f6e6f326b
4 changed files with 196 additions and 18 deletions

View File

@@ -83,6 +83,44 @@ impl MSCanvas {
self.pixels.clone()
}
pub fn get_pixels_scale(&self, scale: i32) -> Vec<u8> {
if scale <= 1 {
return self.pixels.clone();
}
let dst_width = self.width * scale;
let dst_height = self.width * scale;
let mut dst = vec![0; (self.width * self.width * 4) as usize]; // RGBA
for y in 0..self.height {
for x in 0..self.width {
// 源像素索引
let src_idx = ((y * self.width + x) * 4) as usize;
// 源像素颜色
let r = self.pixels[src_idx];
let g = self.pixels[src_idx + 1];
let b = self.pixels[src_idx + 2];
let a = self.pixels[src_idx + 3];
// 在目标图像中填充 scale×scale 区域
for dy in 0..scale {
for dx in 0..scale {
let dst_x = x * scale + dx;
let dst_y = y * scale + dy;
let dst_idx = ((dst_y * dst_width + dst_x) * 4) as usize;
dst[dst_idx] = r;
dst[dst_idx + 1] = g;
dst[dst_idx + 2] = b;
dst[dst_idx + 3] = a;
}
}
}
}
dst
}
pub fn pixel_at(&self, x: i32, y: i32) -> MSColor {
// 边界检查
if x < 0 || x >= self.width || y < 0 || y >= self.height as i32 {
@@ -118,6 +156,25 @@ impl MSCanvas {
self.pixels[index + 3] = self.color.a; // A
}
pub fn draw_pixel_color_at(&mut self, point: Point, color: MSColor) {
let Point { x, y } = point;
let x = x as i32;
let y = y as i32;
// 边界检查
if x < 0 || x >= self.width || y < 0 || y >= self.height {
return;
}
// 计算索引:(y * width + x) * 4
let index = ((y * self.width + x) * 4) as usize;
// 写入 RGBA 数据
// 注意Color 的 r, g, b, a 是 0.0 - 1.0,需要转为 0 - 255
self.pixels[index] = color.r; // R
self.pixels[index + 1] = color.g; // G
self.pixels[index + 2] = color.b; // B
self.pixels[index + 3] = color.a; // A
}
fn draw_pixel_at1(&mut self, x: i32, y: i32) {
// 边界检查
if x < 0 || x >= self.width || y < 0 || y >= self.height {
@@ -160,6 +217,17 @@ impl MSCanvas {
}
}
pub fn draw_cross_color(&mut self, point: Point, color: MSColor) {
let Point { x, y } = point;
let r = 5;
for dy in -r..=r {
self.draw_pixel_color_at(Point::new(point.x, point.y + dy as f32), color);
}
for dx in -r..=r {
self.draw_pixel_color_at(Point::new(point.x + dx as f32, point.y), color);
}
}
pub fn brush_circle(&mut self, center: Point) {
if self.line_width <= 1 {
self.draw_pixel_at(center);
@@ -191,6 +259,27 @@ impl MSCanvas {
}
}
pub fn brush_slash(&mut self, center: Point) {
let r = self.line_width / 2;
let l = self.line_width - r;
// for dx in -1..1 {
// for d in -l..r {
// self.draw_pixel_at(Point::new(center.x - (d as f32) + (dx as f32), center.y - d as f32));
// }
// }
for d in -l..r {
self.draw_pixel_at(Point::new(center.x - (d as f32), center.y - d as f32));
}
}
pub fn brush_backslash(&mut self, center: Point) {
let r = self.line_width / 2;
let l = self.line_width - r;
for d in -l..r {
self.draw_pixel_at(Point::new(center.x + d as f32, center.y - d as f32));
}
}
fn bresenham_line(&mut self, begin: Point, end: Point) -> Vec<Point> {
let x1 = begin.x;
let y1 = begin.y;
@@ -433,6 +522,10 @@ impl MSCanvas {
}
pub fn stroke_rect(&mut self, x: i32, y: i32, width: i32, height: i32) {
if width < 2 * self.line_width || height < 2 * self.line_width {
self.fill_rect(x, y, width, height);
return;
}
self.fill_rect(x, y, width, self.line_width);
self.fill_rect(x, y + height - self.line_width, width, self.line_width);
self.fill_rect(x, y, self.line_width, height);
@@ -440,6 +533,7 @@ impl MSCanvas {
}
pub fn stroke_rect1(&mut self, p1: Point, p2: Point) {
self.draw_cross_color(p1, MSColor::new(255, 0, 0, 255));
let mut x = p1.x;
let mut y = p1.y;
let mut width = (p2.x - p1.x);