# save_cover.py # # Copyright 2022-2023 kramo # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # SPDX-License-Identifier: GPL-3.0-or-later from pathlib import Path from shutil import copyfile from gi.repository import Gdk, Gio, GLib from PIL import Image, ImageSequence, UnidentifiedImageError from src import shared def resize_cover(cover_path=None, pixbuf=None): if not cover_path and not pixbuf: return None if pixbuf: cover_path = Path(Gio.File.new_tmp("XXXXXX.tiff")[0].get_path()) pixbuf.savev(str(cover_path), "tiff", ["compression"], ["1"]) try: with Image.open(cover_path) as image: if getattr(image, "is_animated", False): frames = tuple( frame.resize((200, 300)) for frame in ImageSequence.Iterator(image) ) tmp_path = Path(Gio.File.new_tmp("XXXXXX.gif")[0].get_path()) frames[0].save( tmp_path, save_all=True, append_images=frames[1:], ) else: # This might not be necessary in the future # https://github.com/python-pillow/Pillow/issues/2663 if image.mode not in ("RGB", "RGBA"): image = image.convert("RGBA") tmp_path = Path(Gio.File.new_tmp("XXXXXX.tiff")[0].get_path()) image.resize(shared.image_size).save( tmp_path, compression="tiff_adobe_deflate" if shared.schema.get_boolean("high-quality-images") else "webp", ) except UnidentifiedImageError: try: Gdk.Texture.new_from_filename(str(cover_path)).save_to_tiff( tmp_path := Gio.File.new_tmp("XXXXXX.tiff")[0].get_path() ) return resize_cover(tmp_path) except GLib.GError: return None return tmp_path def save_cover(game_id, cover_path): shared.covers_dir.mkdir(parents=True, exist_ok=True) animated_path = shared.covers_dir / f"{game_id}.gif" static_path = shared.covers_dir / f"{game_id}.tiff" # Remove previous covers animated_path.unlink(missing_ok=True) static_path.unlink(missing_ok=True) if not cover_path: return copyfile( cover_path, animated_path if cover_path.suffix == ".gif" else static_path, ) if game_id in shared.win.game_covers: shared.win.game_covers[game_id].new_cover( animated_path if cover_path.suffix == ".gif" else static_path )