Files
Artificial-Sweetener-Simple…/tools/decoded_image_comparison.py
T

58 lines
1.8 KiB
Python

# SimpleSyrup - workflow-focused ComfyUI extensions for image generation
# Copyright (C) 2026 Artificial Sweetener and contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
"""Compare decoded RGB image pixels independently of container metadata."""
from __future__ import annotations
from dataclasses import dataclass
from pathlib import Path
from PIL import Image
@dataclass(frozen=True, slots=True)
class DecodedImageComparison:
"""Describe one exact decoded RGB pixel comparison."""
changed_pixels: int
maximum_channel_delta: int
width: int
height: int
def as_json(self) -> dict[str, int]:
"""Return deterministic machine-readable comparison evidence."""
return {
"changed_pixels": self.changed_pixels,
"maximum_channel_delta": self.maximum_channel_delta,
"width": self.width,
"height": self.height,
}
def compare_decoded_rgb_images(
left_path: Path,
right_path: Path,
) -> DecodedImageComparison:
"""Compare decoded RGB pixels without considering file metadata."""
with Image.open(left_path) as left_source, Image.open(right_path) as right_source:
left = left_source.convert("RGB")
right = right_source.convert("RGB")
if left.size != right.size:
raise ValueError("Compared decoded images must have identical dimensions.")
left_bytes = left.tobytes()
right_bytes = right.tobytes()
maximum_delta = 0
changed_pixels = 0
for offset in range(0, len(left_bytes), 3):
deltas = tuple(
abs(left_bytes[offset + channel] - right_bytes[offset + channel])
for channel in range(3)
)
maximum_delta = max(maximum_delta, *deltas)
changed_pixels += int(any(deltas))
return DecodedImageComparison(changed_pixels, maximum_delta, *left.size)