From b252627d1f24abfe424f925e8fb2bd5133a87655 Mon Sep 17 00:00:00 2001 From: Bipin Date: Fri, 18 Oct 2024 16:01:19 +0530 Subject: [PATCH] add ability to visualize series of FSWs (#1) * add function * fix workflow checks * update vertical image test --- .github/workflows/lint.yaml | 2 +- .github/workflows/test.yaml | 2 +- pyproject.toml | 5 +++ signwriting/utils/join_signs.py | 3 +- .../visualizer/test_assets/horizontal.png | Bin 0 -> 2897 bytes .../visualizer/test_assets/vertical.png | Bin 0 -> 2813 bytes signwriting/visualizer/test_visualize.py | 11 +++++- signwriting/visualizer/visualize.py | 36 +++++++++++++++++- 8 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 signwriting/visualizer/test_assets/horizontal.png create mode 100644 signwriting/visualizer/test_assets/vertical.png diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 3b0ff89..7dd523f 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -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 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 1afeb29..7936df2 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -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 diff --git a/pyproject.toml b/pyproject.toml index cc8ccb9..931544a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,11 @@ mouthing = [ "epitran", "g2pk" ] +server = [ + # For API server + "flask", + "Flask-RESTful", +] [tool.yapf] based_on_style = "google" diff --git a/signwriting/utils/join_signs.py b/signwriting/utils/join_signs.py index 8db2cda..e63e940 100644 --- a/signwriting/utils/join_signs.py +++ b/signwriting/utils/join_signs.py @@ -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 @@ -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: diff --git a/signwriting/visualizer/test_assets/horizontal.png b/signwriting/visualizer/test_assets/horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..ed2b203ad83f7243d56962e662f72435b581cb0d GIT binary patch literal 2897 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 vWAz7~0e*idI literal 0 HcmV?d00001 diff --git a/signwriting/visualizer/test_assets/vertical.png b/signwriting/visualizer/test_assets/vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..db22c3037e4cd31501e00f7d582eddbb5b97a8a8 GIT binary patch literal 2813 zcmVZpG}W1~Bu$<$ z4A=nN1hfEUs(RS>iW5{?JV8}Y0W*O2fl^?DZ6aBrbTtQ5^*AsM;|brwfEbmo`g>E_ zAONW95uhCS2)GtlFCxR!X+tcf6#{^&9t5TUp8_`k>qKN|y6uQo+93d_>Zia|;1F;t z@OKdzoC#YXLl6K|^+Qb4I11bjyecAvnXtt(2qH38M1IqkE2^sh2JQe(V1T?VB7?lL zDPgH<$_W??v;hh{k;MMD0H^H!e+BZquq)yEJpfPwd}vQ#8!$A<<2-JUp}_M%PQQQv z6a)XVhHnRkCwZK?Kqv}=0>8&bv{?%Q7zOOI2JZkyCV8B@fS?0FBt4t85P;!8lQncV zaDI}ov4;HzxG+fow*V&r zUA1aev|0$#TUd;v^M62K(jD?sPWnX@+( z3aL}UU@$mq)~xL=5W>J5FCp|AHj79eum-5Gn|`UP`+D1_7oD;Y2!%rJYRN<^FE1}| z&6+jeuBfPJ>g6~A%*F6dyrwzwYF%1uYHE6PkkMMbdi4fd-)W%I4*)SC0IOU8MAA{4IBZq zuCDGqCxAEKd~=h2@7nDLfh$u0aWgi0T)A>(_+>RMlF7O+`83@2KHvqM@wOgaSRm0)1*3{Iz69pm_kN7@z9Fdcg6T-v-i_-zX z*3Vp9X1;?uSat#I0;s z#^xtvlLjC#009_)06<;|j`0p4 zdTRbA$N!scbD7h(Mwnf4gD}mJ-|finwZAueVoiqR2H|Q){zFIpWBYrZH|AtUZnwxG zj{HGK{s{0pOn=dDjSko{&!h zukda1e5##asn^GABJvS1A!^f5Rc%kL0cM}vI>s(X-WfL_BA@Y|(U0W@q1BO};K+Z|{Ihm0ggg5Bv>XRM+m)qZ0J+mkS>J@^jb^yPQ+H|RiOa}8YC@>Rf zR@Ke^nV1H-hLmOy75V5ZGDm44@E&GVIVsZ-pRW;PME3Lkr-1KbJ_QV79<{Ad)xGie z>>u*|t+ZV+<0aq)RejFa%953zZicyq?#DEvQ@|xIbllj9>N;nE zmX?+WCQh7~&^ky54jdRhX3Uu7eK)mNrFt=XNJPd1hg9{<1EW052jDjXuZhS)RsEA= zzdJEY0A*CIt*!T6cG+dI9`Bu_co#!NZo@2G(<~x)ML^_XKL1$_%me-?BE_ouw0Guv zqr$?%O3VUPNl8TR0{#pXU|uigV;>*psClVc4LpZ=RQ8mJT#%~KUMn{@H|g7$h*SeF zV*qRdDxz=QIRL5}R@EBd>FDiARFuyws-U32IoI)wLZMLZ(W6Jt2VMhy7;h+>wDC5iR@ME$m3AAz7tY(W9R^$+qim0b zWeR~!_uO;O>)~*?U1KN^2%MfWWy&t#N#K#Pva;=+otk&*#mLPo>Oor@b0o@%U)B}P6vRlnKNhZ1fGd1|J(BN^7mqZ2rpm0 zd;@0USD}X|oe%s25}I3`c#2WcD4_ZN`|p1#0wNFy1S=~mcL0ANYE^AapR#89^y%*e z0)dke01rO+;5y8rw&(e9^`qB|bxThIkMtRWt*8iizqYpam5z>%Qxz2zyD@!6Zk((0 z%8VH^ws&-NoT{s<+lX1xe3;h&oF40Pay>k@&k*d6#lZWcM~^;i+jW79oBqX?-35&D z3xLyO Image: + images = [ + signwriting_to_image(fsw_string, antialiasing, trust_box, embedded_color, line_color, fill_color) + for fsw_string in fsw_list + ] + + if direction == "horizontal": + max_height = max(img.height for img in images) + total_width = sum(img.width for img in images) + size = (total_width, max_height) + paste_position = lambda offset: (offset, 0) + offset_increment = lambda img: img.width + else: + max_width = max(img.width for img in images) + total_height = sum(img.height for img in images) + size = (max_width, total_height) + paste_position = lambda offset: (0, offset) + offset_increment = lambda img: img.height + + final_image = Image.new("RGBA", size, (255, 255, 255, 0)) + offset = 0 + for img in images: + final_image.paste(img, paste_position(offset)) + offset += offset_increment(img) + + return final_image