You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
4.6 KiB

import numpy as _np
import math as _m
import sys as _sys
#_PIL_PATH = r'C:\Users\user\AppData\Roaming\Python\Python311\site-packages'
_PIL_PATH=r'C:\Users\tech\AppData\Local\Programs\Python\Python311\site-packages'
_LATIN = 'C:/Windows/Fonts/SpaceMono-Regular.ttf'
_CJK = 'C:/Windows/Fonts/NotoSansCJKtc-Regular.otf'
_FC = {}
_FLOAT=0; _GATHER=1; _LINES=2; _LFADE=3; _EXPAND=4; _ELLIPSE=5
def _font(cjk, sz):
from PIL import ImageFont
sz=max(8,int(sz)); k=(cjk,sz)
if k not in _FC:
try: _FC[k]=ImageFont.truetype(_CJK if cjk else _LATIN,sz)
except: _FC[k]=ImageFont.load_default()
return _FC[k]
def _cjk(ch): return '\u4e00'<=ch<='\u9fff'
def _blit_top(img, arr, x, y, alpha, H):
from PIL import Image as _Img
th, tw = arr.shape[:2]
arr_f = _np.flipud(arr)
lum = arr_f[:,:,0]
cols = _np.where(lum.max(axis=0) > 0.05)[0]
if len(cols) == 0: return x
arr_f = arr_f[:, :int(cols[-1])+1, :]
lum_rows = arr_f[:,:,0]
row_mask = _np.where(lum_rows.max(axis=1) > 0.05)[0]
if len(row_mask) == 0: return x
arr_f = arr_f[int(row_mask[0]):int(row_mask[-1])+1, :]
th, tw = arr_f.shape[:2]
mask_arr = (arr_f[:,:,0] * alpha * 255).clip(0,255).astype(_np.uint8)
from PIL import Image as _Img2
mask = _Img2.fromarray(mask_arr, 'L')
white = _Img2.new('RGBA', (tw, th), (255,255,255,255))
px=max(0,x); py=max(0, y - th//2)
if px >= img.width or py >= img.height: return x + tw
cw=min(tw, img.width-px); ch2=min(th, img.height-py)
if cw>0 and ch2>0:
img.paste(white.crop((0,0,cw,ch2)), (px,py), mask.crop((0,0,cw,ch2)))
return x + tw
def onSetupParameters(scriptOp): pass
def onCook(scriptOp):
try:
if _PIL_PATH not in _sys.path:
_sys.path.insert(0,_PIL_PATH)
_do_render(scriptOp)
except Exception as e:
import traceback; traceback.print_exc()
def _do_render(scriptOp):
from PIL import Image, ImageDraw
root=op('/project1/deep_sound')
W=int(root.par.Resw.val); H=int(root.par.Resh.val)
st=root.fetch('state_dict',None) or {}
ast=int(round(st.get('appState',_FLOAT)))
ea=float(st.get('ellipseAlpha',1.))
lfp=float(st.get('labelFadeProgress',0.))
edt=float(st.get('ellipseDrawT',0.))
pids=[int(round(st.get(f'pid{i}',0))) for i in range(4)]
ds=max(1.,root.par.Dotsize.val)
bg=root.fetch('bg_dots',[]); cd=root.fetch('circle_dots',[])
segs=root.fetch('line_segs',[]); las=root.fetch('label_alphas',[0,0,0,0])
prox=root.fetch('prox_pairs',[])
img=Image.new('RGBA',(W,H),(0,0,0,255))
draw=ImageDraw.Draw(img)
# 1. BG lines + dots (floating only)
if ast==_FLOAT:
for dist,i,j in prox:
a=int((1-dist/90)*.6*255)
draw.line([(bg[i]['x'],bg[i]['y']),(bg[j]['x'],bg[j]['y'])],
fill=(255,255,255,a),width=1)
for d in bg:
x,y=d['x'],d['y']
draw.ellipse([x-ds,y-ds,x+ds,y+ds],fill=(255,255,255,200))
# 2. Circle dots (not in ellipse states)
if ast not in (_EXPAND,_ELLIPSE):
for d in cd:
x,y=d['x'],d['y']
draw.ellipse([x-ds,y-ds,x+ds,y+ds],fill=(255,255,255,255))
# Connecting lines handled by line_render Script TOP + line_level Level TOP
# 3. Line labels (Chinese via lbl_ch_N, English via lbl_en_N)
if ast in (_LINES,_LFADE) and pids:
fade=1. if ast==_LINES else 1.-lfp
for i,did in enumerate(pids):
if i>=len(las): break
ca=las[i]*fade
if ca>0.01 and did<len(cd):
d=cd[did]
bx=int(d['x']+10); by=int(d['y']-6)
ch_top=root.op(f'lbl_ch_{i}'); en_top=root.op(f'lbl_en_{i}')
cx=bx
if ch_top:
ch_arr=ch_top.numpyArray(delayed=False)
if ch_arr is not None: cx=_blit_top(img,ch_arr,cx,by,ca,H)
if en_top:
en_arr=en_top.numpyArray(delayed=False)
if en_arr is not None: _blit_top(img,en_arr,cx+4,by,ca,H)
# 4. Ellipse dots
if ast in (_EXPAND,_ELLIPSE):
ei=int(ea*255)
for d in cd:
x,y=d['x'],d['y']
draw.ellipse([x-ds,y-ds,x+ds,y+ds],fill=(255,255,255,ei))
# 5. Ellipse outline
if ast==_ELLIPSE and edt>0:
ei=int(ea*.5*255); n=200; dn=int(n*edt)
pts=[(W/2+W*.47*_m.cos(s/n*2*_m.pi-_m.pi/2),
H/2+H*.43*_m.sin(s/n*2*_m.pi-_m.pi/2)) for s in range(dn+1)]
if len(pts)>1: draw.line(pts,fill=(255,255,255,ei),width=1)
arr=_np.ascontiguousarray(_np.flipud(_np.array(img,dtype=_np.float32)/255.))
scriptOp.copyNumpyArray(arr)