diff --git a/docs/tutorials/image_processing.ipynb b/docs/tutorials/image_processing.ipynb index d306ca154..fd063f807 100644 --- a/docs/tutorials/image_processing.ipynb +++ b/docs/tutorials/image_processing.ipynb @@ -175,7 +175,7 @@ "execution_count": null, "outputs": [], "source": [ - "# plane.adjust_color_balance(0.5)" + "plane.adjust_color_balance(0.5)" ], "metadata": { "collapsed": false @@ -280,7 +280,7 @@ "execution_count": null, "outputs": [], "source": [ - "# plane.find_edges()\n" + "plane.find_edges()\n" ], "metadata": { "collapsed": false diff --git a/src/safeds/data/image/containers/_image.py b/src/safeds/data/image/containers/_image.py index 763fbcb82..4f4f73045 100644 --- a/src/safeds/data/image/containers/_image.py +++ b/src/safeds/data/image/containers/_image.py @@ -34,6 +34,12 @@ class Image: _pil_to_tensor = PILToTensor() _default_device = _get_device() + _FILTER_EDGES_KERNEL = ( + torch.tensor([[-1.0, -1.0, -1.0], [-1.0, 8.0, -1.0], [-1.0, -1.0, -1.0]]) + .unsqueeze(dim=0) + .unsqueeze(dim=0) + .to(_default_device) + ) @staticmethod def from_file(path: str | Path, device: Device = _default_device) -> Image: @@ -116,7 +122,10 @@ def _repr_jpeg_(self) -> bytes | None: if self.channel == 4: return None buffer = io.BytesIO() - save_image(self._image_tensor.to(torch.float32) / 255, buffer, format="jpeg") + if self.channel == 1: + func2.to_pil_image(self._image_tensor, mode="L").save(buffer, format="jpeg") + else: + save_image(self._image_tensor.to(torch.float32) / 255, buffer, format="jpeg") buffer.seek(0) return buffer.read() @@ -130,7 +139,10 @@ def _repr_png_(self) -> bytes: The image as PNG. """ buffer = io.BytesIO() - save_image(self._image_tensor.to(torch.float32) / 255, buffer, format="png") + if self.channel == 1: + func2.to_pil_image(self._image_tensor, mode="L").save(buffer, format="png") + else: + save_image(self._image_tensor.to(torch.float32) / 255, buffer, format="png") buffer.seek(0) return buffer.read() @@ -213,7 +225,10 @@ def to_jpeg_file(self, path: str | Path) -> None: if self.channel == 4: raise IllegalFormatError("png") Path(path).parent.mkdir(parents=True, exist_ok=True) - save_image(self._image_tensor.to(torch.float32) / 255, path, format="jpeg") + if self.channel == 1: + func2.to_pil_image(self._image_tensor, mode="L").save(path, format="jpeg") + else: + save_image(self._image_tensor.to(torch.float32) / 255, path, format="jpeg") def to_png_file(self, path: str | Path) -> None: """ @@ -225,7 +240,10 @@ def to_png_file(self, path: str | Path) -> None: The path to the PNG file. """ Path(path).parent.mkdir(parents=True, exist_ok=True) - save_image(self._image_tensor.to(torch.float32) / 255, path, format="png") + if self.channel == 1: + func2.to_pil_image(self._image_tensor, mode="L").save(path, format="png") + else: + save_image(self._image_tensor.to(torch.float32) / 255, path, format="png") # ------------------------------------------------------------------------------------------------------------------ # Transformations @@ -457,6 +475,12 @@ def adjust_color_balance(self, factor: float) -> Image: UserWarning, stacklevel=2, ) + elif self.channel == 1: + warnings.warn( + "Color adjustment will not have an affect on grayscale images with only one channel.", + UserWarning, + stacklevel=2, + ) return Image( self.convert_to_grayscale()._image_tensor * (1.0 - factor * 1.0) + self._image_tensor * (factor * 1.0), device=self.device, @@ -568,3 +592,38 @@ def rotate_left(self) -> Image: The image rotated 90 degrees counter-clockwise. """ return Image(func2.rotate(self._image_tensor, 90, expand=True), device=self.device) + + def find_edges(self) -> Image: + """ + Return a grayscale version of the image with the edges highlighted. + + The original image is not modified. + + Returns + ------- + result : Image + The image with edges found. + """ + kernel = ( + Image._FILTER_EDGES_KERNEL + if self.device.type == Image._default_device + else Image._FILTER_EDGES_KERNEL.to(self.device) + ) + edges_tensor = torch.clamp( + torch.nn.functional.conv2d( + self.convert_to_grayscale()._image_tensor.float()[0].unsqueeze(dim=0), + kernel, + padding="same", + ).squeeze(dim=1), + 0, + 255, + ).to(torch.uint8) + if self.channel == 3: + return Image(edges_tensor.repeat(3, 1, 1), device=self.device) + elif self.channel == 4: + return Image( + torch.cat([edges_tensor.repeat(3, 1, 1), self._image_tensor[3].unsqueeze(dim=0)]), + device=self.device, + ) + else: + return Image(edges_tensor, device=self.device) diff --git a/tests/resources/image/grayscale.jpg b/tests/resources/image/grayscale.jpg new file mode 100644 index 000000000..aee8e7957 Binary files /dev/null and b/tests/resources/image/grayscale.jpg differ diff --git a/tests/resources/image/grayscale.png b/tests/resources/image/grayscale.png new file mode 100644 index 000000000..a89155613 Binary files /dev/null and b/tests/resources/image/grayscale.png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-minimum noise-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-minimum noise-cpu].png new file mode 100644 index 000000000..f53b0a950 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-minimum noise-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-minimum noise-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-minimum noise-cuda].png new file mode 100644 index 000000000..f53b0a950 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-minimum noise-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-some noise-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-some noise-cpu].png new file mode 100644 index 000000000..1dd360e32 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-some noise-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-some noise-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-some noise-cuda].png new file mode 100644 index 000000000..1dd360e32 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-some noise-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-very noisy-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-very noisy-cpu].png new file mode 100644 index 000000000..66b8714af Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-very noisy-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-very noisy-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-very noisy-cuda].png new file mode 100644 index 000000000..66b8714af Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-jpg-grayscale-very noisy-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-minimum noise-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-minimum noise-cpu].png new file mode 100644 index 000000000..c4d2ce71b Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-minimum noise-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-minimum noise-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-minimum noise-cuda].png new file mode 100644 index 000000000..c4d2ce71b Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-minimum noise-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-some noise-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-some noise-cpu].png new file mode 100644 index 000000000..32967f5fa Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-some noise-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-some noise-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-some noise-cuda].png new file mode 100644 index 000000000..32967f5fa Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-some noise-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-very noisy-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-very noisy-cpu].png new file mode 100644 index 000000000..b20e04f08 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-very noisy-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-very noisy-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-very noisy-cuda].png new file mode 100644 index 000000000..b20e04f08 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAddNoise.test_should_add_noise[opaque-1-channel-png-grayscale-very noisy-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-large factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-large factor-cpu].png new file mode 100644 index 000000000..b22dbf313 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-large factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-large factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-large factor-cuda].png new file mode 100644 index 000000000..b22dbf313 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-large factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-small factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-small factor-cpu].png new file mode 100644 index 000000000..0b90605f5 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-small factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-small factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-small factor-cuda].png new file mode 100644 index 000000000..0b90605f5 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-jpg-grayscale-small factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-large factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-large factor-cpu].png new file mode 100644 index 000000000..9c03c56eb Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-large factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-large factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-large factor-cuda].png new file mode 100644 index 000000000..9c03c56eb Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-large factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-small factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-small factor-cpu].png new file mode 100644 index 000000000..5fd3b4fab Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-small factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-small factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-small factor-cuda].png new file mode 100644 index 000000000..5fd3b4fab Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestAdjustContrast.test_should_adjust_contrast[opaque-1-channel-png-grayscale-small factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-jpg-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-jpg-grayscale-cpu].png new file mode 100644 index 000000000..7cf5c2cf6 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-jpg-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-jpg-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-jpg-grayscale-cuda].png new file mode 100644 index 000000000..7cf5c2cf6 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-jpg-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-png-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-png-grayscale-cpu].png new file mode 100644 index 000000000..1852f77cc Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-png-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-png-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-png-grayscale-cuda].png new file mode 100644 index 000000000..1852f77cc Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBlur.test_should_return_blurred_image[opaque-1-channel-png-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-large factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-large factor-cpu].png new file mode 100644 index 000000000..559248113 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-large factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-large factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-large factor-cuda].png new file mode 100644 index 000000000..559248113 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-large factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-small factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-small factor-cpu].png new file mode 100644 index 000000000..76048f2e9 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-small factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-small factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-small factor-cuda].png new file mode 100644 index 000000000..76048f2e9 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-jpg-grayscale-small factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-large factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-large factor-cpu].png new file mode 100644 index 000000000..6d9858766 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-large factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-large factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-large factor-cuda].png new file mode 100644 index 000000000..6d9858766 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-large factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-small factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-small factor-cpu].png new file mode 100644 index 000000000..99ca03bc2 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-small factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-small factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-small factor-cuda].png new file mode 100644 index 000000000..99ca03bc2 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestBrightness.test_should_adjust_brightness[opaque-1-channel-png-grayscale-small factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-jpg-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-jpg-grayscale-cpu].png new file mode 100644 index 000000000..79a7c4c9c Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-jpg-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-jpg-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-jpg-grayscale-cuda].png new file mode 100644 index 000000000..79a7c4c9c Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-jpg-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-png-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-png-grayscale-cpu].png new file mode 100644 index 000000000..c0a5f338f Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-png-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-png-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-png-grayscale-cuda].png new file mode 100644 index 000000000..c0a5f338f Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestConvertToGrayscale.test_convert_to_grayscale[opaque-1-channel-png-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-jpg-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-jpg-grayscale-cpu].png new file mode 100644 index 000000000..6f79881aa Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-jpg-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-jpg-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-jpg-grayscale-cuda].png new file mode 100644 index 000000000..6f79881aa Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-jpg-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-png-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-png-grayscale-cpu].png new file mode 100644 index 000000000..aa111dbad Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-png-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-png-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-png-grayscale-cuda].png new file mode 100644 index 000000000..aa111dbad Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestCrop.test_should_return_cropped_image[opaque-1-channel-png-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-jpg-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-jpg-grayscale-cpu].png new file mode 100644 index 000000000..3fad4f556 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-jpg-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-jpg-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-jpg-grayscale-cuda].png new file mode 100644 index 000000000..3fad4f556 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-jpg-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-png-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-png-grayscale-cpu].png new file mode 100644 index 000000000..3b8b7e3f5 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-png-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-png-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-png-grayscale-cuda].png new file mode 100644 index 000000000..3b8b7e3f5 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-1-channel-png-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-plane-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-plane-cpu].png new file mode 100644 index 000000000..184e3d544 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-plane-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-plane-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-plane-cuda].png new file mode 100644 index 000000000..184e3d544 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-plane-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-white_square-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-white_square-cpu].png new file mode 100644 index 000000000..94381b429 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-white_square-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-white_square-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-white_square-cuda].png new file mode 100644 index 000000000..94381b429 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-jpg-white_square-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-png-white_square-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-png-white_square-cpu].png new file mode 100644 index 000000000..94381b429 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-png-white_square-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-png-white_square-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-png-white_square-cuda].png new file mode 100644 index 000000000..94381b429 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-3-channel-png-white_square-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-4-channel-png-plane-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-4-channel-png-plane-cpu].png new file mode 100644 index 000000000..034d1f6dc Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-4-channel-png-plane-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-4-channel-png-plane-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-4-channel-png-plane-cuda].png new file mode 100644 index 000000000..034d1f6dc Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[opaque-4-channel-png-plane-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[transparent-4-channel-png-rgba-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[transparent-4-channel-png-rgba-cpu].png new file mode 100644 index 000000000..5b6f27592 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[transparent-4-channel-png-rgba-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[transparent-4-channel-png-rgba-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[transparent-4-channel-png-rgba-cuda].png new file mode 100644 index 000000000..5b6f27592 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFindEdges.test_should_return_edges_of_image[transparent-4-channel-png-rgba-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-jpg-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-jpg-grayscale-cpu].png new file mode 100644 index 000000000..0f259c701 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-jpg-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-jpg-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-jpg-grayscale-cuda].png new file mode 100644 index 000000000..0f259c701 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-jpg-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-png-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-png-grayscale-cpu].png new file mode 100644 index 000000000..96405e88e Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-png-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-png-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-png-grayscale-cuda].png new file mode 100644 index 000000000..96405e88e Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipHorizontally.test_should_flip_horizontally[opaque-1-channel-png-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-jpg-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-jpg-grayscale-cpu].png new file mode 100644 index 000000000..0f259c701 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-jpg-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-jpg-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-jpg-grayscale-cuda].png new file mode 100644 index 000000000..0f259c701 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-jpg-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-png-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-png-grayscale-cpu].png new file mode 100644 index 000000000..96405e88e Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-png-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-png-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-png-grayscale-cuda].png new file mode 100644 index 000000000..96405e88e Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestFlipVertically.test_should_flip_vertically[opaque-1-channel-png-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-jpg-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-jpg-grayscale-cpu].png new file mode 100644 index 000000000..390da7c54 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-jpg-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-jpg-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-jpg-grayscale-cuda].png new file mode 100644 index 000000000..390da7c54 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-jpg-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-png-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-png-grayscale-cpu].png new file mode 100644 index 000000000..e14828ba4 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-png-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-png-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-png-grayscale-cuda].png new file mode 100644 index 000000000..e14828ba4 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestInvertColors.test_should_invert_colors[opaque-1-channel-png-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-jpg-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-jpg-grayscale-cpu].png new file mode 100644 index 000000000..2dd33f50a Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-jpg-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-jpg-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-jpg-grayscale-cuda].png new file mode 100644 index 000000000..2dd33f50a Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-jpg-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-png-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-png-grayscale-cpu].png new file mode 100644 index 000000000..00daafa37 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-png-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-png-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-png-grayscale-cuda].png new file mode 100644 index 000000000..00daafa37 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(2, 3)-opaque-1-channel-png-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-jpg-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-jpg-grayscale-cpu].png new file mode 100644 index 000000000..37abf75f1 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-jpg-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-jpg-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-jpg-grayscale-cuda].png new file mode 100644 index 000000000..37abf75f1 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-jpg-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-png-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-png-grayscale-cpu].png new file mode 100644 index 000000000..9f174e615 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-png-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-png-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-png-grayscale-cuda].png new file mode 100644 index 000000000..9f174e615 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestResize.test_should_return_resized_image[(700, 400)-opaque-1-channel-png-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cpu].png new file mode 100644 index 000000000..278ad9641 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cuda].png new file mode 100644 index 000000000..278ad9641 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-png-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-png-grayscale-cpu].png new file mode 100644 index 000000000..96405e88e Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-png-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-png-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-png-grayscale-cuda].png new file mode 100644 index 000000000..96405e88e Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_clockwise_rotated_image[opaque-1-channel-png-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cpu].png new file mode 100644 index 000000000..278ad9641 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cuda].png new file mode 100644 index 000000000..278ad9641 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-jpg-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-png-grayscale-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-png-grayscale-cpu].png new file mode 100644 index 000000000..96405e88e Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-png-grayscale-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-png-grayscale-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-png-grayscale-cuda].png new file mode 100644 index 000000000..96405e88e Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestRotate.test_should_return_counter_clockwise_rotated_image[opaque-1-channel-png-grayscale-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-large factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-large factor-cpu].png new file mode 100644 index 000000000..d28eeec3e Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-large factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-large factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-large factor-cuda].png new file mode 100644 index 000000000..d28eeec3e Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-large factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-small factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-small factor-cpu].png new file mode 100644 index 000000000..83e11ef44 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-small factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-small factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-small factor-cuda].png new file mode 100644 index 000000000..83e11ef44 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-small factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-zero factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-zero factor-cpu].png new file mode 100644 index 000000000..b1dd5d468 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-zero factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-zero factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-zero factor-cuda].png new file mode 100644 index 000000000..b1dd5d468 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-jpg-grayscale-zero factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-large factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-large factor-cpu].png new file mode 100644 index 000000000..0e9a5801b Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-large factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-large factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-large factor-cuda].png new file mode 100644 index 000000000..0e9a5801b Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-large factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-small factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-small factor-cpu].png new file mode 100644 index 000000000..973faa3c2 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-small factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-small factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-small factor-cuda].png new file mode 100644 index 000000000..973faa3c2 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-small factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-zero factor-cpu].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-zero factor-cpu].png new file mode 100644 index 000000000..b963e5df8 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-zero factor-cpu].png differ diff --git a/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-zero factor-cuda].png b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-zero factor-cuda].png new file mode 100644 index 000000000..b963e5df8 Binary files /dev/null and b/tests/safeds/data/image/containers/__snapshots__/test_image/TestSharpen.test_should_sharpen[opaque-1-channel-png-grayscale-zero factor-cuda].png differ diff --git a/tests/safeds/data/image/containers/test_image.py b/tests/safeds/data/image/containers/test_image.py index 1c4231fb3..0b09e0dd2 100644 --- a/tests/safeds/data/image/containers/test_image.py +++ b/tests/safeds/data/image/containers/test_image.py @@ -20,12 +20,16 @@ _rgba_png_path = "image/rgba.png" _white_square_jpg_path = "image/white_square.jpg" _white_square_png_path = "image/white_square.png" +_grayscale_jpg_path = "image/grayscale.jpg" +_grayscale_png_path = "image/grayscale.png" _plane_jpg_id = "opaque-3-channel-jpg-plane" _plane_png_id = "opaque-4-channel-png-plane" _rgba_png_id = "transparent-4-channel-png-rgba" _white_square_jpg_id = "opaque-3-channel-jpg-white_square" _white_square_png_id = "opaque-3-channel-png-white_square" +_grayscale_jpg_id = "opaque-1-channel-jpg-grayscale" +_grayscale_png_id = "opaque-1-channel-png-grayscale" def _test_devices() -> list[torch.device]: @@ -43,6 +47,8 @@ def _test_images_all() -> list[str]: _rgba_png_path, _white_square_jpg_path, _white_square_png_path, + _grayscale_jpg_path, + _grayscale_png_path, ] @@ -53,6 +59,8 @@ def _test_images_all_ids() -> list[str]: _rgba_png_id, _white_square_jpg_id, _white_square_png_id, + _grayscale_jpg_id, + _grayscale_png_id, ] @@ -61,6 +69,8 @@ def _test_images_asymmetric() -> list[str]: _plane_jpg_path, _plane_png_path, _rgba_png_path, + _grayscale_jpg_path, + _grayscale_png_path, ] @@ -69,6 +79,8 @@ def _test_images_asymmetric_ids() -> list[str]: _plane_jpg_id, _plane_png_id, _rgba_png_id, + _grayscale_jpg_id, + _grayscale_png_id, ] @@ -77,6 +89,12 @@ def _skip_if_device_not_available(device: Device) -> None: pytest.skip("This test requires cuda") +def _assert_width_height_channel(image1: Image, image2: Image) -> None: + assert image1.width == image2.width + assert image1.height == image2.height + assert image1.channel == image2.channel + + @pytest.mark.parametrize("device", _test_devices(), ids=_test_devices_ids()) class TestFromFile: @pytest.mark.parametrize( @@ -112,14 +130,14 @@ def test_should_raise_if_file_not_found(self, resource_path: str | Path, device: class TestFromBytes: @pytest.mark.parametrize( "resource_path", - [_white_square_jpg_path, _white_square_png_path], - ids=[_white_square_jpg_id, _white_square_png_id], + [_plane_jpg_path, _white_square_jpg_path, _white_square_png_path, _grayscale_jpg_path, _grayscale_png_path], + ids=[_plane_jpg_id, _white_square_jpg_id, _white_square_png_id, _grayscale_jpg_id, _grayscale_png_id], ) def test_should_write_and_load_bytes_jpeg(self, resource_path: str | Path, device: Device) -> None: _skip_if_device_not_available(device) image = Image.from_file(resolve_resource_path(resource_path), device) image_copy = Image.from_bytes(typing.cast(bytes, image._repr_jpeg_()), device) - assert image == image_copy + _assert_width_height_channel(image, image_copy) @pytest.mark.parametrize( "resource_path", @@ -137,8 +155,8 @@ def test_should_write_and_load_bytes_png(self, resource_path: str | Path, device class TestReprJpeg: @pytest.mark.parametrize( "resource_path", - [_plane_jpg_path, _white_square_jpg_path, _white_square_png_path], - ids=[_plane_jpg_id, _white_square_jpg_id, _white_square_png_id], + [_plane_jpg_path, _white_square_jpg_path, _white_square_png_path, _grayscale_jpg_path, _grayscale_png_path], + ids=[_plane_jpg_id, _white_square_jpg_id, _white_square_png_id, _grayscale_jpg_id, _grayscale_png_id], ) def test_should_return_bytes(self, resource_path: str | Path, device: Device) -> None: _skip_if_device_not_available(device) @@ -176,8 +194,8 @@ def test_should_return_bytes(self, resource_path: str | Path, device: Device) -> class TestToJpegFile: @pytest.mark.parametrize( "resource_path", - [_white_square_jpg_path, _white_square_png_path], - ids=[_white_square_jpg_id, _white_square_png_id], + [_plane_jpg_path, _white_square_jpg_path, _white_square_png_path, _grayscale_jpg_path, _grayscale_png_path], + ids=[_plane_jpg_id, _white_square_jpg_id, _white_square_png_id, _grayscale_jpg_id, _grayscale_png_id], ) def test_should_save_file(self, resource_path: str | Path, device: Device) -> None: _skip_if_device_not_available(device) @@ -188,7 +206,7 @@ def test_should_save_file(self, resource_path: str | Path, device: Device) -> No image.to_jpeg_file(tmp_file.name) with Path(tmp_jpeg_file.name).open("r", encoding="utf-8") as tmp_file: image_r = Image.from_file(tmp_file.name) - assert image == image_r + _assert_width_height_channel(image, image_r) @pytest.mark.parametrize( "resource_path", @@ -240,6 +258,18 @@ class TestProperties: 1, 3, ), + ( + _white_square_png_path, + 1, + 1, + 3, + ), + ( + _plane_jpg_path, + 568, + 320, + 3, + ), ( _plane_png_path, 568, @@ -252,8 +282,28 @@ class TestProperties: 5, 4, ), + ( + _grayscale_jpg_path, + 16, + 16, + 1, + ), + ( + _grayscale_png_path, + 16, + 16, + 1, + ), + ], + ids=[ + "[3,1,1]" + _white_square_jpg_id, + "[3,1,1]" + _white_square_png_id, + "[4,568,320]" + _plane_jpg_id, + "[3,568,320]" + _plane_png_id, + "[4,568,320]" + _rgba_png_id, + "[1,16,16]" + _grayscale_jpg_id, + "[1,16,16]" + _grayscale_png_id, ], - ids=["[3,1,1]" + _white_square_jpg_id, "[4,568,320]" + _plane_png_id, "[4,568,320]" + _rgba_png_id], ) def test_should_return_image_properties( self, @@ -356,8 +406,7 @@ def test_should_return_resized_image( new_image = image.resize(new_width, new_height) assert new_image.width == new_width assert new_image.height == new_height - assert image.width != new_width - assert image.height != new_height + assert image.channel == new_image.channel assert image != new_image assert new_image == snapshot_png @@ -387,6 +436,7 @@ def test_convert_to_grayscale(self, resource_path: str, snapshot_png: SnapshotAs image = Image.from_file(resolve_resource_path(resource_path), device) grayscale_image = image.convert_to_grayscale() assert grayscale_image == snapshot_png + _assert_width_height_channel(image, grayscale_image) @pytest.mark.parametrize("device", _test_devices(), ids=_test_devices_ids()) @@ -404,8 +454,9 @@ def test_should_return_cropped_image( ) -> None: _skip_if_device_not_available(device) image = Image.from_file(resolve_resource_path(resource_path), device) - image = image.crop(0, 0, 100, 100) - assert image == snapshot_png + image_cropped = image.crop(0, 0, 100, 100) + assert image_cropped == snapshot_png + assert image_cropped.channel == image.channel @pytest.mark.parametrize("device", _test_devices(), ids=_test_devices_ids()) @@ -421,6 +472,7 @@ def test_should_flip_vertically(self, resource_path: str, snapshot_png: Snapshot image_flip_v = image.flip_vertically() assert image != image_flip_v assert image_flip_v == snapshot_png + _assert_width_height_channel(image, image_flip_v) @pytest.mark.parametrize( "resource_path", @@ -452,6 +504,7 @@ def test_should_flip_horizontally( image_flip_h = image.flip_horizontally() assert image != image_flip_h assert image_flip_h == snapshot_png + _assert_width_height_channel(image, image_flip_h) @pytest.mark.parametrize( "resource_path", @@ -470,8 +523,8 @@ class TestBrightness: @pytest.mark.parametrize("factor", [0.5, 10], ids=["small factor", "large factor"]) @pytest.mark.parametrize( "resource_path", - [_plane_jpg_path, _plane_png_path], - ids=[_plane_jpg_id, _plane_png_id], + [_plane_jpg_path, _plane_png_path, _grayscale_png_path, _grayscale_jpg_path], + ids=[_plane_jpg_id, _plane_png_id, _grayscale_png_id, _grayscale_jpg_id], ) def test_should_adjust_brightness( self, @@ -485,6 +538,7 @@ def test_should_adjust_brightness( image_adjusted_brightness = image.adjust_brightness(factor) assert image != image_adjusted_brightness assert image_adjusted_brightness == snapshot_png + _assert_width_height_channel(image, image_adjusted_brightness) @pytest.mark.parametrize( "resource_path", @@ -541,6 +595,7 @@ def test_should_add_noise( image = Image.from_file(resolve_resource_path(resource_path), device) image_noise = image.add_noise(standard_deviation) assert image_noise == snapshot_png + _assert_width_height_channel(image, image_noise) @pytest.mark.parametrize( "standard_deviation", @@ -572,8 +627,8 @@ class TestAdjustContrast: @pytest.mark.parametrize("factor", [0.75, 5], ids=["small factor", "large factor"]) @pytest.mark.parametrize( "resource_path", - [_plane_jpg_path, _plane_png_path], - ids=[_plane_jpg_id, _plane_png_id], + [_plane_jpg_path, _plane_png_path, _grayscale_jpg_path, _grayscale_png_path], + ids=[_plane_jpg_id, _plane_png_id, _grayscale_jpg_id, _grayscale_png_id], ) def test_should_adjust_contrast( self, @@ -587,6 +642,7 @@ def test_should_adjust_contrast( image_adjusted_contrast = image.adjust_contrast(factor) assert image != image_adjusted_contrast assert image_adjusted_contrast == snapshot_png + _assert_width_height_channel(image, image_adjusted_contrast) @pytest.mark.parametrize( "resource_path", @@ -619,8 +675,8 @@ class TestAdjustColor: @pytest.mark.parametrize("factor", [2, 0.5, 0], ids=["add color", "remove color", "gray"]) @pytest.mark.parametrize( "resource_path", - _test_images_all(), - ids=_test_images_all_ids(), + [_plane_jpg_path, _plane_png_path, _rgba_png_path, _white_square_jpg_path, _white_square_png_path], + ids=[_plane_jpg_id, _plane_png_id, _rgba_png_id, _white_square_jpg_id, _white_square_png_id], ) def test_should_adjust_colors( self, @@ -640,7 +696,7 @@ def test_should_adjust_colors( _test_images_all(), ids=_test_images_all_ids(), ) - def test_should_not_adjust_colors(self, resource_path: str, device: Device) -> None: + def test_should_not_adjust_colors_factor_1(self, resource_path: str, device: Device) -> None: _skip_if_device_not_available(device) with pytest.warns( UserWarning, @@ -650,6 +706,21 @@ def test_should_not_adjust_colors(self, resource_path: str, device: Device) -> N image_adjusted_color_balance = image.adjust_color_balance(1) assert image == image_adjusted_color_balance + @pytest.mark.parametrize( + "resource_path", + [_grayscale_png_path, _grayscale_jpg_path], + ids=[_grayscale_png_id, _grayscale_jpg_id], + ) + def test_should_not_adjust_colors_channel_1(self, resource_path: str, device: Device) -> None: + _skip_if_device_not_available(device) + with pytest.warns( + UserWarning, + match="Color adjustment will not have an affect on grayscale images with only one channel", + ): + image = Image.from_file(resolve_resource_path(resource_path), device) + image_adjusted_color_balance = image.adjust_color_balance(0.5) + assert image == image_adjusted_color_balance + @pytest.mark.parametrize( "resource_path", _test_images_all(), @@ -678,6 +749,7 @@ def test_should_return_blurred_image( image = Image.from_file(resolve_resource_path(resource_path), device=device) image_blurred = image.blur(2) assert image_blurred == snapshot_png + _assert_width_height_channel(image, image_blurred) @pytest.mark.parametrize("device", _test_devices(), ids=_test_devices_ids()) @@ -685,8 +757,8 @@ class TestSharpen: @pytest.mark.parametrize("factor", [0, 0.5, 10], ids=["zero factor", "small factor", "large factor"]) @pytest.mark.parametrize( "resource_path", - [_plane_jpg_path, _plane_png_path], - ids=[_plane_jpg_id, _plane_png_id], + [_plane_jpg_path, _plane_png_path, _grayscale_jpg_path, _grayscale_png_path], + ids=[_plane_jpg_id, _plane_png_id, _grayscale_jpg_id, _grayscale_png_id], ) def test_should_sharpen( self, @@ -700,6 +772,7 @@ def test_should_sharpen( image_sharpened = image.sharpen(factor) assert image != image_sharpened assert image_sharpened == snapshot_png + _assert_width_height_channel(image, image_sharpened) @pytest.mark.parametrize( "resource_path", @@ -736,6 +809,7 @@ def test_should_invert_colors(self, resource_path: str, snapshot_png: SnapshotAs image = Image.from_file(resolve_resource_path(resource_path), device) image_inverted_colors = image.invert_colors() assert image_inverted_colors == snapshot_png + _assert_width_height_channel(image, image_inverted_colors) @pytest.mark.parametrize("device", _test_devices(), ids=_test_devices_ids()) @@ -755,6 +829,7 @@ def test_should_return_clockwise_rotated_image( image = Image.from_file(resolve_resource_path(resource_path), device) image_right_rotated = image.rotate_right() assert image_right_rotated == snapshot_png + assert image.channel == image_right_rotated.channel @pytest.mark.parametrize( "resource_path", @@ -771,6 +846,7 @@ def test_should_return_counter_clockwise_rotated_image( image = Image.from_file(resolve_resource_path(resource_path), device) image_left_rotated = image.rotate_left() assert image_left_rotated == snapshot_png + assert image.channel == image_left_rotated.channel @pytest.mark.parametrize( "resource_path", @@ -804,3 +880,23 @@ def test_should_be_original(self, resource_path: str, device: Device) -> None: assert image == image_right_left_rotated assert image == image_left_l_l_l_l assert image == image_left_r_r_r_r + + +@pytest.mark.parametrize("device", _test_devices(), ids=_test_devices_ids()) +class TestFindEdges: + @pytest.mark.parametrize( + "resource_path", + _test_images_all(), + ids=_test_images_all_ids(), + ) + def test_should_return_edges_of_image( + self, + resource_path: str, + snapshot_png: SnapshotAssertion, + device: Device, + ) -> None: + _skip_if_device_not_available(device) + image = Image.from_file(resolve_resource_path(resource_path), device=device) + image_edges = image.find_edges() + assert image_edges == snapshot_png + _assert_width_height_channel(image, image_edges)