diff --git a/tests/test_webp.py b/tests/test_webp.py index 4374a82..f623955 100644 --- a/tests/test_webp.py +++ b/tests/test_webp.py @@ -148,6 +148,16 @@ def test_image_simple(self): expected = np.asarray(img, dtype=np.uint8) assert_array_equal(actual, expected) + def test_image_target_size(self): + rng = np.random.RandomState(42) + img = Image.fromarray(rng.randint(0, 256, size=(128, 128, 3), dtype=np.uint8)) + + with TemporaryDirectory() as tmpdir: + file_name = os.path.join(tmpdir, 'image.webp') + + webp.save_image(img, file_name, target_size=5000, passes=6) + assert os.path.getsize(file_name) <= 5000 + def test_image_palette(self, image_bars_palette): with TemporaryDirectory() as tmpdir: file_name = os.path.join(tmpdir, 'image.webp') diff --git a/tests/test_webp_config.py b/tests/test_webp_config.py index c8a5b3e..7711fbc 100644 --- a/tests/test_webp_config.py +++ b/tests/test_webp_config.py @@ -11,6 +11,11 @@ def test_default(self): assert config.method == 4 del config + def test_default_target_size_override(self): + config = webp.WebPConfig.new(target_size=1000) + assert config.target_size == 1000 + del config + def test_default_lossless(self): config = webp.WebPConfig.new(lossless=True) assert config.lossless is True diff --git a/webp/__init__.py b/webp/__init__.py index ce3c9af..f7ed52a 100644 --- a/webp/__init__.py +++ b/webp/__init__.py @@ -66,6 +66,22 @@ def method(self) -> int: def method(self, method: int) -> None: self.ptr.method = method + @property + def target_size(self) -> int: + return self.ptr.target_size + + @target_size.setter + def target_size(self, target_size: int) -> None: + self.ptr.target_size = target_size + + @property + def passes(self) -> int: + return getattr(self.ptr, "pass") + + @passes.setter + def passes(self, passes: int) -> None: + setattr(self.ptr, "pass", passes) + def validate(self) -> bool: return lib.WebPValidateConfig(self.ptr) != 0 @@ -74,7 +90,10 @@ def new(preset: WebPPreset = WebPPreset.DEFAULT, quality: Optional[float] = None, lossless: bool = False, lossless_preset: Optional[int] = None, - method: Optional[int] = None) -> "WebPConfig": + method: Optional[int] = None, + *, + target_size: Optional[int] = None, + passes: Optional[int] = None) -> "WebPConfig": """Create a new WebPConfig instance to describe encoder settings. 1. The preset is loaded, setting default values for quality factor (75.0) and compression @@ -98,6 +117,9 @@ def new(preset: WebPPreset = WebPPreset.DEFAULT, factor and compression method together. Effective default is 6. method (int, optional): Compression method (0=fast but big, 6=small but slow). Overrides presets. Effective default is 4. + target_size (int, optional): Desired target size in bytes. When setting this, you + will likely want to set passes to a value greater than 1 also. + passes (int, optional): Number of entropy-analysis passes (between 1 and 10 inclusive). Returns: WebPConfig: The new WebPConfig instance. @@ -120,6 +142,10 @@ def new(preset: WebPPreset = WebPPreset.DEFAULT, config.quality = quality if method is not None: config.method = method + if target_size is not None: + config.target_size = target_size + if passes is not None: + config.passes = passes if not config.validate(): raise WebPError('config is not valid') diff --git a/webp_build/cdef.h b/webp_build/cdef.h index 8035f27..2038e11 100644 --- a/webp_build/cdef.h +++ b/webp_build/cdef.h @@ -7,6 +7,14 @@ typedef enum WebPPreset { WEBP_PRESET_TEXT } WebPPreset; +typedef enum WebPImageHint { + WEBP_HINT_DEFAULT = 0, + WEBP_HINT_PICTURE, + WEBP_HINT_PHOTO, + WEBP_HINT_GRAPH, + WEBP_HINT_LAST +} WebPImageHint; + typedef enum WEBP_CSP_MODE { MODE_RGB = 0, MODE_RGBA = 1, MODE_BGR = 2, MODE_BGRA = 3, @@ -110,6 +118,19 @@ struct WebPConfig { int lossless; float quality; int method; + WebPImageHint image_hint; + int target_size; + float target_PSNR; + int segments; + int sns_strength; + int filter_strength; + int filter_sharpness; + int filter_type; + int autofilter; + int alpha_compression; + int alpha_filtering; + int alpha_quality; + int pass; ...; }; typedef struct WebPConfig WebPConfig;