diff --git a/modules/images.py b/modules/images.py
index 03591c91..68cd6fd4 100644
--- a/modules/images.py
+++ b/modules/images.py
@@ -2,29 +2,31 @@ from __future__ import annotations
import datetime
import functools
-import pytz
+import hashlib
import io
+import json
import math
import os
+import re
+import string
import subprocess
from collections import namedtuple
-import re
import numpy as np
import piexif
import piexif.helper
-from PIL import Image, ImageFont, ImageDraw, ImageColor, PngImagePlugin, ImageOps
-from pillow_heif import AvifImagePlugin, HeifImagePlugin # noqa: F401
-import string
-import json
-import hashlib
+import pillow_jxl # noqa
+import pytz
+from PIL import Image, ImageColor, ImageDraw, ImageFont, ImageOps, PngImagePlugin
+from pillow_heif import register_heif_opener
-from modules import sd_samplers, shared, script_callbacks, errors
+from modules import errors, script_callbacks, sd_samplers, shared
from modules.paths_internal import roboto_ttf_file
from modules.shared import opts
-LANCZOS = getattr(Image, "Resampling", Image).LANCZOS
-NEAREST = getattr(Image, "Resampling", Image).NEAREST
+register_heif_opener()
+LANCZOS = Image.Resampling.LANCZOS
+NEAREST = Image.Resampling.NEAREST
def get_font(fontsize: int):
@@ -567,7 +569,7 @@ def get_next_sequence_number(path, basename):
return result + 1
-def save_image_with_geninfo(image, geninfo, filename, extension=None, existing_pnginfo=None, pnginfo_section_name='parameters'):
+def save_image_with_geninfo(image, geninfo, filename, extension=None, existing_pnginfo=None, pnginfo_section_name="parameters"):
"""
Saves image to filename, including geninfo as text information for generation info.
For PNG images, geninfo is added to existing pnginfo dictionary using the pnginfo_section_name argument as key.
@@ -579,12 +581,10 @@ def save_image_with_geninfo(image, geninfo, filename, extension=None, existing_p
image_format = Image.registered_extensions()[extension]
- if extension.lower() == '.png':
+ if extension.lower() == ".png":
existing_pnginfo = existing_pnginfo or {}
if opts.enable_pnginfo:
existing_pnginfo[pnginfo_section_name] = geninfo
-
- if opts.enable_pnginfo:
pnginfo_data = PngImagePlugin.PngInfo()
for k, v in (existing_pnginfo or {}).items():
pnginfo_data.add_text(k, str(v))
@@ -594,32 +594,32 @@ def save_image_with_geninfo(image, geninfo, filename, extension=None, existing_p
image.save(filename, format=image_format, quality=opts.jpeg_quality, pnginfo=pnginfo_data)
elif extension.lower() in (".jpg", ".jpeg", ".webp"):
- if image.mode == 'RGBA':
+ if image.mode == "RGBA":
image = image.convert("RGB")
- elif image.mode == 'I;16':
+ elif image.mode == "I;16":
image = image.point(lambda p: p * 0.0038910505836576).convert("RGB" if extension.lower() == ".webp" else "L")
image.save(filename, format=image_format, quality=opts.jpeg_quality, lossless=opts.webp_lossless)
if opts.enable_pnginfo and geninfo is not None:
- exif_bytes = piexif.dump({
- "Exif": {
- piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(geninfo or "", encoding="unicode")
- },
- })
+ exif_bytes = piexif.dump(
+ {
+ "Exif": {piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(geninfo or "", encoding="unicode")},
+ }
+ )
piexif.insert(exif_bytes, filename)
- elif extension.lower() == '.avif':
+ elif extension.lower() in (".avif", ".jxl"):
if opts.enable_pnginfo and geninfo is not None:
- exif_bytes = piexif.dump({
- "Exif": {
- piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(geninfo or "", encoding="unicode")
- },
- })
+ exif_bytes = piexif.dump(
+ {
+ "Exif": {piexif.ExifIFD.UserComment: piexif.helper.UserComment.dump(geninfo or "", encoding="unicode")},
+ }
+ )
else:
exif_bytes = None
- image.save(filename,format=image_format, quality=opts.jpeg_quality, exif=exif_bytes)
+ image.save(filename, format=image_format, quality=opts.jpeg_quality, exif=exif_bytes)
elif extension.lower() == ".gif":
image.save(filename, format=image_format, comment=geninfo)
else:
diff --git a/modules/shared_options.py b/modules/shared_options.py
index b5206ee9..4c52ad5e 100644
--- a/modules/shared_options.py
+++ b/modules/shared_options.py
@@ -41,12 +41,12 @@ options_templates.update(
("saving-images", "Saving Images/Grids", "saving"),
{
"samples_save": OptionInfo(True, "Automatically save every generated image").info('if disabled, images will needed to be manually saved via the "Save Image" button'),
- "samples_format": OptionInfo("png", "Image Format", gr.Dropdown, {"choices": ("jpg", "jpeg", "png", "webp", "avif", "heif")}).info('"webp" is recommended if supported'),
+ "samples_format": OptionInfo("png", "Image Format", gr.Dropdown, {"choices": ("jpg", "jpeg", "png", "webp", "jxl", "avif", "heif")}).info('"webp" is recommended if supported').info("some format may not be shown in the Gallery"),
"samples_filename_pattern": OptionInfo("", "Filename pattern for saving images", component_args=hide_dirs).link("wiki", "https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Custom-Images-Filename-Name-and-Subdirectory"),
"save_images_add_number": OptionInfo(True, "Append an ascending number to the filename", component_args=hide_dirs),
"save_images_replace_action": OptionInfo("Override", "Behavior when saving image to an existing filename", gr.Radio, {"choices": ("Override", "Number Suffix"), **hide_dirs}),
"grid_save": OptionInfo(True, "Automatically save every generated image grid").info("e.g. for X/Y/Z Plot"),
- "grid_format": OptionInfo("jpg", "Image Format for Grids", gr.Dropdown, {"choices": ("jpg", "jpeg", "png", "webp", "avif", "heif")}),
+ "grid_format": OptionInfo("jpg", "Image Format for Grids", gr.Dropdown, {"choices": ("jpg", "jpeg", "png", "webp", "jxl", "avif", "heif")}),
"grid_extended_filename": OptionInfo(False, "Append extended info (seed, prompt, etc.) to the filename when saving grids"),
"grid_only_if_multiple": OptionInfo(True, "Do not save grids that contain only one image"),
"grid_prevent_empty_spots": OptionInfo(True, "Prevent empty gaps within a grid"),
diff --git a/requirements.txt b/requirements.txt
index d9d1aa94..1d95a42d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,35 +1,36 @@
-GitPython==3.1.44
-Pillow==11.3.0
+GitPython==3.1.45
+Pillow==12.0.0
accelerate==1.10.1
clean-fid==0.1.35
-diffusers==0.35.1
+diffusers==0.35.2
diskcache==5.6.3
einops==0.8.1
facexlib==0.3.0
fastapi==0.112.4
httpcore==0.15.0
httpx==0.24.1
-huggingface-hub==0.34.1
+huggingface-hub==0.34.6
inflection==0.5.1
joblib==1.5.1
jsonmerge==1.8.0
kornia==0.6.7
lark==1.2.2
-lightning==2.5.1
+lightning==2.5.6
loadimg==0.1.2
-numpy==1.26.4
+numpy==2.3.5
omegaconf==2.2.3
open-clip-torch==2.32.0
opencv-python==4.8.1.78
peft==0.17.1
piexif==1.1.3
-pillow-heif==0.22.0
-protobuf==4.25.7
+pillow-heif==1.1.1
+pillow-jxl-plugin==1.3.6
+protobuf==4.25.8
psutil==5.9.8
pydantic-core==2.23.4
pydantic==2.9.2
resize-right==0.0.2
-safetensors==0.6.2
+safetensors==0.7.0
scikit-image==0.25.2
setuptools==69.5.1
spandrel-extra-arches==0.2.0