From 17d451eaa7c143fd7a5a3fa41876ac5ad6039f73 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Wed, 4 Oct 2023 15:26:32 +1100 Subject: [PATCH] feat(images): add `png_compress_level` config The compress_level setting of PIL.Image.save(), used for PNG encoding. All settings are lossless. 0 = fastest, largest filesize, 9 = slowest, smallest filesize Closes #4786 --- invokeai/app/services/config/invokeai_config.py | 1 + invokeai/app/services/image_file_storage.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/invokeai/app/services/config/invokeai_config.py b/invokeai/app/services/config/invokeai_config.py index 8ea703f39a..d8b598815d 100644 --- a/invokeai/app/services/config/invokeai_config.py +++ b/invokeai/app/services/config/invokeai_config.py @@ -255,6 +255,7 @@ class InvokeAIAppConfig(InvokeAISettings): attention_slice_size: Literal["auto", "balanced", "max", 1, 2, 3, 4, 5, 6, 7, 8] = Field(default="auto", description='Slice size, valid when attention_type=="sliced"', category="Generation", ) force_tiled_decode : bool = Field(default=False, description="Whether to enable tiled VAE decode (reduces memory consumption with some performance penalty)", category="Generation",) force_tiled_decode: bool = Field(default=False, description="Whether to enable tiled VAE decode (reduces memory consumption with some performance penalty)", category="Generation",) + png_compress_level : int = Field(default=6, description="The compress_level setting of PIL.Image.save(), used for PNG encoding. All settings are lossless. 0 = fastest, largest filesize, 9 = slowest, smallest filesize", category="Generation", ) # QUEUE max_queue_size : int = Field(default=10000, gt=0, description="Maximum number of items in the session queue", category="Queue", ) diff --git a/invokeai/app/services/image_file_storage.py b/invokeai/app/services/image_file_storage.py index 75a5888175..cddc32c6d2 100644 --- a/invokeai/app/services/image_file_storage.py +++ b/invokeai/app/services/image_file_storage.py @@ -8,6 +8,7 @@ from typing import Dict, Optional, Union from PIL import Image, PngImagePlugin from PIL.Image import Image as PILImageType from send2trash import send2trash +from invokeai.app.services.config.invokeai_config import InvokeAIAppConfig from invokeai.app.util.thumbnails import get_thumbnail_name, make_thumbnail @@ -79,6 +80,7 @@ class DiskImageFileStorage(ImageFileStorageBase): __cache_ids: Queue # TODO: this is an incredibly naive cache __cache: Dict[Path, PILImageType] __max_cache_size: int + __compress_level: int def __init__(self, output_folder: Union[str, Path]): self.__cache = dict() @@ -87,7 +89,7 @@ class DiskImageFileStorage(ImageFileStorageBase): self.__output_folder: Path = output_folder if isinstance(output_folder, Path) else Path(output_folder) self.__thumbnails_folder = self.__output_folder / "thumbnails" - + self.__compress_level = InvokeAIAppConfig.get_config().png_compress_level # Validate required output folders at launch self.__validate_storage_folders() @@ -134,7 +136,7 @@ class DiskImageFileStorage(ImageFileStorageBase): if original_workflow is not None: pnginfo.add_text("invokeai_workflow", original_workflow) - image.save(image_path, "PNG", pnginfo=pnginfo) + image.save(image_path, "PNG", pnginfo=pnginfo, compress_level=self.__compress_level) thumbnail_name = get_thumbnail_name(image_name) thumbnail_path = self.get_path(thumbnail_name, thumbnail=True)