Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/desktop-gpui/locales/de.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2183,7 +2183,8 @@ noise = "Rauschen"
to = "Bis"

[editor.sidebar.image]
prompt = "Klicken Sie zum Auswählen oder ziehen Sie ein Bild hierher"
file_type = "Bild oder Video"
prompt = "Klicken Sie zum Auswählen oder ziehen Sie ein Bild, GIF oder Video hierher"

[editor.sidebar.layout]
background_blur = "Hintergrundunschärfe"
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop-gpui/locales/en.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2185,7 +2185,8 @@ noise = "Noise"
to = "To"

[editor.sidebar.image]
prompt = "Click to select or drag and drop image"
file_type = { text = "Image or video", context = "File type name in the Linux file chooser for editor backgrounds, which accept images, GIFs and videos." }
prompt = "Click to select or drag and drop an image, GIF or video"

[editor.sidebar.layout]
background_blur = "Background Blur"
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop-gpui/locales/es.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2183,7 +2183,8 @@ noise = "Ruido"
to = "Hasta"

[editor.sidebar.image]
prompt = "Haz clic para elegir o arrastra y suelta una imagen"
file_type = "Imagen o vídeo"
prompt = "Haz clic para elegir o arrastra y suelta una imagen, un GIF o un vídeo"

[editor.sidebar.layout]
background_blur = "Desenfoque del fondo"
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop-gpui/locales/fr.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2183,7 +2183,8 @@ noise = "Bruit"
to = "À"

[editor.sidebar.image]
prompt = "Cliquez pour choisir ou glissez-déposez une image"
file_type = "Image ou vidéo"
prompt = "Cliquez pour choisir ou glissez-déposez une image, un GIF ou une vidéo"

[editor.sidebar.layout]
background_blur = "Flou de l'arrière-plan"
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop-gpui/locales/hi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2183,7 +2183,8 @@ noise = "नॉइज़"
to = "तक"

[editor.sidebar.image]
prompt = "चुनने के लिए क्लिक करें या इमेज ड्रैग करके छोड़ें"
file_type = "इमेज या वीडियो"
prompt = "चुनने के लिए क्लिक करें या इमेज, GIF या वीडियो ड्रैग करके छोड़ें"

[editor.sidebar.layout]
background_blur = "बैकग्राउंड ब्लर"
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop-gpui/locales/ja.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2183,7 +2183,8 @@ noise = "ノイズ"
to = "終了"

[editor.sidebar.image]
prompt = "クリックして選択するか、画像をドラッグ&ドロップ"
file_type = "画像または動画"
prompt = "クリックして選択するか、画像・GIF・動画をドラッグ&ドロップ"

[editor.sidebar.layout]
background_blur = "背景のぼかし"
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop-gpui/locales/zh-CN.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2183,7 +2183,8 @@ noise = "噪点"
to = "结束"

[editor.sidebar.image]
prompt = "点击选择或拖放图片"
file_type = "图片或视频"
prompt = "点击选择或拖放图片、GIF 或视频"

[editor.sidebar.layout]
background_blur = "背景模糊"
Expand Down
36 changes: 31 additions & 5 deletions apps/desktop-gpui/src/editor_sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@ pub const DEFAULT_BACKGROUND_ROUNDING: f64 = 7.5;
pub const DEFAULT_NOISE_SCALE: f32 = 3.;
/// `BACKGROUND_IMAGE_EXTENSIONS` (`:250-257`).
pub const BACKGROUND_IMAGE_EXTENSIONS: [&str; 6] = ["jpg", "jpeg", "png", "gif", "webp", "bmp"];
/// What the recording editor's image pane accepts: the images above plus
/// videos, which loop behind the recording.
pub const BACKGROUND_MEDIA_EXTENSIONS: [&str; 10] = [
"jpg", "jpeg", "png", "gif", "webp", "bmp", "mp4", "mov", "m4v", "webm",
];
/// `CURRENT_DESKTOP_BACKGROUND_BASENAME` (`:350`, and `recording.rs:91`).
pub const CURRENT_DESKTOP_BACKGROUND_BASENAME: &str = "current-desktop-background";
/// `recording.rs:92-93`.
Expand Down Expand Up @@ -1968,6 +1973,10 @@ impl EditorWindow {
/// side. The same rule as `library::decode_thumbnail`: the atlas would
/// otherwise hold a multi-megapixel original per tile.
fn decode_scaled_rgba(path: &Path, max: u32) -> Option<image::RgbaImage> {
if is_background_video(path) {
let (pixels, width, height) = cap_rendering::video_background_poster(path, max)?;
return image::RgbaImage::from_raw(width, height, pixels);
}
let bytes = std::fs::read(path).ok()?;
let format = image::guess_format(&bytes).ok()?;
let (decoded, width, height) = if format == image::ImageFormat::Jpeg {
Expand Down Expand Up @@ -2005,6 +2014,12 @@ fn decode_scaled_rgba(path: &Path, max: u32) -> Option<image::RgbaImage> {
})
}

/// GIFs decode as images here; only the first frame is needed for a tile.
fn is_background_video(path: &Path) -> bool {
let path = path.to_string_lossy();
cap_rendering::is_video_background(&path) && !path.to_lowercase().ends_with(".gif")
}

fn decode_jpeg_thumbnail(bytes: &[u8], max: u32) -> Option<(image::DynamicImage, u32, u32)> {
crate::jpeg_thumbnail::decode_jpeg_thumbnail(bytes, |_, _| (max, max))
}
Expand Down Expand Up @@ -2434,16 +2449,16 @@ impl EditorWindow {
#[cfg(target_os = "linux")]
let picked = crate::platform::open_file_panel_async(
&[(
tr::editor::sidebar::source::image(),
&BACKGROUND_IMAGE_EXTENSIONS[..],
tr::editor::sidebar::image::file_type(),
&BACKGROUND_MEDIA_EXTENSIONS[..],
)],
None,
cx,
)
.await;
#[cfg(not(target_os = "linux"))]
let picked = cx
.update(|_, _| crate::platform::open_image_panel(&BACKGROUND_IMAGE_EXTENSIONS))
.update(|_, _| crate::platform::open_image_panel(&BACKGROUND_MEDIA_EXTENSIONS))
.ok()
.flatten();

Expand All @@ -2456,9 +2471,9 @@ impl EditorWindow {
.and_then(|extension| extension.to_str())
.map(str::to_lowercase);
if !extension.is_some_and(|extension| {
BACKGROUND_IMAGE_EXTENSIONS.contains(&extension.as_str())
BACKGROUND_MEDIA_EXTENSIONS.contains(&extension.as_str())
}) {
return Err("Invalid image file type".to_string());
return Err("Invalid image or video file type".to_string());
}
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
Expand Down Expand Up @@ -4295,6 +4310,17 @@ mod tests {
assert!(pixel[2].abs_diff(200) <= 3);
}

#[test]
fn videos_get_a_poster_while_gifs_decode_as_images() {
assert!(is_background_video(Path::new("/bg/loop.mp4")));
assert!(is_background_video(Path::new("/bg/loop.MOV")));
assert!(!is_background_video(Path::new("/bg/loop.gif")));
assert!(!is_background_video(Path::new("/bg/still.png")));
for extension in BACKGROUND_IMAGE_EXTENSIONS {
assert!(BACKGROUND_MEDIA_EXTENSIONS.contains(&extension));
}
}

#[test]
fn built_in_wallpapers_reject_unknown_and_traversal_identifiers() {
assert_eq!(wallpaper_path("unknown/wallpaper"), None);
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop-gpui/src/i18n/editor_panels_surface_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,9 +504,10 @@ fn editor_panels_match_the_literals_they_replaced() {
"Use the wallpaper from your desktop",
),
(tr::editor::sidebar::desktop::reimport(), "Re-import"),
(tr::editor::sidebar::image::file_type(), "Image or video"),
(
tr::editor::sidebar::image::prompt(),
"Click to select or drag and drop image",
"Click to select or drag and drop an image, GIF or video",
),
(tr::editor::sidebar::gradient::from(), "From"),
(tr::editor::sidebar::gradient::to(), "To"),
Expand Down
21 changes: 11 additions & 10 deletions crates/rendering/src/decoder/frame_converter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,22 @@ impl FrameConverter {

/// swscale converts YUV with BT.601 unless told otherwise: switch the source
/// matrix to BT.709 and keep the ranges and adjustments it chose.
fn use_bt709_source(context: &mut software::scaling::Context) {
pub(crate) fn use_bt709_source(context: &mut software::scaling::Context) {
unsafe { use_bt709_source_raw(context.as_mut_ptr()) }
}

/// [`use_bt709_source`] for a context created through the raw swscale API.
///
/// # Safety
/// `context` must point to an initialised `SwsContext`.
pub(crate) unsafe fn use_bt709_source_raw(context: *mut ffmpeg::ffi::SwsContext) {
unsafe {
let mut inv_table = std::ptr::null_mut();
let mut table = std::ptr::null_mut();
let (mut src_range, mut dst_range) = (0, 0);
let (mut brightness, mut contrast, mut saturation) = (0, 0, 0);
if ffmpeg::ffi::sws_getColorspaceDetails(
context.as_mut_ptr(),
context,
&mut inv_table,
&mut src_range,
&mut table,
Expand All @@ -206,14 +214,7 @@ fn use_bt709_source(context: &mut software::scaling::Context) {
}
let bt709 = ffmpeg::ffi::sws_getCoefficients(ffmpeg::ffi::SWS_CS_ITU709);
ffmpeg::ffi::sws_setColorspaceDetails(
context.as_mut_ptr(),
bt709,
src_range,
table,
dst_range,
brightness,
contrast,
saturation,
context, bt709, src_range, table, dst_range, brightness, contrast, saturation,
);
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/rendering/src/decoder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use std::sync::{
mod avassetreader;
mod ffmpeg;
mod frame_converter;
pub(crate) use frame_converter::use_bt709_source_raw;
#[cfg(target_os = "windows")]
mod media_foundation;
#[cfg(test)]
Expand Down
Loading
Loading