mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-08 06:54:24 +00:00
nano-banana-pro: respect explicit --resolution when editing images (#36880)
* nano-banana-pro: respect explicit --resolution when editing images * Changelog: note nano banana resolution fix * Update CHANGELOG.md --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
@@ -196,6 +196,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Agents/gateway config guidance: stop exposing `config.schema` through the agent `gateway` tool, remove prompt/docs guidance that told agents to call it, and keep agents on `config.get` plus `config.patch`/`config.apply` for config changes. (#7382) thanks @kakuteki.
|
||||
- Agents/failover: classify periodic provider limit exhaustion text (for example `Weekly/Monthly Limit Exhausted`) as `rate_limit` while keeping explicit `402 Payment Required` variants in billing, so failover continues without misclassifying billing-wrapped quota errors. (#33813) thanks @zhouhe-xydt.
|
||||
- Mattermost/interactive button callbacks: allow external callback base URLs and stop requiring loopback-origin requests so button clicks work when Mattermost reaches the gateway over Tailscale, LAN, or a reverse proxy. (#37543) thanks @mukhtharcm.
|
||||
- Skills/nano-banana-pro resolution override: respect explicit `--resolution` values during image editing and only auto-detect output size from input images when the flag is omitted. (#36880) Thanks @shuofengzhang and @vincentkoc.
|
||||
|
||||
## 2026.3.2
|
||||
|
||||
|
||||
@@ -42,6 +42,33 @@ def get_api_key(provided_key: str | None) -> str | None:
|
||||
return os.environ.get("GEMINI_API_KEY")
|
||||
|
||||
|
||||
def auto_detect_resolution(max_input_dim: int) -> str:
|
||||
"""Infer output resolution from the largest input image dimension."""
|
||||
if max_input_dim >= 3000:
|
||||
return "4K"
|
||||
if max_input_dim >= 1500:
|
||||
return "2K"
|
||||
return "1K"
|
||||
|
||||
|
||||
def choose_output_resolution(
|
||||
requested_resolution: str | None,
|
||||
max_input_dim: int,
|
||||
has_input_images: bool,
|
||||
) -> tuple[str, bool]:
|
||||
"""Choose final resolution and whether it was auto-detected.
|
||||
|
||||
Auto-detection is only applied when the user did not pass --resolution.
|
||||
"""
|
||||
if requested_resolution is not None:
|
||||
return requested_resolution, False
|
||||
|
||||
if has_input_images and max_input_dim > 0:
|
||||
return auto_detect_resolution(max_input_dim), True
|
||||
|
||||
return "1K", False
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate images using Nano Banana Pro (Gemini 3 Pro Image)"
|
||||
@@ -66,8 +93,8 @@ def main():
|
||||
parser.add_argument(
|
||||
"--resolution", "-r",
|
||||
choices=["1K", "2K", "4K"],
|
||||
default="1K",
|
||||
help="Output resolution: 1K (default), 2K, or 4K"
|
||||
default=None,
|
||||
help="Output resolution: 1K, 2K, or 4K. If omitted with input images, auto-detect from largest image dimension."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--aspect-ratio", "-a",
|
||||
@@ -105,13 +132,12 @@ def main():
|
||||
|
||||
# Load input images if provided (up to 14 supported by Nano Banana Pro)
|
||||
input_images = []
|
||||
output_resolution = args.resolution
|
||||
max_input_dim = 0
|
||||
if args.input_images:
|
||||
if len(args.input_images) > 14:
|
||||
print(f"Error: Too many input images ({len(args.input_images)}). Maximum is 14.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
max_input_dim = 0
|
||||
for img_path in args.input_images:
|
||||
try:
|
||||
with PILImage.open(img_path) as img:
|
||||
@@ -126,15 +152,16 @@ def main():
|
||||
print(f"Error loading input image '{img_path}': {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Auto-detect resolution from largest input if not explicitly set
|
||||
if args.resolution == "1K" and max_input_dim > 0: # Default value
|
||||
if max_input_dim >= 3000:
|
||||
output_resolution = "4K"
|
||||
elif max_input_dim >= 1500:
|
||||
output_resolution = "2K"
|
||||
else:
|
||||
output_resolution = "1K"
|
||||
print(f"Auto-detected resolution: {output_resolution} (from max input dimension {max_input_dim})")
|
||||
output_resolution, auto_detected = choose_output_resolution(
|
||||
requested_resolution=args.resolution,
|
||||
max_input_dim=max_input_dim,
|
||||
has_input_images=bool(input_images),
|
||||
)
|
||||
if auto_detected:
|
||||
print(
|
||||
f"Auto-detected resolution: {output_resolution} "
|
||||
f"(from max input dimension {max_input_dim})"
|
||||
)
|
||||
|
||||
# Build contents (images first if editing, prompt only if generating)
|
||||
if input_images:
|
||||
|
||||
36
skills/nano-banana-pro/scripts/test_generate_image.py
Normal file
36
skills/nano-banana-pro/scripts/test_generate_image.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
MODULE_PATH = Path(__file__).with_name("generate_image.py")
|
||||
SPEC = importlib.util.spec_from_file_location("generate_image", MODULE_PATH)
|
||||
assert SPEC and SPEC.loader
|
||||
MODULE = importlib.util.module_from_spec(SPEC)
|
||||
SPEC.loader.exec_module(MODULE)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("max_input_dim", "expected"),
|
||||
[
|
||||
(0, "1K"),
|
||||
(1499, "1K"),
|
||||
(1500, "2K"),
|
||||
(2999, "2K"),
|
||||
(3000, "4K"),
|
||||
],
|
||||
)
|
||||
def test_auto_detect_resolution_thresholds(max_input_dim, expected):
|
||||
assert MODULE.auto_detect_resolution(max_input_dim) == expected
|
||||
|
||||
|
||||
def test_choose_output_resolution_auto_detects_when_resolution_omitted():
|
||||
assert MODULE.choose_output_resolution(None, 2200, True) == ("2K", True)
|
||||
|
||||
|
||||
def test_choose_output_resolution_defaults_to_1k_without_inputs():
|
||||
assert MODULE.choose_output_resolution(None, 0, False) == ("1K", False)
|
||||
|
||||
|
||||
def test_choose_output_resolution_respects_explicit_1k_with_large_input():
|
||||
assert MODULE.choose_output_resolution("1K", 3500, True) == ("1K", False)
|
||||
Reference in New Issue
Block a user