|
1 | 1 | import os |
2 | | -import shutil |
3 | | -import subprocess |
4 | 2 | import uuid |
5 | 3 |
|
| 4 | +import cv2 |
| 5 | +import numpy as np |
6 | 6 | import pytest |
7 | 7 | import pytest_asyncio |
8 | 8 | from dotenv import load_dotenv |
|
14 | 14 | EXPECTED_WIDTH, |
15 | 15 | MAX_DEPLOYMENT_ID_LENGTH, |
16 | 16 | ) |
17 | | -from tests.utils.image_generation import create_test_image |
| 17 | + |
| 18 | + |
| 19 | +def _create_base_test_image_opencv(width: int, height: int) -> np.ndarray: |
| 20 | + """Create a test image using only OpenCV2. |
| 21 | +
|
| 22 | + Creates a simple test pattern with background and accent colors. |
| 23 | +
|
| 24 | + Args: |
| 25 | + width: Image width in pixels |
| 26 | + height: Image height in pixels |
| 27 | +
|
| 28 | + Returns: |
| 29 | + numpy array in BGR format suitable for cv2.imencode |
| 30 | + """ |
| 31 | + # Create a simple test image with random colors |
| 32 | + # Background color (blue-green) |
| 33 | + img_bgr = np.zeros((height, width, 3), dtype=np.uint8) |
| 34 | + img_bgr[:, :] = (100, 150, 200) # BGR format |
| 35 | + |
| 36 | + # Add an accent rectangle for visual variation |
| 37 | + x1, y1 = width // 4, height // 4 |
| 38 | + x2, y2 = (width * 3) // 4, (height * 3) // 4 |
| 39 | + cv2.rectangle(img_bgr, (x1, y1), (x2, y2), (200, 100, 50), -1) |
| 40 | + |
| 41 | + return img_bgr |
| 42 | + |
18 | 43 |
|
19 | 44 | SUPPORTED_TEST_FORMATS = [ |
20 | 45 | "gif", |
|
25 | 50 | "pbm", |
26 | 51 | "pgm", |
27 | 52 | "ppm", |
28 | | - "pxm", |
29 | 53 | "pnm", |
30 | 54 | "sr", |
31 | 55 | "ras", |
32 | 56 | "tiff", |
33 | 57 | "pic", |
34 | 58 | "raw_uint8", |
| 59 | + |
| 60 | + # pxm - OpenCV2 has issues with this format, the docs state its |
| 61 | + # supported, but pxm is also used to mean PBM/PGM/PPM which are supported, |
| 62 | + # so its unclear if this format is truly supported. |
35 | 63 | ] |
36 | 64 |
|
37 | 65 |
|
@@ -91,47 +119,45 @@ def valid_formatted_image( |
91 | 119 | request: pytest.FixtureRequest, |
92 | 120 | tmp_path_factory: pytest.TempPathFactory, |
93 | 121 | ) -> bytes: |
94 | | - image_format = request.param |
95 | | - if (magick_path := shutil.which("magick")) is None and ( |
96 | | - magick_path := shutil.which("convert") |
97 | | - ) is None: |
98 | | - pytest.fail( |
99 | | - "ImageMagick 'magick' or 'convert' command not found - cannot " |
100 | | - "run multi-format test" |
101 | | - ) |
| 122 | + """Generate test images in various formats using OpenCV2. |
102 | 123 |
|
| 124 | + Images are cached to disk to avoid regenerating on every test run. |
| 125 | + """ |
| 126 | + image_format = request.param |
103 | 127 | image_dir = tmp_path_factory.mktemp("images") |
| 128 | + base_image = _create_base_test_image_opencv(EXPECTED_WIDTH, EXPECTED_HEIGHT) |
104 | 129 |
|
105 | | - base_image_format = "png" |
106 | | - base_image = create_test_image( |
107 | | - EXPECTED_WIDTH, EXPECTED_HEIGHT, img_format=base_image_format |
108 | | - ) |
109 | | - base_image_path = image_dir / "base_image.png" |
110 | | - if not base_image_path.exists(): |
111 | | - with base_image_path.open("wb") as f: |
112 | | - _ = f.write(base_image) |
113 | | - |
114 | | - if image_format == base_image_format: |
115 | | - return base_image |
116 | | - |
| 130 | + # Handle raw_uint8 format separately - return raw BGR bytes |
117 | 131 | if image_format == "raw_uint8": |
118 | | - return create_test_image( |
119 | | - EXPECTED_WIDTH, EXPECTED_HEIGHT, img_format="raw_uint8" |
120 | | - ) |
| 132 | + return base_image.tobytes() |
121 | 133 |
|
| 134 | + # Check if image already exists in cache |
122 | 135 | image_path = image_dir / f"test_image.{image_format}" |
123 | | - if not image_path.exists(): |
124 | | - cmd = [magick_path, str(base_image_path), str(image_path)] |
125 | | - _ = subprocess.run( # noqa: S603 - false positive :( |
126 | | - cmd, |
127 | | - check=True, |
128 | | - shell=False, |
129 | | - ) |
130 | | - |
131 | | - if not image_path.exists(): |
| 136 | + if image_path.exists(): |
| 137 | + with image_path.open("rb") as f: |
| 138 | + return f.read() |
| 139 | + |
| 140 | + # Convert format using OpenCV2 and cache to disk |
| 141 | + try: |
| 142 | + # Encode image in the target format |
| 143 | + if image_format in ["pgm", "pbm"]: |
| 144 | + # PGM and PBM are grayscale, so convert the image to grayscale |
| 145 | + gray_image = cv2.cvtColor(base_image, cv2.COLOR_BGR2GRAY) |
| 146 | + success, encoded = cv2.imencode(f".{image_format}", gray_image) |
| 147 | + else: |
| 148 | + success, encoded = cv2.imencode(f".{image_format}", base_image) |
| 149 | + |
| 150 | + if not success: |
132 | 151 | pytest.fail( |
133 | | - f"Failed to create {image_format} image with command: {cmd}" |
| 152 | + f"OpenCV failed to encode image in {image_format} format" |
134 | 153 | ) |
135 | 154 |
|
136 | | - with image_path.open("rb") as f: |
137 | | - return f.read() |
| 155 | + image_bytes = encoded.tobytes() |
| 156 | + |
| 157 | + # Cache the image to disk |
| 158 | + with image_path.open("wb") as f: |
| 159 | + _ = f.write(image_bytes) |
| 160 | + |
| 161 | + return image_bytes |
| 162 | + except Exception as e: |
| 163 | + pytest.fail(f"Failed to create {image_format} image with OpenCV: {e}") |
0 commit comments