1
0
Fork 0

A crappy wallpaper sorter by aspect ratio

This commit is contained in:
Luca Beltrame 2022-06-05 21:42:21 +02:00
parent 9717b51778
commit 029201da1e
Signed by: einar
GPG key ID: 4707F46E9EC72DEC

133
misc/wallpaper_sorter.py Executable file
View file

@ -0,0 +1,133 @@
#!/usr/bin/python3
import argparse
from typing import List
from pathlib import Path
from PIL import Image
SOURCES = ["konachan", "wallhaven", "yandere", "moe_imouto"]
RATIO_PATHS = ("4_3", "16_9", "16_10", "vertical")
def get_wallpaper_source(filename: Path) -> str:
if filename.name.startswith("Konachan.com"):
return "konachan"
elif filename.name.startswith("wallhaven"):
return "wallhaven"
elif filename.name.startswith("yande.re"):
return "yandere"
elif filename.name.startswith("moe"):
return "moe_imouto"
else:
return ""
def ratio_and_resolution(filename: Path, guess_source=True) -> Path:
img = Image.open(filename)
resolution = f"{img.width}x{img.height}"
ratio = img.width / img.height
check_ratios = [("4:3", 4/3), ("16:9", 16/9), ("16:10", 16/10)]
# Calculate the distance from each ratio of the image in question
distances = {label: (ratio-ref)**2 for label, ref in check_ratios}
# Calculate the ratio with the minimum distance
min_dist = min(distances, key=distances.get).replace(":", "_")
if guess_source:
source = get_wallpaper_source(filename)
else:
source = ""
new_filename = "_".join((filename.stem, resolution)) + filename.suffix
# Special case phone wallpapers for now
if img.height > img.width:
min_dist = "vertical"
if source:
final_name = Path(min_dist) / source / new_filename
else:
final_name = Path(min_dist) / new_filename
return final_name
def organize_images(files: List[Path],
destination_path: Path, dry_run=True) -> None:
for ratio_set in RATIO_PATHS:
if not dry_run:
(destination_path / ratio_set).mkdir(exist_ok=True)
for source in SOURCES:
(destination_path / ratio_set / source).mkdir(exist_ok=True)
for element in files:
new_name = destination_path / ratio_and_resolution(element)
if dry_run:
print(f"{element} -> {new_name}")
continue
if not new_name.exists():
element.rename(new_name)
# new_name.symlink_to(element)
def get_image_list(source: Path) -> List[Path]:
candidates = list()
for element in source.glob("**/*"):
if element.is_dir():
continue
# Exclude already processed directories
if any(part in RATIO_PATHS for part in element.parts):
continue
if element.suffix in (".png", ".jpg", ".webp", ".jpeg", ".bmp"):
candidates.append(element)
return candidates
def cleanup(destination: Path) -> None:
for element in RATIO_PATHS:
full_path = destination / element
for source in SOURCES:
source_path = full_path / source
if not any(source_path.iterdir()):
source_path.rmdir()
if not any(full_path.iterdir()):
full_path.rmdir()
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--dry-run", action="store_true",
help="Only simulate")
parser.add_argument("source", help="Source wallpaper directory")
parser.add_argument("destination", help="Destination path to move data to")
options = parser.parse_args()
source = Path(options.source).absolute()
destination = Path(options.destination).absolute()
images = get_image_list(source)
organize_images(images, destination, options.dry_run)
cleanup(destination)
if __name__ == "__main__":
main()