Files
iguanesolutions-comfyui-ig1…/resolution.py
T
2025-09-04 10:43:31 +02:00

99 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# pylint: disable=missing-module-docstring,disable=missing-class-docstring,missing-function-docstring,line-too-long
import math
from typing import List
class AspectRatio:
def __init__(self, numerator: int, denominator: int):
self.numerator = numerator
self.denominator = denominator
def value(self) -> float:
return self.numerator / self.denominator
def simplify(self) -> 'AspectRatio':
divisor = greatest_common_denominator(self.numerator, self.denominator)
if divisor == 1:
return self
return AspectRatio(self.numerator // divisor, self.denominator // divisor)
def __str__(self) -> str:
return f"{self.numerator}:{self.denominator}"
def __eq__(self, ar: 'AspectRatio') -> bool:
return self.numerator * ar.denominator == ar.numerator * self.denominator
class Resolution:
def __init__(self, width: int, height: int, compatibility_step: int):
self.width = width
self.height = height
self.compatibility_step = compatibility_step
def aspect_ratio(self) -> AspectRatio:
return AspectRatio(self.width, self.height).simplify()
def has_better_compatibility(self) -> bool:
return self.width % self.compatibility_step == 0 and self.height % self.compatibility_step == 0
def can_contains(self, target: 'Resolution') -> bool:
return self.width >= target.width and self.height >= target.height
def __str__(self) -> str:
return f"{self.width}×{self.height}"
def __repr__(self) -> str:
output = f"{self} ({self.total_pixels()} pixels with {self.aspect_ratio()} ratio)"
if self.has_better_compatibility():
output += " [Better Compatibility]"
return output
def total_pixels(self) -> int:
return self.width * self.height
def valid(self) -> bool:
return self.width > 0 and self.height > 0
class ResolutionsList(List[Resolution]):
def biggest_resolution(self) -> Resolution:
return max(self, key=lambda res: res.total_pixels())
def smallest_resolution(self) -> Resolution:
return min(self, key=lambda res: res.total_pixels())
def get_closest(self, target: Resolution) -> Resolution:
closest = self[0]
closest_distance = euclidean_distance([closest.width, closest.height], [
target.width, target.height])
for res in self:
distance = euclidean_distance([res.width, res.height], [
target.width, target.height])
if distance < closest_distance:
closest = res
closest_distance = distance
return closest
def get_closest_equal_or_larger(self, target: Resolution) -> Resolution:
closest_equal_or_larger = self[0]
closest_distance = euclidean_distance(
[closest_equal_or_larger.width, closest_equal_or_larger.height], [target.width, target.height])
for res in self:
distance = euclidean_distance([res.width, res.height], [
target.width, target.height])
if distance < closest_distance or not closest_equal_or_larger.can_contains(target):
closest_equal_or_larger = res
closest_distance = distance
return closest_equal_or_larger
def euclidean_distance(a: List[float], b: List[float]) -> float:
diff = [a_i - b_i for a_i, b_i in zip(a, b)]
return math.sqrt(sum(x * x for x in diff))
def greatest_common_denominator(a: int, b: int) -> int:
while b != 0:
a, b = b, a % b
return a