fix: update version to 1.1.3 and add make_civitai_safe_text function for punctuation normalization
This commit is contained in:
+2
-2
@@ -3,7 +3,7 @@ Compatibility shim for MetaHub Save Node metadata helpers.
|
||||
|
||||
The implementation is kept in metadata_utils_impl.py; this module exposes the
|
||||
same public API expected by the save nodes while pinning the published node
|
||||
version to 1.1.2.
|
||||
version to 1.1.3.
|
||||
"""
|
||||
|
||||
try:
|
||||
@@ -11,7 +11,7 @@ try:
|
||||
except ImportError:
|
||||
import metadata_utils_impl as _impl
|
||||
|
||||
METAHUB_SAVE_NODE_VERSION = "1.1.2"
|
||||
METAHUB_SAVE_NODE_VERSION = "1.1.3"
|
||||
_impl.METAHUB_SAVE_NODE_VERSION = METAHUB_SAVE_NODE_VERSION
|
||||
|
||||
for _name in dir(_impl):
|
||||
|
||||
+29
-6
@@ -14,7 +14,7 @@ from xml.sax.saxutils import escape as xml_escape
|
||||
import numpy as np
|
||||
from PIL import Image, PngImagePlugin
|
||||
|
||||
METAHUB_SAVE_NODE_VERSION = "1.0.9"
|
||||
METAHUB_SAVE_NODE_VERSION = "1.1.3"
|
||||
|
||||
try:
|
||||
import piexif
|
||||
@@ -315,6 +315,28 @@ def collect_version_info() -> Dict[str, Optional[str]]:
|
||||
# METADATA FORMATTING
|
||||
# ============================================================================
|
||||
|
||||
def make_civitai_safe_text(value: str) -> str:
|
||||
"""
|
||||
Normalizes common smart punctuation for legacy A1111/Civitai text readers.
|
||||
"""
|
||||
if value is None:
|
||||
return ""
|
||||
replacements = {
|
||||
"\u2018": "'",
|
||||
"\u2019": "'",
|
||||
"\u201c": '"',
|
||||
"\u201d": '"',
|
||||
"\u2013": "-",
|
||||
"\u2014": "-",
|
||||
"\u2026": "...",
|
||||
"\u00a0": " ",
|
||||
}
|
||||
text = str(value)
|
||||
for source, replacement in replacements.items():
|
||||
text = text.replace(source, replacement)
|
||||
return text
|
||||
|
||||
|
||||
def build_a1111_metadata(params: dict) -> str:
|
||||
"""
|
||||
Builds A1111/Civitai compatible metadata string for tEXt chunk.
|
||||
@@ -836,7 +858,7 @@ def save_png_with_metadata(image: Image.Image, image_path: str, a1111_metadata:
|
||||
"""
|
||||
try:
|
||||
png_info = PngImagePlugin.PngInfo()
|
||||
png_info.add_text("parameters", a1111_metadata or "")
|
||||
png_info.add_text("parameters", make_civitai_safe_text(a1111_metadata))
|
||||
imh_json = json.dumps(imh_metadata or {}, ensure_ascii=False)
|
||||
png_info.add_itxt("imagemetahub_data", imh_json)
|
||||
workflow_text = _serialize_metadata_json_ascii(imh_metadata.get("workflow"))
|
||||
@@ -861,9 +883,10 @@ def _build_exif_bytes(a1111_metadata: str, imh_metadata: dict) -> Optional[bytes
|
||||
imh_json = json.dumps(imh_metadata or {}, ensure_ascii=False)
|
||||
if imh_json:
|
||||
exif_dict["0th"][piexif.ImageIFD.ImageDescription] = imh_json.encode("utf-8", errors="replace")
|
||||
if a1111_metadata:
|
||||
civitai_metadata = make_civitai_safe_text(a1111_metadata)
|
||||
if civitai_metadata:
|
||||
exif_dict["Exif"][piexif.ExifIFD.UserComment] = piexif_helper.UserComment.dump(
|
||||
a1111_metadata, encoding="unicode"
|
||||
civitai_metadata, encoding="unicode"
|
||||
)
|
||||
return piexif.dump(exif_dict)
|
||||
except Exception:
|
||||
@@ -889,7 +912,7 @@ def save_jpeg_with_metadata(
|
||||
if exif_bytes:
|
||||
save_kwargs["exif"] = exif_bytes
|
||||
elif a1111_metadata:
|
||||
save_kwargs["comment"] = a1111_metadata.encode("utf-8", errors="replace")
|
||||
save_kwargs["comment"] = make_civitai_safe_text(a1111_metadata).encode("utf-8", errors="replace")
|
||||
if xmp_bytes:
|
||||
save_kwargs["xmp"] = xmp_bytes
|
||||
try:
|
||||
@@ -922,7 +945,7 @@ def save_webp_with_metadata(
|
||||
if exif_bytes:
|
||||
save_kwargs["exif"] = exif_bytes
|
||||
elif a1111_metadata:
|
||||
save_kwargs["comment"] = a1111_metadata
|
||||
save_kwargs["comment"] = make_civitai_safe_text(a1111_metadata)
|
||||
if xmp_bytes:
|
||||
save_kwargs["xmp"] = xmp_bytes
|
||||
try:
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "imagemetahub-comfyui-save"
|
||||
description = "Official companion node for Image MetaHub. Saves A1111/Civitai-compatible parameters plus extended Image MetaHub metadata (workflow JSON, SHA256 model hashes, VRAM peak/total, GPU device, generation time, and steps/sec) for reproducibility and benchmarking."
|
||||
version = "1.1.2"
|
||||
version = "1.1.3"
|
||||
license = {file = "LICENSE"}
|
||||
# classifiers = [
|
||||
# # For OS-independent nodes (works on all operating systems)
|
||||
|
||||
@@ -16,6 +16,7 @@ from metadata_utils import (
|
||||
get_next_filename,
|
||||
get_output_directory,
|
||||
get_workflow_json,
|
||||
make_civitai_safe_text,
|
||||
resolve_filename_pattern_path,
|
||||
save_png_with_metadata,
|
||||
)
|
||||
@@ -316,7 +317,7 @@ def test_extract_workflow_attribution_from_node_properties():
|
||||
|
||||
assert attribution["token"] == "imhcrt_br_creator_workflow_v1_random"
|
||||
assert attribution["source"] == "metahub_save_node"
|
||||
assert attribution["node_version"] == "1.0.9"
|
||||
assert attribution["node_version"] == "1.1.3"
|
||||
|
||||
|
||||
def test_build_imh_metadata_includes_attribution_without_a1111_parameters():
|
||||
@@ -401,6 +402,42 @@ def test_build_a1111_metadata_formats_text():
|
||||
assert "Model hash: abcdef1234" in text
|
||||
|
||||
|
||||
def test_make_civitai_safe_text_normalizes_smart_punctuation():
|
||||
text = "McDonald\u2019s \u201cquote\u201d \u2013 dash \u2014 dash\u2026space\u00a0here"
|
||||
|
||||
assert make_civitai_safe_text(text) == "McDonald's \"quote\" - dash - dash...space here"
|
||||
|
||||
|
||||
def test_save_png_with_metadata_sanitizes_only_parameters_chunk(tmp_path):
|
||||
imh_metadata = {
|
||||
"prompt": "McDonald\u2019s \u201cquote\u201d",
|
||||
"workflow": {"nodes": [{"title": "McDonald\u2019s \u201cquote\u201d"}]},
|
||||
"prompt_api": {
|
||||
"1": {
|
||||
"class_type": "CLIPTextEncode",
|
||||
"inputs": {"text": "McDonald\u2019s \u201cquote\u201d"},
|
||||
}
|
||||
},
|
||||
}
|
||||
image = Image.new("RGB", (2, 2), color=(0, 0, 0))
|
||||
file_path = tmp_path / "civitai-safe.png"
|
||||
|
||||
save_png_with_metadata(
|
||||
image,
|
||||
str(file_path),
|
||||
"McDonald\u2019s \u201cquote\u201d \u2013 dash\u2026",
|
||||
imh_metadata,
|
||||
)
|
||||
|
||||
loaded = Image.open(file_path)
|
||||
text = getattr(loaded, "text", {})
|
||||
|
||||
assert text["parameters"] == "McDonald's \"quote\" - dash..."
|
||||
assert json.loads(text["imagemetahub_data"])["prompt"] == "McDonald\u2019s \u201cquote\u201d"
|
||||
assert json.loads(text["workflow"])["nodes"][0]["title"] == "McDonald\u2019s \u201cquote\u201d"
|
||||
assert json.loads(text["prompt"])["1"]["inputs"]["text"] == "McDonald\u2019s \u201cquote\u201d"
|
||||
|
||||
|
||||
def test_save_png_with_metadata_writes_workflow_prompt(tmp_path):
|
||||
imh_metadata = {
|
||||
"workflow": {"nodes": []},
|
||||
|
||||
Reference in New Issue
Block a user