Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified Tests/images/morph_a.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 16 additions & 17 deletions Tests/test_imagemorph.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,10 @@ def string_to_img(image_string: str) -> Image.Image:
rows = [s for s in image_string.replace(" ", "").split("\n") if len(s)]
height = len(rows)
width = len(rows[0])
im = Image.new("L", (width, height))
for i in range(width):
for j in range(height):
c = rows[j][i]
v = c in "X1"
im.putpixel((i, j), v)

im = Image.new("1", (width, height))
for x in range(width):
for y in range(height):
im.putpixel((x, y), rows[y][x] in "X1")
return im


Expand All @@ -42,10 +39,10 @@ def img_to_string(im: Image.Image) -> str:
"""Turn a (small) binary image into a string representation"""
chars = ".1"
result = []
for r in range(im.height):
for y in range(im.height):
line = ""
for c in range(im.width):
value = im.getpixel((c, r))
for x in range(im.width):
value = im.getpixel((x, y))
assert not isinstance(value, tuple)
assert value is not None
line += chars[value > 0]
Expand Down Expand Up @@ -165,10 +162,12 @@ def test_edge() -> None:
)


def test_corner() -> None:
@pytest.mark.parametrize("mode", ("1", "L"))
def test_corner(mode: str) -> None:
# Create a corner detector pattern
mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "4:(00. 01. ...)->1"])
count, Aout = mop.apply(A)
image = A.convert(mode) if mode == "L" else A
count, Aout = mop.apply(image)
assert count == 5
assert_img_equal_img_string(
Aout,
Expand All @@ -184,7 +183,7 @@ def test_corner() -> None:
)

# Test the coordinate counting with the same operator
coords = mop.match(A)
coords = mop.match(image)
assert len(coords) == 4
assert tuple(coords) == ((2, 2), (4, 2), (2, 4), (4, 4))

Expand Down Expand Up @@ -232,14 +231,14 @@ def test_negate() -> None:


def test_incorrect_mode() -> None:
im = hopper("RGB")
im = hopper()
mop = ImageMorph.MorphOp(op_name="erosion8")

with pytest.raises(ValueError, match="Image mode must be L"):
with pytest.raises(ValueError, match="Image mode must be 1 or L"):
mop.apply(im)
with pytest.raises(ValueError, match="Image mode must be L"):
with pytest.raises(ValueError, match="Image mode must be 1 or L"):
mop.match(im)
with pytest.raises(ValueError, match="Image mode must be L"):
with pytest.raises(ValueError, match="Image mode must be 1 or L"):
mop.get_on_pixels(im)


Expand Down
14 changes: 7 additions & 7 deletions src/PIL/ImageMorph.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ def apply(self, image: Image.Image) -> tuple[int, Image.Image]:
msg = "No operator loaded"
raise Exception(msg)

if image.mode != "L":
msg = "Image mode must be L"
if image.mode not in ("1", "L"):
msg = "Image mode must be 1 or L"
raise ValueError(msg)
outimage = Image.new(image.mode, image.size, None)
count = _imagingmorph.apply(bytes(self.lut), image.getim(), outimage.getim())
Expand All @@ -226,19 +226,19 @@ def match(self, image: Image.Image) -> list[tuple[int, int]]:
msg = "No operator loaded"
raise Exception(msg)

if image.mode != "L":
msg = "Image mode must be L"
if image.mode not in ("1", "L"):
msg = "Image mode must be 1 or L"
raise ValueError(msg)
return _imagingmorph.match(bytes(self.lut), image.getim())

def get_on_pixels(self, image: Image.Image) -> list[tuple[int, int]]:
"""Get a list of all turned on pixels in a binary image
"""Get a list of all turned on pixels in a 1 or L mode image.

Returns a list of tuples of (x,y) coordinates
of all matching pixels. See :ref:`coordinate-system`."""

if image.mode != "L":
msg = "Image mode must be L"
if image.mode not in ("1", "L"):
msg = "Image mode must be 1 or L"
raise ValueError(msg)
return _imagingmorph.get_on_pixels(image.getim())

Expand Down
Loading