feat: add GIF files support as wallpaper (#88)

* feat: add GIF files support as wallpaper (not animated tho)

* tweak: simplifying variable use

* fix: git is good but damn it's annoying

* fix

---------

Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
This commit is contained in:
Unrectified
2026-02-20 14:17:16 +01:00
committed by GitHub
parent 25c473c18e
commit 8ce97ea3f5
+28 -4
View File
@@ -24,7 +24,7 @@ from caelestia.utils.theme import apply_colours
def is_valid_image(path: Path) -> bool: def is_valid_image(path: Path) -> bool:
return path.is_file() and path.suffix in [".jpg", ".jpeg", ".png", ".webp", ".tif", ".tiff"] return path.is_file() and path.suffix in [".jpg", ".jpeg", ".png", ".webp", ".tif", ".tiff", ".gif"]
def check_wall(wall: Path, filter_size: tuple[int, int], threshold: float) -> bool: def check_wall(wall: Path, filter_size: tuple[int, int], threshold: float) -> bool:
@@ -99,6 +99,9 @@ def get_colours_for_wall(wall: Path | str, no_smart: bool) -> None:
scheme = get_scheme() scheme = get_scheme()
cache = wallpapers_cache_dir / compute_hash(wall) cache = wallpapers_cache_dir / compute_hash(wall)
if wall.suffix.lower() == ".gif"
wall = convert_gif(wall)
name = "dynamic" name = "dynamic"
if not no_smart: if not no_smart:
@@ -121,6 +124,24 @@ def get_colours_for_wall(wall: Path | str, no_smart: bool) -> None:
"colours": get_colours_for_image(get_thumb(wall, cache), scheme), "colours": get_colours_for_image(get_thumb(wall, cache), scheme),
} }
def convert_gif(wall: Path) -> Path:
cache = wallpapers_cache_dir / compute_hash(wall)
output_path = cache / "first_frame.png"
if not output_path.exists():
output_path.parent.mkdir(parents=True, exist_ok=True)
with Image.open(wall) as img:
try:
img.seek(0)
except EOFError:
pass
img = img.convert("RGB")
img.save(output_path, "PNG")
return output_path
def set_wallpaper(wall: Path | str, no_smart: bool) -> None: def set_wallpaper(wall: Path | str, no_smart: bool) -> None:
# Make path absolute # Make path absolute
@@ -129,6 +150,9 @@ def set_wallpaper(wall: Path | str, no_smart: bool) -> None:
if not is_valid_image(wall): if not is_valid_image(wall):
raise ValueError(f'"{wall}" is not a valid image') raise ValueError(f'"{wall}" is not a valid image')
# Use gif's 1st frame for thumb only
wall_cache = convert_gif(wall) if wall.suffix.lower() == ".gif" else wall
# Update files # Update files
wallpaper_path_path.parent.mkdir(parents=True, exist_ok=True) wallpaper_path_path.parent.mkdir(parents=True, exist_ok=True)
wallpaper_path_path.write_text(str(wall)) wallpaper_path_path.write_text(str(wall))
@@ -136,10 +160,10 @@ def set_wallpaper(wall: Path | str, no_smart: bool) -> None:
wallpaper_link_path.unlink(missing_ok=True) wallpaper_link_path.unlink(missing_ok=True)
wallpaper_link_path.symlink_to(wall) wallpaper_link_path.symlink_to(wall)
cache = wallpapers_cache_dir / compute_hash(wall) cache = wallpapers_cache_dir / compute_hash(wall_cache)
# Generate thumbnail or get from cache # Generate thumbnail or get from cache
thumb = get_thumb(wall, cache) thumb = get_thumb(wall_cache, cache)
wallpaper_thumbnail_path.parent.mkdir(parents=True, exist_ok=True) wallpaper_thumbnail_path.parent.mkdir(parents=True, exist_ok=True)
wallpaper_thumbnail_path.unlink(missing_ok=True) wallpaper_thumbnail_path.unlink(missing_ok=True)
wallpaper_thumbnail_path.symlink_to(thumb) wallpaper_thumbnail_path.symlink_to(thumb)
@@ -148,7 +172,7 @@ def set_wallpaper(wall: Path | str, no_smart: bool) -> None:
# Change mode and variant based on wallpaper colour # Change mode and variant based on wallpaper colour
if scheme.name == "dynamic" and not no_smart: if scheme.name == "dynamic" and not no_smart:
smart_opts = get_smart_opts(wall, cache) smart_opts = get_smart_opts(wall_cache, cache)
scheme.mode = smart_opts["mode"] scheme.mode = smart_opts["mode"]
scheme.variant = smart_opts["variant"] scheme.variant = smart_opts["variant"]