backend.tests.unit.components.utils.test_image_utils
1import pytest 2import numpy as np 3import cv2 4from backend.components.utils.imageUtils import parse_image, encode_image 5from backend.components.utils import imageUtils 6 7 8# -------------------------------------------------------------------------- 9# Testy funkcji parse_image (Bytes -> Array) 10# -------------------------------------------------------------------------- 11 12def test_parse_image_success(): 13 """ 14 Checks whether valid image bytes are converted to a numpy matrix. 15 It also verifies that the result is of the correct shape. 16 """ 17 original_img = np.zeros((10, 10, 3), dtype=np.uint8) 18 19 _, buffer = cv2.imencode('.png', original_img) 20 image_bytes = buffer.tobytes() 21 22 result_img = parse_image(image_bytes) 23 24 assert isinstance(result_img, np.ndarray) 25 assert result_img.shape == (10, 10, 3) 26 27 28def test_parse_image_color_conversion(): 29 """ 30 Checks whether the function correctly converts the color format from BGR to RGB. 31 """ 32 # Tworzymy obraz 1x1 piksel w kolorze NIEBIESKIM. 33 # W OpenCV (BGR) niebieski to [255, 0, 0]. 34 bgr_pixel = np.array([[[255, 0, 0]]], dtype=np.uint8) 35 36 # Kodujemy do PNG 37 _, buffer = cv2.imencode('.png', bgr_pixel) 38 image_bytes = buffer.tobytes() 39 40 # Parsujemy (funkcja powinna zamienić BGR -> RGB) 41 rgb_pixel = parse_image(image_bytes) 42 43 # W RGB niebieski to [0, 0, 255]. 44 # Sprawdzamy, czy kanały zostały odwrócone. 45 assert rgb_pixel[0, 0, 0] == 0 # R 46 assert rgb_pixel[0, 0, 1] == 0 # G 47 assert rgb_pixel[0, 0, 2] == 255 # B 48 49 50def test_parse_image_invalid_bytes(): 51 """ 52 Checks whether a function throws a ValueError when it receives invalid bytes 53 (e.g., a text file instead of an image). 54 """ 55 garbage_bytes = b"to nie jest obrazek, tylko losowy tekst" 56 57 with pytest.raises(ValueError, match="Nie udało się przetworzyć pliku jako obrazu"): 58 parse_image(garbage_bytes) 59 60 61# -------------------------------------------------------------------------- 62# Testy funkcji encode_image (Array -> Bytes) 63# -------------------------------------------------------------------------- 64 65def test_encode_image_default_png(): 66 """ 67 Checks default encoding to PNG format. 68 """ 69 # Tworzymy prosty obraz RGB 70 img = np.zeros((10, 10, 3), dtype=np.uint8) 71 72 # Wywołanie bez podania formatu (domyślnie .png) 73 result_bytes = encode_image(img) 74 75 assert isinstance(result_bytes, bytes) 76 assert len(result_bytes) > 0 77 78 # Magiczne bajty PNG to: 89 50 4E 47 79 # Sprawdzamy nagłówek, żeby upewnić się, że to PNG 80 assert result_bytes.startswith(b'\x89PNG') 81 82 83def test_encode_image_custom_format_jpg(): 84 """ 85 Checks encoding to JPG format. 86 """ 87 img = np.zeros((10, 10, 3), dtype=np.uint8) 88 89 result_bytes = encode_image(img, encode_format=".jpg") 90 91 assert isinstance(result_bytes, bytes) 92 assert len(result_bytes) > 0 93 # Magiczne bajty JPEG zaczynają się zazwyczaj od FF D8 94 assert result_bytes.startswith(b'\xff\xd8') 95 96 97def test_encode_image_failure(): 98 """ 99 Checks whether the function throws a ValueError when OpenCV fails to encode an image. 100 We simulate this by providing an invalid file format or an empty array in a way that causes the cv2. 101 imencode function to fail. 102 """ 103 # Pusta tablica lub tablica o złym kształcie zazwyczaj zwróci False w imencode 104 bad_img = np.zeros((0, 0, 0), dtype=np.uint8) 105 106 with pytest.raises(ValueError, match="Nie udało się zenkodować obrazu"): 107 encode_image(bad_img) 108 109 110# ============================================================================ 111# Test parse_image - Success Cases 112# ============================================================================ 113 114def test_parse_image_valid_png(): 115 """Test parsing valid PNG image from bytes.""" 116 # Create a simple test image 117 test_array = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8) 118 test_array_bgr = cv2.cvtColor(test_array, cv2.COLOR_RGB2BGR) 119 120 # Encode to PNG bytes 121 success, buffer = cv2.imencode(".png", test_array_bgr) 122 image_bytes = buffer.tobytes() 123 124 # Parse back 125 result = imageUtils.parse_image(image_bytes) 126 127 assert isinstance(result, np.ndarray) 128 assert result.shape == (100, 100, 3) 129 assert result.dtype == np.uint8 130 131 132def test_parse_image_valid_jpg(): 133 """Test parsing valid JPG image from bytes.""" 134 test_array = np.random.randint(0, 256, (200, 150, 3), dtype=np.uint8) 135 test_array_bgr = cv2.cvtColor(test_array, cv2.COLOR_RGB2BGR) 136 137 success, buffer = cv2.imencode(".jpg", test_array_bgr) 138 image_bytes = buffer.tobytes() 139 140 result = imageUtils.parse_image(image_bytes) 141 142 assert isinstance(result, np.ndarray) 143 assert result.shape[2] == 3 # RGB channels 144 assert result.dtype == np.uint8 145 146 147# ============================================================================ 148# Test encode_image - Success Cases 149# ============================================================================ 150 151def test_encode_image_default_png(): 152 """Test encoding image to PNG (default format).""" 153 test_array = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8) 154 155 result = imageUtils.encode_image(test_array) 156 157 assert isinstance(result, bytes) 158 assert len(result) > 0 159 # PNG files start with specific magic bytes 160 assert result[:8] == b'\x89PNG\r\n\x1a\n' 161 162 163def test_encode_image_to_jpg(): 164 """Test encoding image to JPG format.""" 165 test_array = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8) 166 167 result = imageUtils.encode_image(test_array, encode_format=".jpg") 168 169 assert isinstance(result, bytes) 170 assert len(result) > 0 171 # JPG files start with FFD8FF 172 assert result[:2] == b'\xff\xd8' 173 174 175def test_encode_image_various_sizes(): 176 """Test encoding images of various sizes.""" 177 sizes = [(50, 50), (100, 200), (800, 600)] 178 179 for height, width in sizes: 180 test_array = np.random.randint(0, 256, (height, width, 3), dtype=np.uint8) 181 result = imageUtils.encode_image(test_array) 182 183 assert isinstance(result, bytes) 184 assert len(result) > 0 185 186 187def test_encode_image_preserves_content(): 188 """Test that encoded image can be decoded back.""" 189 original = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8) 190 191 # Encode 192 encoded_bytes = imageUtils.encode_image(original) 193 194 # Decode back 195 decoded = imageUtils.parse_image(encoded_bytes) 196 197 assert isinstance(decoded, np.ndarray) 198 # Allow for compression artifacts 199 assert decoded.shape == original.shape 200 201 202# ============================================================================ 203# Test Round-trip Conversion 204# ============================================================================ 205 206def test_parse_and_encode(): 207 """Test parse -> encode -> parse produces same dimensions.""" 208 original = np.random.randint(0, 256, (150, 200, 3), dtype=np.uint8) 209 original_bgr = cv2.cvtColor(original, cv2.COLOR_RGB2BGR) 210 211 # Create initial bytes 212 success, buffer = cv2.imencode(".png", original_bgr) 213 image_bytes = buffer.tobytes() 214 215 # Parse 216 parsed = imageUtils.parse_image(image_bytes) 217 218 # Encode back 219 re_encoded = imageUtils.encode_image(parsed) 220 221 # Parse again 222 re_parsed = imageUtils.parse_image(re_encoded) 223 224 assert parsed.shape == re_parsed.shape 225 assert parsed.dtype == re_parsed.dtype 226 227 228def test_encode_and_parse(): 229 """Test encode -> parse produces same dimensions.""" 230 original = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8) 231 232 # Encode 233 encoded = imageUtils.encode_image(original) 234 235 # Parse 236 parsed = imageUtils.parse_image(encoded) 237 238 assert parsed.shape == original.shape 239 assert parsed.dtype == original.dtype
13def test_parse_image_success(): 14 """ 15 Checks whether valid image bytes are converted to a numpy matrix. 16 It also verifies that the result is of the correct shape. 17 """ 18 original_img = np.zeros((10, 10, 3), dtype=np.uint8) 19 20 _, buffer = cv2.imencode('.png', original_img) 21 image_bytes = buffer.tobytes() 22 23 result_img = parse_image(image_bytes) 24 25 assert isinstance(result_img, np.ndarray) 26 assert result_img.shape == (10, 10, 3)
Checks whether valid image bytes are converted to a numpy matrix. It also verifies that the result is of the correct shape.
29def test_parse_image_color_conversion(): 30 """ 31 Checks whether the function correctly converts the color format from BGR to RGB. 32 """ 33 # Tworzymy obraz 1x1 piksel w kolorze NIEBIESKIM. 34 # W OpenCV (BGR) niebieski to [255, 0, 0]. 35 bgr_pixel = np.array([[[255, 0, 0]]], dtype=np.uint8) 36 37 # Kodujemy do PNG 38 _, buffer = cv2.imencode('.png', bgr_pixel) 39 image_bytes = buffer.tobytes() 40 41 # Parsujemy (funkcja powinna zamienić BGR -> RGB) 42 rgb_pixel = parse_image(image_bytes) 43 44 # W RGB niebieski to [0, 0, 255]. 45 # Sprawdzamy, czy kanały zostały odwrócone. 46 assert rgb_pixel[0, 0, 0] == 0 # R 47 assert rgb_pixel[0, 0, 1] == 0 # G 48 assert rgb_pixel[0, 0, 2] == 255 # B
Checks whether the function correctly converts the color format from BGR to RGB.
51def test_parse_image_invalid_bytes(): 52 """ 53 Checks whether a function throws a ValueError when it receives invalid bytes 54 (e.g., a text file instead of an image). 55 """ 56 garbage_bytes = b"to nie jest obrazek, tylko losowy tekst" 57 58 with pytest.raises(ValueError, match="Nie udało się przetworzyć pliku jako obrazu"): 59 parse_image(garbage_bytes)
Checks whether a function throws a ValueError when it receives invalid bytes (e.g., a text file instead of an image).
152def test_encode_image_default_png(): 153 """Test encoding image to PNG (default format).""" 154 test_array = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8) 155 156 result = imageUtils.encode_image(test_array) 157 158 assert isinstance(result, bytes) 159 assert len(result) > 0 160 # PNG files start with specific magic bytes 161 assert result[:8] == b'\x89PNG\r\n\x1a\n'
Test encoding image to PNG (default format).
84def test_encode_image_custom_format_jpg(): 85 """ 86 Checks encoding to JPG format. 87 """ 88 img = np.zeros((10, 10, 3), dtype=np.uint8) 89 90 result_bytes = encode_image(img, encode_format=".jpg") 91 92 assert isinstance(result_bytes, bytes) 93 assert len(result_bytes) > 0 94 # Magiczne bajty JPEG zaczynają się zazwyczaj od FF D8 95 assert result_bytes.startswith(b'\xff\xd8')
Checks encoding to JPG format.
98def test_encode_image_failure(): 99 """ 100 Checks whether the function throws a ValueError when OpenCV fails to encode an image. 101 We simulate this by providing an invalid file format or an empty array in a way that causes the cv2. 102 imencode function to fail. 103 """ 104 # Pusta tablica lub tablica o złym kształcie zazwyczaj zwróci False w imencode 105 bad_img = np.zeros((0, 0, 0), dtype=np.uint8) 106 107 with pytest.raises(ValueError, match="Nie udało się zenkodować obrazu"): 108 encode_image(bad_img)
Checks whether the function throws a ValueError when OpenCV fails to encode an image. We simulate this by providing an invalid file format or an empty array in a way that causes the cv2. imencode function to fail.
115def test_parse_image_valid_png(): 116 """Test parsing valid PNG image from bytes.""" 117 # Create a simple test image 118 test_array = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8) 119 test_array_bgr = cv2.cvtColor(test_array, cv2.COLOR_RGB2BGR) 120 121 # Encode to PNG bytes 122 success, buffer = cv2.imencode(".png", test_array_bgr) 123 image_bytes = buffer.tobytes() 124 125 # Parse back 126 result = imageUtils.parse_image(image_bytes) 127 128 assert isinstance(result, np.ndarray) 129 assert result.shape == (100, 100, 3) 130 assert result.dtype == np.uint8
Test parsing valid PNG image from bytes.
133def test_parse_image_valid_jpg(): 134 """Test parsing valid JPG image from bytes.""" 135 test_array = np.random.randint(0, 256, (200, 150, 3), dtype=np.uint8) 136 test_array_bgr = cv2.cvtColor(test_array, cv2.COLOR_RGB2BGR) 137 138 success, buffer = cv2.imencode(".jpg", test_array_bgr) 139 image_bytes = buffer.tobytes() 140 141 result = imageUtils.parse_image(image_bytes) 142 143 assert isinstance(result, np.ndarray) 144 assert result.shape[2] == 3 # RGB channels 145 assert result.dtype == np.uint8
Test parsing valid JPG image from bytes.
164def test_encode_image_to_jpg(): 165 """Test encoding image to JPG format.""" 166 test_array = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8) 167 168 result = imageUtils.encode_image(test_array, encode_format=".jpg") 169 170 assert isinstance(result, bytes) 171 assert len(result) > 0 172 # JPG files start with FFD8FF 173 assert result[:2] == b'\xff\xd8'
Test encoding image to JPG format.
176def test_encode_image_various_sizes(): 177 """Test encoding images of various sizes.""" 178 sizes = [(50, 50), (100, 200), (800, 600)] 179 180 for height, width in sizes: 181 test_array = np.random.randint(0, 256, (height, width, 3), dtype=np.uint8) 182 result = imageUtils.encode_image(test_array) 183 184 assert isinstance(result, bytes) 185 assert len(result) > 0
Test encoding images of various sizes.
188def test_encode_image_preserves_content(): 189 """Test that encoded image can be decoded back.""" 190 original = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8) 191 192 # Encode 193 encoded_bytes = imageUtils.encode_image(original) 194 195 # Decode back 196 decoded = imageUtils.parse_image(encoded_bytes) 197 198 assert isinstance(decoded, np.ndarray) 199 # Allow for compression artifacts 200 assert decoded.shape == original.shape
Test that encoded image can be decoded back.
207def test_parse_and_encode(): 208 """Test parse -> encode -> parse produces same dimensions.""" 209 original = np.random.randint(0, 256, (150, 200, 3), dtype=np.uint8) 210 original_bgr = cv2.cvtColor(original, cv2.COLOR_RGB2BGR) 211 212 # Create initial bytes 213 success, buffer = cv2.imencode(".png", original_bgr) 214 image_bytes = buffer.tobytes() 215 216 # Parse 217 parsed = imageUtils.parse_image(image_bytes) 218 219 # Encode back 220 re_encoded = imageUtils.encode_image(parsed) 221 222 # Parse again 223 re_parsed = imageUtils.parse_image(re_encoded) 224 225 assert parsed.shape == re_parsed.shape 226 assert parsed.dtype == re_parsed.dtype
Test parse -> encode -> parse produces same dimensions.
229def test_encode_and_parse(): 230 """Test encode -> parse produces same dimensions.""" 231 original = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8) 232 233 # Encode 234 encoded = imageUtils.encode_image(original) 235 236 # Parse 237 parsed = imageUtils.parse_image(encoded) 238 239 assert parsed.shape == original.shape 240 assert parsed.dtype == original.dtype
Test encode -> parse produces same dimensions.