#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Test file for: crop_tif.py import os import sys from pathlib import Path import pytest # Add scripts/python to path for imports ROOT_DIR = Path(__file__).resolve().parent.parent.parent sys.path.insert(0, str(ROOT_DIR / "scripts" / "python")) # Check for dependencies try: import cv2 import numpy as np from crop_tif import crop_tif, find_content_area, resize_image HAS_CV2 = True except ImportError: HAS_CV2 = False # Tests for find_content_area @pytest.mark.skipif(not HAS_CV2, reason="cv2 (opencv-python) not available") def test_find_content_area_returns_tuple(tmp_path): """Test that find_content_area returns a 4-tuple for valid image.""" # Create a simple test image with content img = np.ones((100, 100, 3), dtype=np.uint8) * 255 # White background img[20:80, 20:80] = 0 # Black square in center test_image = tmp_path / "test.tif" cv2.imwrite(str(test_image), img) result = find_content_area(str(test_image)) assert isinstance(result, tuple) assert len(result) == 4 x, y, w, h = result assert all(isinstance(v, (int, np.integer)) for v in result) @pytest.mark.skipif(not HAS_CV2, reason="cv2 (opencv-python) not available") def test_find_content_area_all_white(tmp_path): """Test that all-white image returns full dimensions.""" # Create all-white image img = np.ones((100, 150, 3), dtype=np.uint8) * 255 test_image = tmp_path / "white.tif" cv2.imwrite(str(test_image), img) x, y, w, h = find_content_area(str(test_image)) # Should return full image dimensions assert w == 150 assert h == 100 @pytest.mark.skipif(not HAS_CV2, reason="cv2 (opencv-python) not available") def test_find_content_area_missing_file(): """Test that FileNotFoundError is raised for missing file.""" with pytest.raises(FileNotFoundError): find_content_area("/nonexistent/path/image.tif") # Tests for resize_image @pytest.mark.skipif(not HAS_CV2, reason="cv2 (opencv-python) not available") def test_resize_image_no_change(): """Test that small image within limits stays same size.""" img = np.ones((100, 200, 3), dtype=np.uint8) * 255 result = resize_image(img, max_width=2000, max_height=2000) assert result.shape[0] == 100 # height assert result.shape[1] == 200 # width @pytest.mark.skipif(not HAS_CV2, reason="cv2 (opencv-python) not available") def test_resize_image_downscale_width(): """Test that wide image gets scaled down to fit max_width.""" img = np.ones((100, 3000, 3), dtype=np.uint8) * 255 result = resize_image(img, max_width=2000, max_height=2000) assert result.shape[1] == 2000 # width limited assert result.shape[0] < 100 # height scaled proportionally @pytest.mark.skipif(not HAS_CV2, reason="cv2 (opencv-python) not available") def test_resize_image_downscale_height(): """Test that tall image gets scaled down to fit max_height.""" img = np.ones((3000, 100, 3), dtype=np.uint8) * 255 result = resize_image(img, max_width=2000, max_height=2000) assert result.shape[0] == 2000 # height limited assert result.shape[1] < 100 # width scaled proportionally # Tests for crop_tif @pytest.mark.skipif(not HAS_CV2, reason="cv2 (opencv-python) not available") def test_crop_tif_output_created(tmp_path, capsys): """Test that crop_tif creates output file.""" # Create test image img = np.ones((200, 200, 3), dtype=np.uint8) * 255 img[50:150, 50:150] = 0 # Black square input_file = tmp_path / "input.tif" output_file = tmp_path / "output.tif" cv2.imwrite(str(input_file), img) crop_tif(str(input_file), str(output_file), resize=False) assert output_file.exists() # Verify it's a valid image result_img = cv2.imread(str(output_file)) assert result_img is not None @pytest.mark.skipif(not HAS_CV2, reason="cv2 (opencv-python) not available") def test_crop_tif_missing_file_raises(): """Test that FileNotFoundError is raised for missing input.""" with pytest.raises(FileNotFoundError): crop_tif("/nonexistent/input.tif", "/tmp/output.tif") @pytest.mark.skipif(not HAS_CV2, reason="cv2 (opencv-python) not available") def test_crop_tif_no_output_no_overwrite_raises(): """Test that ValueError is raised when no output and no overwrite.""" with pytest.raises(ValueError, match="output_path must be specified"): crop_tif("input.tif", output_path=None, overwrite=False) @pytest.mark.skipif(not HAS_CV2, reason="cv2 (opencv-python) not available") def test_crop_tif_with_overwrite(tmp_path, capsys): """Test that crop_tif can overwrite input file.""" # Create test image img = np.ones((200, 200, 3), dtype=np.uint8) * 255 img[50:150, 50:150] = 0 input_file = tmp_path / "test.tif" cv2.imwrite(str(input_file), img) crop_tif(str(input_file), output_path=None, overwrite=True, resize=False) # File should still exist assert input_file.exists() result_img = cv2.imread(str(input_file)) assert result_img is not None @pytest.mark.skipif(not HAS_CV2, reason="cv2 (opencv-python) not available") def test_crop_tif_with_resize(tmp_path, capsys): """Test that crop_tif resizes when requested.""" # Create large test image img = np.ones((3000, 3000, 3), dtype=np.uint8) * 255 img[100:2900, 100:2900] = 0 input_file = tmp_path / "large.tif" output_file = tmp_path / "resized.tif" cv2.imwrite(str(input_file), img) crop_tif( str(input_file), str(output_file), resize=True, max_width=1000, max_height=1000 ) result_img = cv2.imread(str(output_file)) assert result_img.shape[0] <= 1000 assert result_img.shape[1] <= 1000 if __name__ == "__main__": import pytest pytest.main([os.path.abspath(__file__), "-v"])