From 4937cfbd6af88ee14ec5fc7b0cb37f4001461dd8 Mon Sep 17 00:00:00 2001 From: binichallein <132759743+binichallein@users.noreply.github.com> Date: Fri, 15 May 2026 13:20:47 +0800 Subject: [PATCH] fix: resize adb screenshots to model limit --- phone_agent/adb/screenshot.py | 27 ++++++++++++++++++++++++--- tests/test_screenshot_resize.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 tests/test_screenshot_resize.py diff --git a/phone_agent/adb/screenshot.py b/phone_agent/adb/screenshot.py index bdc5b0922..95b33b332 100644 --- a/phone_agent/adb/screenshot.py +++ b/phone_agent/adb/screenshot.py @@ -7,10 +7,11 @@ import uuid from dataclasses import dataclass from io import BytesIO -from typing import Tuple from PIL import Image +MAX_MODEL_IMAGE_DIMENSION = 2048 + @dataclass class Screenshot: @@ -67,6 +68,7 @@ def get_screenshot(device_id: str | None = None, timeout: int = 10) -> Screensho # Read and encode image img = Image.open(temp_path) + img = _resize_image_to_model_limit(img) width, height = img.size buffered = BytesIO() @@ -92,18 +94,37 @@ def _get_adb_prefix(device_id: str | None) -> list: return ["adb"] +def _resize_image_to_model_limit( + img: Image.Image, max_dimension: int = MAX_MODEL_IMAGE_DIMENSION +) -> Image.Image: + """Resize an image so neither dimension exceeds the model input limit.""" + width, height = img.size + largest_dimension = max(width, height) + if largest_dimension <= max_dimension: + return img + + scale = max_dimension / largest_dimension + resized_size = ( + max(1, int(width * scale)), + max(1, int(height * scale)), + ) + return img.resize(resized_size, Image.Resampling.LANCZOS) + + def _create_fallback_screenshot(is_sensitive: bool) -> Screenshot: """Create a black fallback image when screenshot fails.""" default_width, default_height = 1080, 2400 black_img = Image.new("RGB", (default_width, default_height), color="black") + black_img = _resize_image_to_model_limit(black_img) + width, height = black_img.size buffered = BytesIO() black_img.save(buffered, format="PNG") base64_data = base64.b64encode(buffered.getvalue()).decode("utf-8") return Screenshot( base64_data=base64_data, - width=default_width, - height=default_height, + width=width, + height=height, is_sensitive=is_sensitive, ) diff --git a/tests/test_screenshot_resize.py b/tests/test_screenshot_resize.py new file mode 100644 index 000000000..5f6e78c08 --- /dev/null +++ b/tests/test_screenshot_resize.py @@ -0,0 +1,33 @@ +import base64 +from io import BytesIO + +from PIL import Image + +from phone_agent.adb.screenshot import ( + _create_fallback_screenshot, + _resize_image_to_model_limit, +) + + +def _decode_image_size(base64_data: str) -> tuple[int, int]: + image_data = base64.b64decode(base64_data) + image = Image.open(BytesIO(image_data)) + return image.size + + +def test_resize_image_to_model_limit_preserves_aspect_ratio() -> None: + image = Image.new("RGB", (1240, 2772), color="white") + + resized = _resize_image_to_model_limit(image) + + assert resized.size == (916, 2048) + + +def test_fallback_screenshot_stays_within_model_limit() -> None: + screenshot = _create_fallback_screenshot(is_sensitive=False) + + assert max(screenshot.width, screenshot.height) <= 2048 + assert _decode_image_size(screenshot.base64_data) == ( + screenshot.width, + screenshot.height, + )