feat: add minimum photo resolution filters for sources

This commit is contained in:
渡口浪人
2026-10-18 14:59:35 +08:00
parent 9f1c15a4c4
commit 3cff5045b2
6 changed files with 203 additions and 2 deletions
@@ -39,6 +39,8 @@ class PhotoSourceInput(StrictModel):
organized_only: bool = False
folder_caption: bool = False
orientation: Literal["auto", "landscape", "portrait"] | None = None
minimum_short_edge: int = Field(default=0, ge=0, le=50000)
minimum_long_edge: int = Field(default=0, ge=0, le=50000)
minimum_sharpness: float = Field(default=0, ge=0, le=10000)
minimum_brightness: float = Field(default=0, ge=0, le=255)
maximum_brightness: float = Field(default=255, ge=0, le=255)
@@ -412,6 +414,8 @@ class PhotoSources:
height,
)
)
if not self.resolution_matches(source, width, height):
continue
direction = orientation(width, height)
if wanted and direction != wanted:
continue
@@ -478,6 +482,8 @@ class PhotoSources:
rotation = row.get("additional", {}).get("orientation", 1)
if rotation in (5, 6, 7, 8):
width, height = height, width
if not self.resolution_matches(source, width, height):
continue
direction = orientation(width, height)
if wanted and (not width or not height or direction != wanted):
continue
@@ -560,6 +566,11 @@ class PhotoSources:
self.cache[source_id] = (time.monotonic(), items, wanted, session_identity)
return items
@staticmethod
def resolution_matches(source, width, height):
short, long = sorted((width, height))
return short >= source.minimum_short_edge and long >= source.minimum_long_edge
def read(self, source_id, item_id=None, *, target_size=(1200, 1600)):
source = self.get(source_id)
items = self.catalog(source_id, target_size=target_size)
@@ -642,4 +653,15 @@ class PhotoSources:
data = self.assets.fetch_url(item["id"], headers=self.headers(source))
if len(data) > self.settings.max_bytes:
raise FlowError(E.INVALID_REQUEST, "Image exceeds size limit")
if source.minimum_short_edge or source.minimum_long_edge:
from io import BytesIO
from PIL import Image
with Image.open(BytesIO(data)) as image:
if not self.resolution_matches(source, *image.size):
raise FlowError(
E.INVALID_REQUEST,
"Photo is below the configured minimum resolution",
)
return data, item["name"], item.get("caption")