Skip to content

Commit

Permalink
feat: visualize list of FSWs (#11)
Browse files Browse the repository at this point in the history
* add ability to visualize series of FSWs (#1)

* add function

* fix workflow checks

* update vertical image test

* combine workflow and add testing with multiple version

* fix: for 3.10 python

* diable too-many-positional-arguments for 3.10 and 3.12

* fix workflow

* clean

* refactor

* fix: type check

* add gap and center

* add hello world

* add pylint exclusion
  • Loading branch information
bipinkrish authored Oct 19, 2024
1 parent eaa83cb commit 93ae908
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
python-version: '3.8'

- name: Install Requirements
run: pip install .[dev]
run: pip install .[dev,mouthing,server]

- name: Lint Code
run: pylint signwriting
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
python-version: '3.8'

- name: Install Requirements
run: pip install .[dev]
run: pip install .[dev,mouthing,server]

- name: Test Code
run: pytest signwriting
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ mouthing = [
"epitran",
"g2pk"
]
server = [
# For API server
"flask",
"Flask-RESTful",
]

[tool.yapf]
based_on_style = "google"
Expand All @@ -33,6 +38,8 @@ disable = [
"C0114", # Missing module docstring
"C0115", # Missing class docstring
"C0116", # Missing function or method docstring
"C3001", # Lambda expression assigned to a variable
"R0917", # Too many positional arguments
]
good-names = ["i", "f", "x", "y"]

Expand Down
2 changes: 1 addition & 1 deletion signwriting/tokenizer/base_tokenizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

class BaseTokenizer:

# pylint: disable=too-many-arguments,too-many-instance-attributes
# pylint: disable=too-many-arguments, too-many-instance-attributes
def __init__(self,
tokens: List[str],
starting_index=None,
Expand Down
3 changes: 2 additions & 1 deletion signwriting/utils/join_signs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from collections import namedtuple
from typing import List

from signwriting.formats.fsw_to_sign import fsw_to_sign
from signwriting.formats.sign_to_fsw import sign_to_fsw
Expand Down Expand Up @@ -59,7 +60,7 @@ def join_signs_horizontal(*fsws: str, spacing: int = 0):
Point = namedtuple("Point", ["x", "y"])


def sign_from_symbols(symbols: list[SignSymbol], fix_x=True, fix_y=True) -> Sign:
def sign_from_symbols(symbols: List[SignSymbol], fix_x=True, fix_y=True) -> Sign:
min_p = Point(x=999, y=999)
max_p = Point(x=0, y=0)
for symbol in symbols:
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added signwriting/visualizer/test_assets/vertical.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions signwriting/visualizer/test_visualize.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ def test_image_with_fill_and_embedded_color(self):
fill_color=(123,234,0,255))
self.assert_image_equal_with_reference(fsw, image)

def test_layout_signwriting(self):
fsw_list = ["AS14c20S27106M518x529S14c20481x471S27106503x489",
"AS18701S1870aS2e734S20500M518x533S1870a489x515S18701482x490S20500508x496S2e734500x468"] # Hello World

for direction in ["horizontal", "vertical"]:
image = signwriting_to_image(fsw_list, direction=direction)
self.assert_image_equal_with_reference(direction, image)


if __name__ == '__main__':
unittest.main()
39 changes: 36 additions & 3 deletions signwriting/visualizer/visualize.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from functools import lru_cache
from pathlib import Path
from typing import Tuple
from typing import Tuple, List, Literal, Union

from PIL import Image, ImageDraw, ImageFont

Expand All @@ -26,9 +26,17 @@ def get_symbol_size(symbol: str):


# pylint: disable=too-many-locals, too-many-arguments
def signwriting_to_image(fsw: str, antialiasing=True, trust_box=True, embedded_color=False,
def signwriting_to_image(fsw: Union[str, List[str]], antialiasing=True, trust_box=True, embedded_color=False,
line_color: RGBA = (0, 0, 0, 255),
fill_color: RGBA = (255, 255, 255, 255)) -> Image:
fill_color: RGBA = (255, 255, 255, 255),
direction: Literal["horizontal", "vertical"] = "horizontal") -> Image.Image:
if isinstance(fsw, list):
images = [
signwriting_to_image(fsw_string, antialiasing, trust_box, embedded_color, line_color, fill_color)
for fsw_string in fsw
]
return layout_signwriting(images, direction)

sign = fsw_to_sign(fsw)
if len(sign['symbols']) == 0:
return Image.new('RGBA', (1, 1), (0, 0, 0, 0))
Expand Down Expand Up @@ -65,3 +73,28 @@ def signwriting_to_image(fsw: str, antialiasing=True, trust_box=True, embedded_c
font=line_font, embedded_color=embedded_color)

return img


def layout_signwriting(images: List[Image.Image], direction: str) -> Image.Image:
GAP = 20

if direction == "horizontal":
max_height = max(img.height for img in images)
total_width = sum(img.width for img in images) + GAP * (len(images) - 1)
size = (total_width, max_height)
paste_position = lambda offset, img: (offset, (max_height - img.height) // 2)
offset_increment = lambda img: img.width + GAP
else:
max_width = max(img.width for img in images)
total_height = sum(img.height for img in images) + GAP * (len(images) - 1)
size = (max_width, total_height)
paste_position = lambda offset, img: ((max_width - img.width) // 2, offset)
offset_increment = lambda img: img.height + GAP

layout_image = Image.new("RGBA", size, (255, 255, 255, 0))
offset = 0
for img in images:
layout_image.paste(img, paste_position(offset, img))
offset += offset_increment(img)

return layout_image

0 comments on commit 93ae908

Please sign in to comment.