Skip to content

Commit 9bb8a64

Browse files
committed
[*] refactor
1 parent 7f0cfc3 commit 9bb8a64

File tree

18 files changed

+844
-149
lines changed

18 files changed

+844
-149
lines changed

lib/video-editor/src/filters/traits.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@ use std::{
1212
time::Duration,
1313
};
1414

15+
// 滤镜效果作用的位置
16+
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
17+
pub enum EffectPosition {
18+
Start, // 作用于 segment 开头
19+
End, // 作用于 segment 结尾
20+
}
21+
22+
impl Default for EffectPosition {
23+
fn default() -> Self {
24+
Self::Start
25+
}
26+
}
27+
1528
#[derive(Debug, Clone)]
1629
pub struct VideoFilterConfig {
1730
pub output_width: u32,

lib/video-editor/src/filters/video.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
1+
pub mod border;
12
pub mod chroma;
23
pub mod crop;
34
pub mod fade_in;
45
pub mod fade_out;
56
pub mod flip;
67
pub mod moving;
8+
pub mod opacity;
79
pub mod slide;
810
pub mod transform;
911
pub mod wipe;
1012
pub mod zoom;
1113

14+
pub use border::BorderFilter;
1215
pub use chroma::ChromaKeyFilter;
1316
pub use crop::CropFilter;
1417
pub use fade_in::FadeInFilter;
1518
pub use fade_out::FadeOutFilter;
1619
pub use flip::{FlipDirection, FlipFilter};
1720
pub use moving::{EasingFunction, MovingFilter};
21+
pub use opacity::OpacityFilter;
1822
pub use slide::{SlideDirection, SlideFilter};
1923
pub use transform::TransformFilter;
2024
pub use wipe::{WipeDirection, WipeFilter};
@@ -31,6 +35,8 @@ pub fn all_filter_names() -> &'static [&'static str] {
3135
FlipFilter::NAME,
3236
FadeInFilter::NAME,
3337
FadeOutFilter::NAME,
38+
BorderFilter::NAME,
39+
OpacityFilter::NAME,
3440
ChromaKeyFilter::NAME,
3541
]
3642
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use crate::{
2+
Result,
3+
filters::traits::{VideoData, VideoFilter},
4+
tracks::video_frame_cache::VideoImage,
5+
};
6+
use image::Rgba;
7+
8+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
9+
pub struct BorderFilter {
10+
pub size: u32, // border width in pixels
11+
pub color: [u8; 4], // RGBA color
12+
pub corner_radius: u32, // rounded corner radius
13+
}
14+
15+
impl Default for BorderFilter {
16+
fn default() -> Self {
17+
Self {
18+
size: 0,
19+
color: [0, 0, 0, 255],
20+
corner_radius: 0,
21+
}
22+
}
23+
}
24+
25+
impl BorderFilter {
26+
pub const NAME: &'static str = "border";
27+
28+
pub fn new(size: u32, color: [u8; 4], corner_radius: u32) -> Self {
29+
Self { size, color, corner_radius }
30+
}
31+
32+
fn draw_border(&self, image: &mut image::RgbaImage) {
33+
let width = image.width();
34+
let height = image.height();
35+
let border_color = Rgba(self.color);
36+
let size = self.size.min(width / 2).min(height / 2);
37+
38+
if size == 0 {
39+
return;
40+
}
41+
42+
// Draw top border
43+
for y in 0..size {
44+
for x in 0..width {
45+
image.put_pixel(x, y, border_color);
46+
}
47+
}
48+
49+
// Draw bottom border
50+
for y in (height - size)..height {
51+
for x in 0..width {
52+
image.put_pixel(x, y, border_color);
53+
}
54+
}
55+
56+
// Draw left border
57+
for y in size..(height - size) {
58+
for x in 0..size {
59+
image.put_pixel(x, y, border_color);
60+
}
61+
}
62+
63+
// Draw right border
64+
for y in size..(height - size) {
65+
for x in (width - size)..width {
66+
image.put_pixel(x, y, border_color);
67+
}
68+
}
69+
}
70+
}
71+
72+
impl VideoFilter for BorderFilter {
73+
crate::impl_default_video_filter!(BorderFilter);
74+
75+
fn apply(&self, data: &mut VideoData) -> Result<()> {
76+
for frame in &mut data.frames {
77+
if let VideoImage::Image { buffer, .. } = frame {
78+
self.draw_border(buffer);
79+
}
80+
}
81+
Ok(())
82+
}
83+
}

lib/video-editor/src/filters/video/flip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::{
33
filters::traits::{VideoData, VideoFilter},
44
tracks::video_frame_cache::VideoImage,
55
};
6-
use image::{imageops, RgbaImage};
6+
use image::{RgbaImage, imageops};
77

88
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
99
pub enum FlipDirection {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use crate::{
2+
Result,
3+
filters::traits::{VideoData, VideoFilter},
4+
tracks::video_frame_cache::VideoImage,
5+
};
6+
use rayon::prelude::*;
7+
8+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
9+
pub struct OpacityFilter {
10+
pub opacity: f32, // 0.0 = fully transparent, 1.0 = fully opaque
11+
}
12+
13+
impl Default for OpacityFilter {
14+
fn default() -> Self {
15+
Self { opacity: 1.0 }
16+
}
17+
}
18+
19+
impl OpacityFilter {
20+
pub const NAME: &'static str = "opacity";
21+
22+
pub fn new(opacity: f32) -> Self {
23+
Self { opacity: opacity.clamp(0.0, 1.0) }
24+
}
25+
}
26+
27+
impl VideoFilter for OpacityFilter {
28+
crate::impl_default_video_filter!(OpacityFilter);
29+
30+
fn apply(&self, data: &mut VideoData) -> Result<()> {
31+
for frame in data.frames.iter_mut() {
32+
if let VideoImage::Image { buffer, .. } = frame {
33+
buffer.par_pixels_mut().for_each(|pixel| {
34+
pixel.0[3] = ((pixel.0[3] as f32) * self.opacity).clamp(0.0, 255.0) as u8;
35+
});
36+
}
37+
}
38+
Ok(())
39+
}
40+
}

0 commit comments

Comments
 (0)