From a7ca855014226ae597577862002199d0c9563bf9 Mon Sep 17 00:00:00 2001 From: Fisch Date: Thu, 11 Jan 2018 23:46:46 +0100 Subject: [PATCH] add simulator and client image sender with 2 bit per pixel capability --- .../__pycache__/matrixSender.cpython-35.pyc | Bin 0 -> 3286 bytes client_sw/images.py | 37 ++++ client_sw/images/160_144/grauverlauf.png | Bin 0 -> 14006 bytes client_sw/images/160_144/pokemon1.png | Bin 0 -> 1812 bytes client_sw/images/160_48/Spaceinvaders.png | Bin 0 -> 368 bytes client_sw/images/160_48/black.png | Bin 0 -> 179 bytes client_sw/images/160_48/chaoswest.png | Bin 0 -> 712 bytes client_sw/images/160_48/ctdo_logo.png | Bin 0 -> 474 bytes client_sw/images/160_48/kirby.png | Bin 0 -> 1068 bytes client_sw/images/160_48/kirbyboss.png | Bin 0 -> 1006 bytes client_sw/images/160_48/mario.png | Bin 0 -> 530 bytes client_sw/images/160_48/nyancat.png | Bin 0 -> 1283 bytes .../images/160_48/pokemon_wildpidgey.png | Bin 0 -> 904 bytes client_sw/images/160_48/schlange.png | Bin 0 -> 656 bytes client_sw/images/160_48/tetris.png | Bin 0 -> 986 bytes client_sw/images/160_48/troll.png | Bin 0 -> 2354 bytes client_sw/images/160_48/tuwat.png | Bin 0 -> 494 bytes client_sw/images/160_48/white.png | Bin 0 -> 232 bytes client_sw/images/160_48/zelda.png | Bin 0 -> 1146 bytes client_sw/matrixSender.py | 93 ++++++++++ client_sw/matrixsimulator.py | 159 ++++++++++++++++++ 21 files changed, 289 insertions(+) create mode 100644 client_sw/__pycache__/matrixSender.cpython-35.pyc create mode 100644 client_sw/images.py create mode 100644 client_sw/images/160_144/grauverlauf.png create mode 100644 client_sw/images/160_144/pokemon1.png create mode 100644 client_sw/images/160_48/Spaceinvaders.png create mode 100644 client_sw/images/160_48/black.png create mode 100644 client_sw/images/160_48/chaoswest.png create mode 100644 client_sw/images/160_48/ctdo_logo.png create mode 100644 client_sw/images/160_48/kirby.png create mode 100644 client_sw/images/160_48/kirbyboss.png create mode 100644 client_sw/images/160_48/mario.png create mode 100644 client_sw/images/160_48/nyancat.png create mode 100644 client_sw/images/160_48/pokemon_wildpidgey.png create mode 100644 client_sw/images/160_48/schlange.png create mode 100644 client_sw/images/160_48/tetris.png create mode 100644 client_sw/images/160_48/troll.png create mode 100644 client_sw/images/160_48/tuwat.png create mode 100644 client_sw/images/160_48/white.png create mode 100644 client_sw/images/160_48/zelda.png create mode 100644 client_sw/matrixSender.py create mode 100644 client_sw/matrixsimulator.py diff --git a/client_sw/__pycache__/matrixSender.cpython-35.pyc b/client_sw/__pycache__/matrixSender.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67ba09ea038dde6628715b317ebcd2668acfaef5 GIT binary patch literal 3286 zcmZ`*-EJGl6+W}SBu!ejBulcLv~=nw-KG%TICfgsQ0rKBA~<1;$c2Dyjm46?qE;ez zso7O5u_98`ZX5KbDEb2JRna#n&^MW@0==nTAveu;W=Z|kU2@N!otd3EKi~Og78;G( zga2&!f2$Jxn@(L8^q=9*{{Ru;FQ`v65abIQ7~~r?Fv&MbaGybai+oFugKm>=Pj!cU zXR5p8yHmYFer2jx$*)cI3*-}h6qyuR^a@j36xZn`mTK@a>z;iCd&o1Dy*3DYv8w9F zstjLD)W=y`w7WcLdL6s+C0b%)4`4JrfKTuM)3WI%g)n-7BA5#+EA$HO(5n>H*b+AV z0!4ML!*tklQR^6hNoFXzM6WO*Jh@EKtnR}2If~}BUZ>~^>|a#%Ps2hc`|EKU#Zn5` zbo5_{$47r*^%e_m?Aj1~@zccp5O+R+I23e96c80q407=L2Xp{c*M=@2?v94cJecD1Z%S*4eT?$Rk)_sn)eBxrPFn8~8K73R$%Yj)yh zk`~P{jhZXXyLax~zT3QU!@Hm=!Co}n%JM>4#lbLECPu01GpLWG%w*Zm6RB#D40=JH zjAB*qBt<@q1wR#X)DuN(o52?A9M@Z5AqkSZa<0BBF{F97om(><*+h+%fkcs6eMX<1i=C)=pqCeRq-uR z7gbR;s>bNb>4Yy&M|TY#iHqUMIoA1IgMti>bsoni?cb$B7Z~!m`uux@CghkAVA552 zPeV^KWx~Z*eOF6%ATv2c?dGBRD78Mry!~}1eHPBvw zI5gudA+8APeZY`mb|ytkR_kmj7sMn*bxskMo8;gGW^nlihAFXs(xzRP-$8SWr+IzI z!7R_R50ipp{JM~j>|fow*BL82VkYt&%M3l<4SE@@I5o2b{iDq;Z~~ zPa8IpG-58vXW1@`iEY++-*m(^V?kW8Mwidj8IL|LFLuwut<&`*C>(@oRiUEzRTmYu z;<9YG1<{1GnFEoPGFGDPIr6)hL9!Lt1F=kzDVupWmkbNZ8;fU_gmGIBD(U8&Ly}4M z3GSRNBQbNHq))<1I{G3@?<7lxfd`yVjuR-d=@uA_IC9RQ}qzQ9djMgyQReJ^vr z+n^1`qNWzWZ3njhnlT0x;zL$&+5*2!$1DMl;1!S!M?~*^93X(Hd@bXJQwlH+$TBVI z2-dW`a3+pUTZtc*VB<|A;k`$`1I??$Zs=U+(u44wt-JuLN{N%yICq9&okJp|(@*BmLjKfIo zr75^eUgZg!EHuiv!XzVB!$q#JcH)KB*cHjhXyDH0A?gP9ebX^#FV@|b4%? zT~y}NwNE4ywbV7w*prtb{7MIBsl1yc%1APt3X?&s3>o`2NOpKorlO9Im-RXRvth2B ftiwk$J@e~~QkDB<6jnIJIiK_1KxB`9M&0@bk+i9B literal 0 HcmV?d00001 diff --git a/client_sw/images.py b/client_sw/images.py new file mode 100644 index 0000000..f6ab70e --- /dev/null +++ b/client_sw/images.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +import time +from PIL import Image, ImageDraw, ImageFont +from matrixSender import MatrixSender +import time +import sys +from random import randint + +matrix = MatrixSender(udphost="localhost", udpport=2323, img_size=(160,24*6), bitsperpixel=2) + + +def send_img_from_filename(imgfilename,invert=False): + background = Image.new("RGBA", matrix._img_size, MatrixSender.C_BLACK) + image = Image.open(imgfilename) + image = image.convert(mode='RGBA') + image = image.resize(matrix._img_size) + image.save('/tmp/send2.png', 'PNG') + background.paste(image, box=(0,0), mask=None) + background.save('/tmp/send.png', 'PNG') + + matrix.send(background,invert) + +def send_img(img): + background = Image.new("RGBA", matrix._img_size, MatrixSender.C_BLACK) + stream = io.BytesIO(img) + image = Image.open(stream) + image = image.convert(mode='RGBA') + image = image.resize(matrix._img_size) + image.save('/tmp/send2.jpeg', 'JPEG') + background.paste(image, box=(0,0), mask=None) + background.save('/tmp/send.jpeg', 'JPEG') + + matrix.send(background) + +if __name__ == '__main__': + if len(sys.argv)>1: + send_img_from_filename(sys.argv[1]) diff --git a/client_sw/images/160_144/grauverlauf.png b/client_sw/images/160_144/grauverlauf.png new file mode 100644 index 0000000000000000000000000000000000000000..4e84818ddacaea569e3c11a55caac9f96361e828 GIT binary patch literal 14006 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 literal 0 HcmV?d00001 diff --git a/client_sw/images/160_144/pokemon1.png b/client_sw/images/160_144/pokemon1.png new file mode 100644 index 0000000000000000000000000000000000000000..9c8d1b97d70cb7613ea2b91a90a2f8154c144898 GIT binary patch literal 1812 zcma)-X*3&%0);cFrAq9Ltr|1diqupw_SVt`gHpAnDq|n}jGbwXU=*RMmLitg*NP>U zWEw)Bs#HXfL{X+yYhq0-jqtp`@4O%HobTRy?m74W&A4ZO2XsOH0ssI2S>LsCI?Kv4 z<(>zgIe>mZ2LJ?St*y+RmVao;+8qk7?k^61n;HJtX-zMtg+h#NSk`m94z zi3G67`GdDEf_OgJUFg-O?B!pHq^%f*F)aTVoOSJ^U0`rG9}ls@{AnVDE&LiNV1%AD z11nxnKt_6!WsJs_^KjX|?e5>AJ-xiV5ju9poY$NSO*+;esmZ#3nBHuWAIkD@~IBGov=JwS5V zx&MQ`L)fJ`<+fvt08l})#*Q9?sz^bl_Fr7vwEk^46 zgV-UIESP!eh0+F#73yBd%vvKe z&XfM^nb7VaAp=EF#gWYI%}^3Z|^a?`|*67AUIE%tqvd9hVC9PK&(qrro8i}xt77F7LM#kiAg z;mZ{%ATQiH^p|Ufav|5G4G!s3$P|{qQgS(B25h+pTKKI=b>6&%tFOyeB@vSHc(MLn zi;{x`8dIu;w|Sox+aOPX-)alih`>0mXZUR?#Kp&F=!w|23nefUtP&DS@|w64rHu~^Bg_UL`V63VRVjb zMJW8UC!_Ke`>O`tY%t1^4M=_JA&bsrzma><9w>i{Zovz~d=VZ~f)@L`Ts@7ynovxYB^p%1bk3y>4;?PW*}Q^t07Ig9OHSd-Xd1vU6uhVk{^1b zPjU7Yo3>3PuOWyDvv#JFYgzp7BT(s~uH6@XlvhS^2~FnPJ_n&i!d7IvaBE6mw}7 z`nIsyX0Z)aK^Nr(iSS(J5V4rZu}LZ2$(OM8qDJsx?*R;ko@W0A@x$Ze=W^G4@DmT# zX|#UfKeo+6(pB~!cuO8s;y|3>1`Gl}vCO7TIyU7mcAm{ky28{}B%<{=&}9DRyDJ`n z3By?LDOy{-x5~z$3CLy}?^@hSBom%uELFjrPW7Uj(w@owA~o)wemragU-up%ieou_ zb3@2**3@As1-7hJ4k_S&_P&9FP5r&jWjqyk8_iv$0tQW(=R+h6>nS^0LGQkgb>1il z5O>5EH>|XTuauzS z{4R91oRN`2In2Zuon)Vmk}V@2!&XHm!ucoFO3H3ucnzH1!Doo3cV09W``eLn8#kq? zdDsjQiPi=|7kUO9|7h3{LHQaA0*(KRdV^}qJ{a6&%CFT&hEnSAypBo1O70?}hp13Q z_H>Q$Sg%|6FA^_=jv9k{F6HO)fx)irU*BlFksJK>v&v7l4JE70_a3EWmrwZ2i%ys) zl|fYsyW)b6Bi=hrXwj=U#Kz$g0KA&d82*%2(L}neIeiXnj%dm?OQj8+*fcb4O$PwZ zDUy>1{s)a@!GJqyQR1dv{jti4j$>&tB!#dwYS&Uqnl1zu5|^`^MfF2I!Ck8f&xY@3 zk#%f4tU2>L7pACrVzg5gu#4TkhMy?)is~k;P3EE<`)Y{7WwEu5D}8@`OjxoV5Zv>n z4XFh;rYR=nFl{HHUzslp4c&h|c`&lz2MdaEZs@1!t*Zao&A(q%_X9)=Qeev-cdXdK zjyQ0?Bv$%-G5gnAY3QtfoY0eO-?6&(>v2b)vrrkKuIcN&zf@>BAS$%RDY;Ty-}sdE o-gd69={A`7n~q|887A`NyFc|HT!wq*;D6rE`j)-bYYPPO->nywasU7T literal 0 HcmV?d00001 diff --git a/client_sw/images/160_48/Spaceinvaders.png b/client_sw/images/160_48/Spaceinvaders.png new file mode 100644 index 0000000000000000000000000000000000000000..958e51247f2cc2c189656bb1bb2ab03c8f990d6f GIT binary patch literal 368 zcmV-$0gwKPP)001xn0{{R3tY_mb00006P)t-s00030 z|No`gpWOfe010qNS#tmY3ljhU3ljkVnw%H_000McNliru;S3!WDhBGR2toh=0R2fs zK~yNu&5%8c!!QtqpD@_Xf?ByruCNC%=qhrxSI9P&(&P-OoT~_YfLy^<(hAbpU_2QG z(s|e}?C1$JpO|0ZKbTH{jekK(D2Spa0zaY*v%@!8{(z-LhS|}>kgV1blygY%ac$B& zytp=xC_(OqlP?xXDHr4h1&Car7=|1QERBT-zff?fMuQ^an_Urp%3O&O4m+?^Ffb|z z&=|DG6MV>WPMu04K)>RLZi>d2CUv3nHdOa}=(?`z4_TL9&GWPkE27cUTG7PX6CH^J zSo+oNIe+iahMMN!X%wL2lV>%|>rjV0<|f4MfY%mW*`Dz`@@|{}KV(nN2>JJYtT?Cu O0000wg9%7Vo_=Ntq&N#aB8wRqxP?KOkzv*x37{Z* ziKnkC`$HaCVJlsZ$oUUJ%1c}$N}Tg^b5rw57@Uhz6H8K46v{J8G8EiBeFMT9`NV;W ybUj@hLn>~)J!r@X001xu1^@s6mZ@=W00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-&w9TX=i^%o&w0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbPLPFM4DVpRwU zArt^&<%E#Z@K`K40vkzpUBBg@Kqq`-a5(pG0EY#e)hm)fweQTv`LJ~WGy!E*t;lQ$ zpaI}lD>4uQ;4OV4AQ3`BDs%)0t7V?g%LER>3JMrjE^W08mI{E6DbWZO>IHze!sh{M zrgY<6u0;t^OB65#hz6q-L@XNs!wPw|(%GwmRPhw7^>x~`T6DS8Y?_Wf5&)ObM21~v zb_{S>usH=E;AK?rj_Uwm(H?J9K<{FO@%&W~0YGZ0V%clWf(#G>;A84^h8WNQP=#y; z$C!#OiZwf?DPUv}8~}@ikQq2D6`Nhl0yzL;wad>nAhFhbl^qAPY&7)r?@)vgvt??^ zXdRr^hGtMu05pdNE!kQF3LyjlL+TVsyV`k#5PHBANZRqptDIC}1@taDwJy1`K<(}I zssUSSYmVsDTI9v{amZ%%yH)oJB!oCE+7n_}jztfcvhDMdDz9a-`zZ?ec<*?nlE4Rm zsRU~YB9XV@0JgXST6e{=?rfi3@mzg2r2L9#FA#V2b_5i9z$J9rn{zW29FMK8NskDC uOIwa?VtEA^$ymAf!XMSR;9}V2-g*Jwkr_y?Nq?*hq}T#{LR|m<{|{t_9=coyq!^RD z-CY5+Ij>!MP|ku_QG`p**uBL&4qCHy}kXl^tlfp{I*uh{pNe%Nz5W4Fni2Y}R?m zDp}fbq(Nc+1w-eh&nDkE6_)?El~4AU=0A~orewC3YCG!!v(U@JMN`=KS;uoQw0&XY z`}l5pv*-K%e!k)zr|vQ=x}%@BW6v~ASv}v0Q}$h!jcYFwnHrZdw`k6dwYrav*}d18 zmhq`?-(&Y{lf5!Fo1M4u?)rD;_0ktYeKPu-`uv3|Q!W&iw5YE(Uc$9p+dXl4$1BBI zEtAeGKbm~BQ>QsUErKaXF?Gqr*ALoV*DXBwyy2f(&o74SS*<5S|5ys-s`h4ws`9w& z3M>_ymfWkJnaV4+%DU+-$9|6E%CC51r2}gIF?YXhzP<5w0bfM${L;QFd$`WJANk*2 zUUEiDX0jsh5`N~3AGWC-S-8`}s?FkFwoK9HcRTi%>|gll`-b|*{L{DWEZF|vx&joc Mp00i_>zopr0I@Q=MgRZ+ literal 0 HcmV?d00001 diff --git a/client_sw/images/160_48/kirby.png b/client_sw/images/160_48/kirby.png new file mode 100644 index 0000000000000000000000000000000000000000..286f9610e55749fbaff3af7374dc26adc986e4e3 GIT binary patch literal 1068 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 literal 0 HcmV?d00001 diff --git a/client_sw/images/160_48/nyancat.png b/client_sw/images/160_48/nyancat.png new file mode 100644 index 0000000000000000000000000000000000000000..dca7c51d751bda7b947fb5af91ccce0a7205b3c3 GIT binary patch literal 1283 zcmV+e1^oJnP)001xu1^@s6mZ@=W00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-&w9TYAmv}%XB0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbReMv+?RCwC$U9n2^KoFk9^Kw_Im2me0K7p0B{ULUO`U1X! zh=m|nh>cGoc$Sv-7B*IbC}I!ce)_7)x=AKChzi157)heOoyc6WD4 z^qfp4!bkDhwxk|#XJ-fc{XYE8f#KaD1S~Hv!`ayxnqC_l8_?-=AP54SJ6H%934DRE=Hr__+$fZI*1lMje8w zz|J9f4nRl+KH1ndeN)MM|hz#qKC)6zx%ks*sC(N>Lo%tG%$G>4P zvyAAvbi*vz0}q%7kZKjAsMcsokjl=-Ibh2`ZDRB)eRNh+xC}!WHhnBnVCbZ~Oy^t4 zrZH>5Sa)q5OxV>qt87&8Q%n+6j`L=riW&h6~Go4OR-%8e44@jBkR5fT>?nn6~oX*yJ%+;64 zWCBqXk=nK~n-Q=dOgG(Npkl;%4~6{zl}=ce8UetYn;Y2L z+Cl^1!^4AB|NHy0rvIvCH)3T5Cri2{7kmH`042h27`eXh*CX#c`k(P8xZ|| zUqn%4-Fm$qs$Si0*I1Wsw=2Rh6sM=B;um+ba(#VWc;1tf6S8l3j7FnB-zh0Nc5iP_ t`&b9f{}0vp*p82nc^(iNvtX85Kq>$L literal 0 HcmV?d00001 diff --git a/client_sw/images/160_48/pokemon_wildpidgey.png b/client_sw/images/160_48/pokemon_wildpidgey.png new file mode 100644 index 0000000000000000000000000000000000000000..8e2f7af7880f454ef518f3c19ef808577035ff9e GIT binary patch literal 904 zcmV;319$w1P)001xu1^@s6mZ@=W00006VoOIv00000 z008+zyMF)x010qNS#tmY3ljhU3ljkVnw%H_000McNliru;S3)aH9DaZX1)Lb02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00QtyL_t(|+U;G@Zp0uA8x{Zm z%k1sMWspEf2xYc3Y2(nf1>+b9T`HxN9{>nKj<{$_sacM(00M3&U9S$vc#bf5_DAv# z!L5htU2>)_u&R&n{Tzr@K3eV}2G33zPbqzVK(f0+^bsL=<_1eC zpZeS_w3HG!gIpH~E=sXW9dpE?pjy8R@JXybfZV_-4*EFY+ea5Me& zoHPnSxHH;@3Bp*=|k1hiMmxq2$2<9@LX@-kd^^kOc5Ih}9HRO{FF;!aZ5yJy^39y=K-%>qF z=AK%Di0_+SPZ6-EZdQH`Ay*%Xqzodfa*q{~?D3_u3ObVX7;$Fx4dmnc#H#$bS+IA5 zO0#5cW_~+bSwpm}SFZj2Xb~ zIW{Fv=%D5D4&4K+2^D_jXBJMhvXxRydD*?He zS+8WWSl6dY);dBUDe352{51;FQuWb)6eFp<=6hD!c)J2xPt8Xje3bw#GPRO9djviu z46ZDFNNM;zQhO_6);yF&$5?c1eG0ENnnzF9?Z_>p_c&??M%!8%P@Kwg#~DI0qOlMS eSbM^ro%sdz2*E$PHZunR0000001xu0ssI28O!E500009a7bBm000XU z000XU0RWnu7ytkO2XskIMF-&w9TOxM8Weeq0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbP3Q0skRCwC$oZD{1APhv;DF6S<^sQR8S%UF}F*|HhzzL?*sS7goE!?`e6lugk$k zx;dHH@hKOw_oWrg`2HudC`Eq-!!DxNi^YlfF{v*+sHHg|wVU7pv4CN#N?*D`<@Dqr z+GjOn?<=I;h}pR`O554;4WgUSpdL3$=bzOw*D=`%^7F2Uc+K&B9LqbmitC8*R)e9u zFuO1g$-#s0k|W|ApBoRTo$04geA`i&pNn-L{J1Gh)^~mzatu=S+=%O7;Z<~ItlrXO z{#5HOgzJc~Z&L7lPbZ;;i*SVCB0=$ni|4v5BT_Db!lrSnv2Z3VS}`T1zE9fWoSD!7b}QNC=TMPOcUa1t;$ qY3pea0iSIwvIv+)z%&A;?Xe%*JcCDb70-460000wJse1 literal 0 HcmV?d00001 diff --git a/client_sw/images/160_48/tetris.png b/client_sw/images/160_48/tetris.png new file mode 100644 index 0000000000000000000000000000000000000000..1ecc545ac10f94e645595e847a23bbd328c5b76f GIT binary patch literal 986 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 literal 0 HcmV?d00001 diff --git a/client_sw/images/160_48/white.png b/client_sw/images/160_48/white.png new file mode 100644 index 0000000000000000000000000000000000000000..64a4803e2459f0a11e97f2fa996593308551093b GIT binary patch literal 232 zcmeAS@N?(olHy`uVBq!ia0vp^3xL>wg9%7Vo_=Ntq&N#aB8wRqxP?KOkzv*x37{Z* ziKnkC`$HaCVJnrwR&`g9@)FmG66gHf+|;}h2Ir#G#FEq$h4Rdj3ZQ3ExHmu%vseNn1hMHHV1l6r)(9wK i#G+Cx;Q-T`*ShC3m}8$#Jn0X#jlt8^&t;ucLK6V_$~_PO literal 0 HcmV?d00001 diff --git a/client_sw/images/160_48/zelda.png b/client_sw/images/160_48/zelda.png new file mode 100644 index 0000000000000000000000000000000000000000..036a21ba9eccb39039fa65ca95e5e5ffaaa8030d GIT binary patch literal 1146 zcmV-=1cm#FP)001xu1^@s6mZ@=W00006VoOIv00000 z008+zyMF)x010qNS#tmY3ljhU3ljkVnw%H_000McNliru;sF5w0|`KNwVMC{02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00ZJlL_t(|+U;CRj_e=|gckR| za%PoL6aoHYo51EtFKH$e+ehzV@tn;&B0pyzv7>ndjs*(?Aem(=zIvVvPp2jK4j4#b<;tZQG%kJ;6K2PF7e7XN^8WZoL4WH|< zD4NJJECuV$m!GBIlxc&omDkYbVBU#NyqU|PjdQcus2!vpV~*a^yn{&|kx*JJF~SaY z7A!HrkvD~U52LrH9fA%orQ=!;7!6>GUk6o=>_$dQpSNMn((XxV&Gqf76{+R?Gwb+I z>f&@SI7|9rWPYI}?H5e5L~z~j1xE#sdK&T-3t^$0N>NC|>}p!hSTouo9^T=`+=tlp zTsS2GCG~L93S+HWJSYO}J*SW`N};ONK8Xpq+B{J<4$?}Rn@jDPLRqIJ38i>iTc9S9 zeyPckB(UFy+AE^bl~*Y_^IPC4S?7!!x6p;UltdwmcK?@Ia~`df4pzf*+K*V_X?>r? zEe|*<=7a#GUKP~RBGmqP+%{`mGIQ{pwZg-;yi0d69Ro5{b-mh8fixpWK%eu@iXEO> zh(bgPo;@P2isVCFOvjj2X#+=zYhd|%tu}2`Jh2*-vyUVJ^dcbEVdi#Td%@tB2N$UI5 zb)E*5gt@Q{95wP^)`5(bKdF6p#d1G;&s|${P|i{*jxog?MJ`0ZmVQBNJ`E}XspdAC z{9>s*hGeHfB}1w;OwSjpP&f(U)1Z<-w9}wcH>iroY-EsGz;n+a M07*qoM6N<$g8Zfg9RL6T literal 0 HcmV?d00001 diff --git a/client_sw/matrixSender.py b/client_sw/matrixSender.py new file mode 100644 index 0000000..6ff413c --- /dev/null +++ b/client_sw/matrixSender.py @@ -0,0 +1,93 @@ +from PIL import Image, ImageDraw, ImageFont +import socket +import binascii +import io +import time +import re +import numpy as np + +import PIL.ImageOps + + + +class MatrixSender(object): + + C_BLACK = 0 + C_WHITE = 255 + + global threadrunning + threadrunning=False + + + def __init__(self, udphost, udpport, img_size=(160,48), bitsperpixel=1): + + self._udphost = udphost + if not type(udpport) is int or udpport > 65536: + raise TypeError('port has to be int and > 65536 !!') + self._udpport = udpport + self._img_size = img_size + + self.bitsperpixel=bitsperpixel + + self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + + + def _list2byte(self, l): + byte = 0 + i = 0 + for i in range(8): + byte += 2**(7-i) if l[i] else 0 + return byte + + def _array2packet(self, a): + return [self._list2byte(a[i*8:i*8+8]) for i in range(int(len(a)/8))] + + def _intToBitlist(self,number): #convert integer number to list of bits, exampe: 1-> [0,1], 2->[1,0] + bitlistvaryinglength=[x for x in "{0:b}".format(number)] + bitlist=np.zeros(self.bitsperpixel,dtype=int) + bitlist[self.bitsperpixel-len(bitlistvaryinglength):]=bitlistvaryinglength + return bitlist + + + def send(self, image,invert=False): #changes slowly 'fadespeed'-pixels at a time + global threadrunning + #if fadespeed=0 -> change instant. + #time to change= 1280/25*0.2 + imgmap = [] + for pixel in image.getdata(): + r, g, b, a = pixel + + pixelbrightness=int( (r+g+b)/3 *(pow(2,self.bitsperpixel)-1) /255 +0.5) + + + if invert: + pixelbrightness=pow(2,self.bitsperpixel)-1-pixelbrightness + + for b in self._intToBitlist(pixelbrightness): + imgmap.append(b) + + + + self.sendPacket(imgmap) #send packet and save last-imagemap + + + def sendPacket(self, imgmap): + packet = self._array2packet(imgmap) + self._sock.sendto(bytes(packet), (self._udphost, self._udpport)) + + + def send_bytes(self, img): + imgmap = [] + for pixel in img: + if pixel == "1": + imgmap.append(1) + else: + imgmap.append(0) + + if len(img) < 1280: + imgmap = np.hstack((imgmap, np.zeros(1280-len(img), dtype=int))) + + packet = self._array2packet(imgmap) + + self._sock.sendto(bytes(packet), (self._udphost, self._udpport)) diff --git a/client_sw/matrixsimulator.py b/client_sw/matrixsimulator.py new file mode 100644 index 0000000..cb11b15 --- /dev/null +++ b/client_sw/matrixsimulator.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +import _thread +import socket +import pygame +import math +import random +import numpy as np +from pygame.locals import * +import time + +WIDTH=160 +HEIGHT=24*6 +PIXELSIZE=4 #For Simulator Display +UDPPORT=2323 +DEBUG=True +BITSPERPIXEL=2 + + +class FlipdotSim(): + def __init__(self, + imageSize = (160,48), #80,16 + pixelSize = 10, + udpPort = 2323, + bitsperpixel=1): + self.imageSize=imageSize + self.udpPort = udpPort + self.bitsperpixel=bitsperpixel + self.flipdotMatrixSimulatorWidget = FlipdotMatrixSimulatorWidget(imageSize, pixelSize, bitsperpixel) #comment out if no simulator needed + self.udpHostSocket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + self.udpHostSocket.bind(("", self.udpPort)) + + self.timesincelastpacket=time.time() + + def run(self): + self.RunServer() + + def bitlistToInt(self,bitlist): #lsb last, [1,0]=2, [0,1]=1 + number=0 + for bitindex,bitvalue in enumerate(reversed(bitlist)): + number+=bitvalue*pow(2,bitindex) + return number + + def RunServer(self): + try: + while True: + #rawData = self.udpHostSocket.recv(4096) + rawData = self.udpHostSocket.recv(4096*2) + + imageArray = ImageArrayAdapter().convertPacketToImageArray(rawData) + if DEBUG: + print("Received Data. Time since last message: "+str( round( time.time()-self.timesincelastpacket,2))+"s ("+str( round( (1/ (time.time()-self.timesincelastpacket) ) ,2) ) +" FPS)") + self.timesincelastpacket=time.time() + _bitsneeded=self.imageSize[0]*self.imageSize[1]*self.bitsperpixel + if len(imageArray) < _bitsneeded: + if DEBUG: + print("WARNING: Not enough data received. Got "+str(len(imageArray))+" bits, needs "+str(_bitsneeded)+" bits") + emptyArray=np.zeros(_bitsneeded,dtype=int) + emptyArray[0:len(imageArray)]=imageArray + imageArray=emptyArray + elif len(imageArray) > _bitsneeded: + if DEBUG: + print("WARNING: Too much data received. Got "+str(len(imageArray))+" bits, needs "+str(_bitsneeded)+" bits") + imageArray=imageArray[0:_bitsneeded] + + imageArray=[self.bitlistToInt(x) for x in np.array(imageArray).reshape((int(len(imageArray)/self.bitsperpixel),self.bitsperpixel))] + + self.flipdotMatrixSimulatorWidget.show(imageArray) #send to simulator display + + finally: + self.udpHostSocket.close() + +class ImageArrayAdapter(): + def __init__(self): + self.arrayOfBinaryInts = [] + + def convertPacketToImageArray(self, udpPacketStr): + self.arrayOfBinaryInts = [] + byteArray = bytearray(udpPacketStr) + + #Fix for other format. Not Used + #byteArray = udpPacketStr.translate(None, b'\r\n').decode().replace('[','').replace(']','').replace(' ','').split(',') + #byteArray = [int(x) for x in byteArray] + #print("rawtype="+str(type(byteArray))) + + #print(byteArray) + for byte in byteArray: + #print("byte:"+str(byte)) + self.__appendByteToArrayOfBinaryInts(byte) + return self.arrayOfBinaryInts + + def __appendByteToArrayOfBinaryInts(self, byte): + byteValue = int(byte) + for i in range(8): + if math.floor(byteValue/(2**(7-i))) > 0: + self.arrayOfBinaryInts.append(1) + #print("append 1") + else: + self.arrayOfBinaryInts.append(0) + #print("append 0") + byteValue = byteValue%(2**(7-i)) + + + + +class FlipdotMatrixSimulatorWidget(): + BLACKCOLOR = 0 + WHITECOLOR = 1 + + def __init__(self, + imageSize = (160,48), + pixelSize = 4, + bitsperpixel = 1): + self.imageSize = imageSize + self.pixelSize = pixelSize + + pygame.init() + self.screen = pygame.display.set_mode((imageSize[0]*pixelSize, imageSize[1]*pixelSize)) + self.screen.fill((255,255,255)) + _thread.start_new_thread(self.watchCloseThread, ()) + + self.bitsperpixel=bitsperpixel + + + + def watchCloseThread(self): + while True: + for event in pygame.event.get(): + if event.type in (QUIT, QUIT): + import os + os.kill(os.getpid(), 9) + pygame.time.delay(500) + + def show(self, imageArray): + for yValue in range(self.imageSize[1]): + for xValue in range(self.imageSize[0]): + i = self.imageSize[0]*yValue + xValue + color = imageArray[i] / (pow(2,self.bitsperpixel)-1) #gives a number between 0 and 1 inclusive. Example for bitsperpixel=2: [1,0]-> 2/ (2^2-1)=2/3 + self.updatePixel(xValue, yValue, color) + pygame.display.update() + + def clearPixels(self): + for xValue in range(self.imageSize[0]): + for yValue in range(self.imageSize[1]): + self.updatePixel(xValue, yValue, self.BLACKCOLOR) + + def updatePixel(self, xValue, yValue, brightness): + surface = pygame.Surface((self.pixelSize, self.pixelSize)) + minimumbrightness=32 + rectcolor = ( (255-minimumbrightness)*brightness+minimumbrightness,127*brightness+ minimumbrightness/2, minimumbrightness/4) + + #surface.fill(rectcolor) + pygame.draw.circle(surface, rectcolor, (int(self.pixelSize/2), int(self.pixelSize/2)), int(self.pixelSize/2)) #Draw LED as filled circles + self.screen.blit(surface, (xValue*self.pixelSize, yValue*self.pixelSize)) + + + +if __name__ == '__main__': + FlipdotSim(imageSize=(WIDTH,HEIGHT), pixelSize = PIXELSIZE, udpPort=UDPPORT, bitsperpixel=BITSPERPIXEL).run()