Add Flip filter with bool option support and calibration UI polish

- New FlipFilter with horizontal/vertical bool options (np.fliplr/flipud)
- Add bool option type to filter system (base.py validate, app.js toggle UI)
- Rearrange calibration preview: direction toggle above LED count
- Normalize direction/offset control heights, brighten offset icon

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-12 01:55:00 +03:00
parent a4991c884a
commit 136f6fd120
7 changed files with 136 additions and 27 deletions

View File

@@ -77,13 +77,16 @@ class PostprocessingFilter(ABC):
val = float(raw)
elif opt_def.option_type == "int":
val = int(raw)
elif opt_def.option_type == "bool":
val = bool(raw) if not isinstance(raw, bool) else raw
else:
val = raw
# Clamp to range
if opt_def.min_value is not None and val < opt_def.min_value:
val = opt_def.min_value
if opt_def.max_value is not None and val > opt_def.max_value:
val = opt_def.max_value
# Clamp to range (skip for bools)
if opt_def.option_type != "bool":
if opt_def.min_value is not None and val < opt_def.min_value:
val = opt_def.min_value
if opt_def.max_value is not None and val > opt_def.max_value:
val = opt_def.max_value
cleaned[opt_def.key] = val
return cleaned

View File

@@ -280,3 +280,43 @@ class AutoCropFilter(PostprocessingFilter):
result = image_pool.acquire(cropped_h, cropped_w, channels)
np.copyto(result, image[top:bottom, left:right])
return result
@FilterRegistry.register
class FlipFilter(PostprocessingFilter):
"""Flips the image horizontally and/or vertically."""
filter_id = "flip"
filter_name = "Flip"
@classmethod
def get_options_schema(cls) -> List[FilterOptionDef]:
return [
FilterOptionDef(
key="horizontal",
label="Horizontal",
option_type="bool",
default=False,
min_value=None,
max_value=None,
step=None,
),
FilterOptionDef(
key="vertical",
label="Vertical",
option_type="bool",
default=False,
min_value=None,
max_value=None,
step=None,
),
]
def process_image(self, image: np.ndarray, image_pool: ImagePool) -> Optional[np.ndarray]:
h = self.options.get("horizontal", False)
v = self.options.get("vertical", False)
if h:
image[:] = np.fliplr(image)
if v:
image[:] = np.flipud(image)
return None