mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-05-06 08:26:45 -03:00
144 lines
4.4 KiB
Python
144 lines
4.4 KiB
Python
import json
|
|
|
|
import piexif
|
|
from PIL import Image, PngImagePlugin
|
|
|
|
from py.utils.exif_utils import ExifUtils
|
|
|
|
|
|
def test_append_recipe_metadata_includes_checkpoint(monkeypatch, tmp_path):
|
|
captured = {}
|
|
|
|
monkeypatch.setattr(
|
|
ExifUtils, "extract_image_metadata", staticmethod(lambda _path: None)
|
|
)
|
|
|
|
def fake_update_image_metadata(image_path, metadata):
|
|
captured["path"] = image_path
|
|
captured["metadata"] = metadata
|
|
return image_path
|
|
|
|
monkeypatch.setattr(
|
|
ExifUtils, "update_image_metadata", staticmethod(fake_update_image_metadata)
|
|
)
|
|
|
|
checkpoint = {
|
|
"type": "checkpoint",
|
|
"modelId": 827184,
|
|
"modelVersionId": 2167369,
|
|
"modelName": "WAI-illustrious-SDXL",
|
|
"modelVersionName": "v15.0",
|
|
"hash": "ABC123",
|
|
"file_name": "WAI-illustrious-SDXL",
|
|
"baseModel": "Illustrious",
|
|
}
|
|
|
|
recipe_data = {
|
|
"title": "Semi-realism",
|
|
"base_model": "Illustrious",
|
|
"loras": [],
|
|
"tags": [],
|
|
"checkpoint": checkpoint,
|
|
}
|
|
|
|
image_path = tmp_path / "image.webp"
|
|
image_path.write_bytes(b"")
|
|
|
|
ExifUtils.append_recipe_metadata(str(image_path), recipe_data)
|
|
|
|
assert captured["path"] == str(image_path)
|
|
assert captured["metadata"].startswith("Recipe metadata: ")
|
|
|
|
payload = json.loads(captured["metadata"].split("Recipe metadata: ", 1)[1])
|
|
|
|
assert payload["checkpoint"] == {
|
|
"type": "checkpoint",
|
|
"modelId": 827184,
|
|
"modelVersionId": 2167369,
|
|
"modelName": "WAI-illustrious-SDXL",
|
|
"modelVersionName": "v15.0",
|
|
"hash": "abc123",
|
|
"file_name": "WAI-illustrious-SDXL",
|
|
"baseModel": "Illustrious",
|
|
}
|
|
assert payload["base_model"] == "Illustrious"
|
|
|
|
|
|
def test_optimize_image_preserves_workflow_when_converting_png_to_webp(tmp_path):
|
|
image_path = tmp_path / "source.png"
|
|
png_info = PngImagePlugin.PngInfo()
|
|
png_info.add_text("parameters", "prompt text\nSteps: 20")
|
|
png_info.add_text("workflow", json.dumps({"nodes": [{"id": 1}]}))
|
|
|
|
Image.new("RGB", (64, 32), color="red").save(image_path, pnginfo=png_info)
|
|
|
|
optimized_data, extension = ExifUtils.optimize_image(
|
|
str(image_path),
|
|
target_width=32,
|
|
format="webp",
|
|
quality=85,
|
|
preserve_metadata=True,
|
|
)
|
|
|
|
optimized_path = tmp_path / f"optimized{extension}"
|
|
optimized_path.write_bytes(optimized_data)
|
|
|
|
exif_dict = piexif.load(str(optimized_path))
|
|
assert (
|
|
exif_dict["0th"][piexif.ImageIFD.ImageDescription].decode("utf-8")
|
|
== 'Workflow:{"nodes": [{"id": 1}]}'
|
|
)
|
|
user_comment = exif_dict["Exif"][piexif.ExifIFD.UserComment]
|
|
assert user_comment.startswith(b"UNICODE\0")
|
|
assert user_comment[8:].decode("utf-16be") == "prompt text\nSteps: 20"
|
|
|
|
|
|
def test_update_image_metadata_preserves_webp_workflow(tmp_path):
|
|
image_path = tmp_path / "recipe.webp"
|
|
exif_dict = {
|
|
"0th": {
|
|
piexif.ImageIFD.ImageDescription: 'Workflow:{"nodes":[{"id":1}]}',
|
|
},
|
|
"Exif": {
|
|
piexif.ExifIFD.UserComment: b"UNICODE\0"
|
|
+ "prompt text".encode("utf-16be")
|
|
},
|
|
}
|
|
Image.new("RGB", (32, 32), color="blue").save(
|
|
image_path, format="WEBP", exif=piexif.dump(exif_dict), quality=85
|
|
)
|
|
|
|
ExifUtils.update_image_metadata(
|
|
str(image_path), 'prompt text\nRecipe metadata: {"title":"recipe"}'
|
|
)
|
|
|
|
updated_exif = piexif.load(str(image_path))
|
|
assert (
|
|
updated_exif["0th"][piexif.ImageIFD.ImageDescription].decode("utf-8")
|
|
== 'Workflow:{"nodes":[{"id":1}]}'
|
|
)
|
|
updated_comment = updated_exif["Exif"][piexif.ExifIFD.UserComment]
|
|
assert (
|
|
updated_comment[8:].decode("utf-16be")
|
|
== 'prompt text\nRecipe metadata: {"title":"recipe"}'
|
|
)
|
|
|
|
|
|
def test_update_image_metadata_preserves_png_workflow(tmp_path):
|
|
image_path = tmp_path / "recipe.png"
|
|
png_info = PngImagePlugin.PngInfo()
|
|
png_info.add_text("parameters", "prompt text")
|
|
png_info.add_text("workflow", '{"nodes":[{"id":1}]}')
|
|
Image.new("RGB", (32, 32), color="green").save(image_path, pnginfo=png_info)
|
|
|
|
ExifUtils.update_image_metadata(
|
|
str(image_path), 'prompt text\nRecipe metadata: {"title":"recipe"}'
|
|
)
|
|
|
|
with Image.open(image_path) as img:
|
|
assert img.info["workflow"] == '{"nodes":[{"id":1}]}'
|
|
assert (
|
|
img.info["parameters"]
|
|
== 'prompt text\nRecipe metadata: {"title":"recipe"}'
|
|
)
|