Skip to content

Commit 8771309

Browse files
committed
[*] refactor
1 parent bcfd0e6 commit 8771309

File tree

11 files changed

+239
-193
lines changed

11 files changed

+239
-193
lines changed

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

Lines changed: 30 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use crate::{
44
tracks::video_frame_cache::VideoImage,
55
};
66
use image::{RgbaImage, imageops};
7-
use rayon::prelude::*;
87
use video_utils::convert::resize_rgba_image_contain;
98

109
#[derive(
@@ -108,8 +107,6 @@ impl CropFilter {
108107
Ok(())
109108
}
110109

111-
/// Apply circular crop with anti-aliasing for smooth edges.
112-
/// The circle/ellipse is centered within the crop bounds and scaled to fill the area.
113110
fn apply_circular_crop(
114111
&self,
115112
image: &mut RgbaImage,
@@ -120,57 +117,39 @@ impl CropFilter {
120117
target_width: u32,
121118
target_height: u32,
122119
) -> Result<()> {
123-
// 1. Extract the rectangular crop region
120+
// 1. Crop the rectangular region first
124121
let cropped = imageops::crop(image, px_left, px_top, px_width, px_height);
125-
let cropped_image = cropped.to_image();
126-
127-
// 2. Resize cropped image to target dimensions (same as rectangle crop)
128-
let resized = resize_rgba_image_contain(cropped_image, target_width, target_height, false)?;
129-
130-
// 3. Create output image
131-
let mut result = RgbaImage::new(target_width, target_height);
132-
133-
// 4. Calculate circle parameters based on TARGET size
134-
let center_x = target_width as f32 / 2.0;
135-
let center_y = target_height as f32 / 2.0;
136-
// For true circle shape, use minimum dimension
137-
let min_radius = (target_width as f32 / 2.0).min(target_height as f32 / 2.0);
138-
let radius_x = min_radius;
139-
let radius_y = min_radius;
140-
141-
// 5. Anti-aliasing edge distance
142-
let aa_edge_distance = 1.0;
143-
144-
// 6. Sample from resized image and apply circular mask
145-
result
146-
.par_enumerate_pixels_mut()
147-
.for_each(|(px, py, pixel)| {
148-
// Get source pixel from resized image (same coordinates)
149-
let src_pixel = resized.get_pixel(px, py);
150-
151-
// Check if inside the circle
152-
let dx = px as f32 - center_x;
153-
let dy = py as f32 - center_y;
154-
let ellipse_dist = (dx * dx) / (radius_x * radius_x) + (dy * dy) / (radius_y * radius_y);
155-
156-
if ellipse_dist <= 1.0 - aa_edge_distance / min_radius {
157-
// Fully inside the circle
158-
*pixel = *src_pixel;
159-
} else if ellipse_dist <= 1.0 + aa_edge_distance / min_radius {
160-
// Anti-aliasing zone
161-
let aa_factor = (1.0 - (ellipse_dist - 1.0) * min_radius / aa_edge_distance)
162-
.clamp(0.0, 1.0);
163-
pixel[0] = src_pixel[0];
164-
pixel[1] = src_pixel[1];
165-
pixel[2] = src_pixel[2];
166-
pixel[3] = ((src_pixel[3] as f32 * aa_factor) as u8).min(src_pixel[3]);
167-
} else {
168-
// Outside the circle - transparent
169-
pixel[3] = 0;
122+
let mut cropped_image = cropped.to_image();
123+
124+
// 2. Calculate circle parameters (use center of the cropped region)
125+
let cx = px_width as f32 / 2.0;
126+
let cy = px_height as f32 / 2.0;
127+
let radius = px_width.min(px_height) as f32 / 2.0;
128+
129+
// 3. Apply circular mask (pixels outside circle become transparent)
130+
for y in 0..px_height {
131+
for x in 0..px_width {
132+
let dx = x as f32 - cx;
133+
let dy = y as f32 - cy;
134+
let dist = (dx * dx + dy * dy).sqrt();
135+
136+
if dist > radius {
137+
// Outside circle: set transparent
138+
let pixel = cropped_image.get_pixel_mut(x, y);
139+
pixel[3] = 0; // alpha = 0
140+
} else if dist > radius - 1.0 {
141+
// Edge: apply anti-aliasing
142+
let alpha = (radius - dist).clamp(0.0, 1.0);
143+
let pixel = cropped_image.get_pixel_mut(x, y);
144+
pixel[3] = (pixel[3] as f32 * alpha) as u8;
170145
}
171-
});
146+
}
147+
}
148+
149+
// 4. Resize to target dimensions
150+
*image = resize_rgba_image_contain(cropped_image, target_width, target_height, false)?;
151+
// *image = cropped_image;
172152

173-
*image = result;
174153
Ok(())
175154
}
176155
}

todo.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
## 问题
2-
- segment 向右拖拽时,segment时长肯发生跳变
2+
- segment 向右拖拽时,segment长度有时会发生跳变。检查有哪些缓存变量没有及时更新,导致segment长度跳变
3+
34
- 焦点获取问题,很多地方或获取程序焦点,导致快捷键无法成功使用
45

56
- 圆形裁剪有问题,现在是椭圆形,不是圆形。宽和高不一致。
67

7-
- 点击tool.slint中转录按钮,跳转到transcribe tab时,还是处于`打开或恢复历史`的页面。这个也要跳过才对
8-
98
## 待验证
109

1110

wayshot/src/logic/transcribe/model.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,13 @@ fn inner_init(ui: &AppWindow) {
115115
let config = config::all().transcribe;
116116
global_store!(ui).set_transcribe_setting(config.into());
117117

118-
let mut transcribe = UITranscribe::default();
119-
transcribe.playing_index = -1;
120-
transcribe.subtitles = ModelRc::new(VecModel::from_slice(&[]));
121-
global_store!(ui).set_transcribe(transcribe);
118+
let current = global_store!(ui).get_transcribe();
119+
if current.file_path.is_empty() {
120+
let mut transcribe = UITranscribe::default();
121+
transcribe.playing_index = -1;
122+
transcribe.subtitles = ModelRc::new(VecModel::from_slice(&[]));
123+
global_store!(ui).set_transcribe(transcribe);
124+
}
122125

123126
let ui_weak = ui.as_weak();
124127
tokio::spawn(async move {

wayshot/src/logic/video_editor/common_type.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ pub struct VideoEditorPreferenceTrackConfig {
8686
#[derivative(Default(value = "true"))]
8787
pub show_thumbnail: bool,
8888
pub show_filename: bool,
89+
90+
#[derivative(Default(value = "1.0"))]
91+
pub audio_track_waveform_amplification: f32,
8992
}
9093

9194
#[derive(Serialize, Deserialize, Debug, Clone, Derivative, SlintFromConvert)]

wayshot/src/logic/video_editor/track.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1150,8 +1150,8 @@ fn video_editor_transcribe_audio(ui: &AppWindow) {
11501150
..Default::default()
11511151
};
11521152

1153-
global_logic!(ui).invoke_switch_tab(UITabIndex::Transcribe);
11541153
global_store!(ui).set_transcribe(entry);
1154+
global_logic!(ui).invoke_switch_tab(UITabIndex::Transcribe);
11551155
global_store!(ui).set_transcribe_audio_player_progress(0.0);
11561156
global_store!(ui).set_transcribe_audio_player_is_playing(false);
11571157
global_logic!(ui).invoke_transcribe_show_setting_dialog();

wayshot/ui/panel/desktop/home.slint

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ export component Home inherits VerticalLayout {
3838
}
3939
}
4040

41-
if Store.current-tab-index == TabIndex.Transcribe: TranscribePanel {
42-
height: parent.height;
43-
44-
init => {
45-
Logic.startup-transcribe-init();
46-
}
47-
}
41+
// if Store.current-tab-index == TabIndex.Transcribe: TranscribePanel {
42+
// height: parent.height;
43+
//
44+
// init => {
45+
// Logic.startup-transcribe-init();
46+
// }
47+
// }
4848

4949
//
5050
// if Store.current-tab-index == TabIndex.ShareScreen: ShareScreenPanel {

wayshot/ui/panel/desktop/video-editor/preference-setting-dialog.slint

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
SettingDetailInnerVbox,
2121
SettingDetailLabel,
2222
SettingDetailSwitch,
23+
Slider,
2324
} from "../../../base/widgets.slint";
2425

2526
component Track inherits SettingDetail {
@@ -55,6 +56,41 @@ component Track inherits SettingDetail {
5556
}
5657
}
5758
}
59+
60+
SettingDetailInnerVbox {
61+
as-hbox := HorizontalLayout {
62+
alignment: start;
63+
spacing: Theme.spacing * 4;
64+
65+
as-dl := SettingDetailLabel {
66+
text: Logic.tr("Audio waveform amplification");
67+
tip: Logic.tr("Adjust the amplitude scale for audio track waveform display");
68+
}
69+
70+
VerticalLayout {
71+
alignment: center;
72+
73+
amplification-slider := Slider {
74+
minimum: 1.0;
75+
maximum: 5.0;
76+
height: Theme.default-font-size / 2;
77+
finished-progress-color: Theme.thirdly-brand-color;
78+
indicator-size: self.has-hover ? self.height * 3 : 0;
79+
value: clamp(cache-config.audio-track-waveform-amplification, self.minimum, self.maximum);
80+
width: root.width - as-hbox.spacing * 2 - as-dl.preferred-width - as-lb.width - Theme.padding * 4;
81+
82+
released(value) => {
83+
cache-config.audio-track-waveform-amplification = value;
84+
}
85+
}
86+
}
87+
88+
as-lb := Label {
89+
text: round(amplification-slider.value * 10) / 10;
90+
width: Theme.default-font-size * 2;
91+
}
92+
}
93+
}
5894
}
5995
}
6096

@@ -119,8 +155,7 @@ component SettingPanle inherits SettingDetail {
119155
}
120156

121157
VerticalLayout {
122-
padding-top: Theme.padding;
123-
padding-left: Theme.padding;
158+
padding: Theme.padding;
124159
spacing: Theme.spacing;
125160

126161
hbox := HorizontalLayout {

0 commit comments

Comments
 (0)