Don't change the originality just make sure every text and number looks same and font and font side similar if not correct only those and give me a flawless image
ls -la /home/daytona/workspace/ 2>/dev/null || echo "workspace not found"
mkdir -p /home/daytona/workspace/payment-slip && python3 << 'EOF' from PIL import Image, ImageDraw, ImageFont import os # Check available fonts import subprocess result = subprocess.run(['fc-list', '--format=%{file}\n'], capture_output=True, text=True) fonts = result.stdout.strip().split('\n') # Filter for common fonts useful = [f for f in fonts if any(x in f.lower() for x in ['arial', 'liberation', 'dejavu', 'freesans', 'ubuntu', 'noto', 'times', 'courier'])] print('\n'.join(useful[:30])) EOF
python3 << 'PYEOF' from PIL import Image, ImageDraw, ImageFont import math # Font paths FONT_REG = "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf" FONT_BOLD = "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf" # Canvas size - A4-ish portrait, high resolution W, H = 1240, 1754 img = Image.new("RGB", (W, H), color=(240, 232, 220)) # warm pinkish-beige background draw = ImageDraw.Draw(img) # ─── Font helpers ───────────────────────────────────────────── def font(size, bold=False): path = FONT_BOLD if bold else FONT_REG return ImageFont.truetype(path, size) def text_w(txt, fnt): bbox = fnt.getbbox(txt) return bbox[2] - bbox[0] def draw_text(x, y, txt, fnt, color=(30,30,30)): draw.text((x, y), txt, font=fnt, fill=color) def draw_text_centered(cx, y, txt, fnt, color=(30,30,30)): w = text_w(txt, fnt) draw.text((cx - w//2, y), txt, font=fnt, fill=color) # ─── HEADER BAR ─────────────────────────────────────────────── header_top = 90 header_h = 105 header_left = 80 header_right = W - 80 draw.rectangle([header_left, header_top, header_right, header_top + header_h], fill=(50, 50, 50)) # Logo circle placeholder (left side of header) logo_cx = header_left + 58 logo_cy = header_top + header_h // 2 logo_r = 38 draw.ellipse([logo_cx-logo_r, logo_cy-logo_r, logo_cx+logo_r, logo_cy+logo_r], outline=(200,200,200), width=2, fill=(70,70,70)) # Small inner detail draw.ellipse([logo_cx-28, logo_cy-28, logo_cx+28, logo_cy+28], outline=(180,180,180), width=1) # Building icon in logo draw.rectangle([logo_cx-10, logo_cy-4, logo_cx+10, logo_cy+14], fill=(180,180,180)) draw.rectangle([logo_cx-14, logo_cy-10, logo_cx+14, logo_cy-4], fill=(180,180,180)) draw.rectangle([logo_cx-2, logo_cy+2, logo_cx+2, logo_cy+14], fill=(70,70,70)) # 1993 text f_logo = font(9) draw_text_centered(logo_cx, logo_cy+18, "1993", f_logo, (180,180,180)) # Header text f_h1 = font(26, bold=True) f_h2 = font(23, bold=True) text_cx = (header_left + logo_cx + logo_r + header_right) // 2 + 20 line1 = "Jalal-Abad State University named after B.Osmonov" line2 = "2025–26 Payment Slip" y1 = header_top + 18 y2 = header_top + 52 draw_text_centered(text_cx, y1, line1, f_h1, (255,255,255)) draw_text_centered(text_cx, y2, line2, f_h2, (255,255,255)) # ─── OFFICE ADDRESS ─────────────────────────────────────────── f_addr = font(17) addr = "Office Address: #57, Lenin Street, Jalal-Abad, Kyrgyz Republic – 715600" draw_text_centered(W//2, header_top + header_h + 18, addr, f_addr) # ─── INFO TABLE (Class/Group/Campus/Session) ────────────────── tbl_top = header_top + header_h + 55 tbl_left = 80 tbl_right = W - 80 tbl_w = tbl_right - tbl_left f_lbl = font(17, bold=False) f_val = font(17) f_lbl_u = font(17) # underlined drawn manually row_h = 42 col1_w = 100 # "Class:" label col2_w = 200 # class value col3_w = 145 # "Name:" label col_rest = tbl_w - col1_w - col2_w - col3_w # name value def draw_rect_border(x1,y1,x2,y2, color=(80,80,80), width=1): draw.rectangle([x1,y1,x2,y2], outline=color, width=width) # Outer border draw_rect_border(tbl_left, tbl_top, tbl_right, tbl_top + 4*row_h, width=2) # Row 1: Class | Name r1_top = tbl_top draw_rect_border(tbl_left, r1_top, tbl_right, r1_top + row_h) # vertical dividers x_div1 = tbl_left + col1_w x_div2 = x_div1 + col2_w x_div3 = x_div2 + col3_w draw.line([(x_div1, r1_top),(x_div1, r1_top+row_h)], fill=(80,80,80), width=1) draw.line([(x_div2, r1_top),(x_div2, r1_top+row_h)], fill=(80,80,80), width=1) draw.line([(x_div3, r1_top),(x_div3, r1_top+row_h)], fill=(80,80,80), width=1) ty = r1_top + 11 draw_text(tbl_left+8, ty, "Class:", f_lbl) draw_text(x_div1+8, ty, "4", f_val) draw_text(x_div2+8, ty, "Name:", f_lbl) draw_text(x_div3+8, ty, "KAREMU PRANATHI", f_val) # Row 2: Group | Father Name r2_top = tbl_top + row_h draw_rect_border(tbl_left, r2_top, tbl_right, r2_top + row_h) draw.line([(x_div1, r2_top),(x_div1, r2_top+row_h)], fill=(80,80,80), width=1) draw.line([(x_div2, r2_top),(x_div2, r2_top+row_h)], fill=(80,80,80), width=1) draw.line([(x_div3, r2_top),(x_div3, r2_top+row_h)], fill=(80,80,80), width=1) ty2 = r2_top + 11 draw_text(tbl_left+8, ty2, "Group:", f_lbl) draw_text(x_div1+8, ty2, "8", f_val) draw_text(x_div2+8, ty2, "Father Name:", f_lbl) draw_text(x_div3+8, ty2, "SANTA RATNA RAJU KAREMU", f_val) # Row 3: Campus | Student Id | Mobile r3_top = tbl_top + 2*row_h r3_h = 60 # taller row for campus draw_rect_border(tbl_left, r3_top, tbl_right, r3_top + r3_h) # For row 3, different column layout # col1: Campus label, col2: campus value (spans more), col3: Student Id label, col4: id value, col5: Mobile label, col6: mobile value cx1 = tbl_left + col1_w cx2 = cx1 + 210 # campus value width cx3 = cx2 + 115 # student id label cx4 = cx3 + 60 # student id value cx5 = cx4 + 90 # Mobile label draw.line([(cx1, r3_top),(cx1, r3_top+r3_h)], fill=(80,80,80), width=1) draw.line([(cx2, r3_top),(cx2, r3_top+r3_h)], fill=(80,80,80), width=1) draw.line([(cx3, r3_top),(cx3, r3_top+r3_h)], fill=(80,80,80), width=1) draw.line([(cx4, r3_top),(cx4, r3_top+r3_h)], fill=(80,80,80), width=1) draw.line([(cx5, r3_top),(cx5, r3_top+r3_h)], fill=(80,80,80), width=1) ty3 = r3_top + 8 draw_text(tbl_left+8, ty3, "Campus:", f_lbl) # Multi-line campus name f_small = font(15) draw_text(cx1+8, ty3, "Jalal-Abad State", f_small) draw_text(cx1+8, ty3+18, "University named", f_small) draw_text(cx1+8, ty3+36, "after B.Osmonov", f_small) draw_text(cx2+8, ty3+10, "Student Id:", f_lbl) draw_text(cx3+8, ty3+10, "4301", f_val) draw_text(cx4+8, ty3+10, "Mobile:", f_lbl) # Row 4: Session | Status | Arrear r4_top = r3_top + r3_h draw_rect_border(tbl_left, r4_top, tbl_right, r4_top + row_h) # columns: Session | September | Status | Pursuing | Arrear | 0 USD sx1 = tbl_left + 105 sx2 = sx1 + 155 sx3 = sx2 + 90 sx4 = sx3 + 100 sx5 = sx4 + 95 draw.line([(sx1, r4_top),(sx1, r4_top+row_h)], fill=(80,80,80), width=1) draw.line([(sx2, r4_top),(sx2, r4_top+row_h)], fill=(80,80,80), width=1) draw.line([(sx3, r4_top),(sx3, r4_top+row_h)], fill=(80,80,80), width=1) draw.line([(sx4, r4_top),(sx4, r4_top+row_h)], fill=(80,80,80), width=1) draw.line([(sx5, r4_top),(sx5, r4_top+row_h)], fill=(80,80,80), width=1) ty4 = r4_top + 11 # "Session" with underline draw_text(tbl_left+8, ty4, "Session", f_lbl) tw = text_w("Session", f_lbl) draw.line([(tbl_left+8, ty4+20),(tbl_left+8+tw, ty4+20)], fill=(30,30,30), width=1) draw_text(sx1+8, ty4, "September", f_val) draw_text(sx2+8, ty4, "Status", f_lbl) draw_text(sx3+8, ty4, "Pursuing", f_val) draw_text(sx4+8, ty4, "Arrear", f_val) # "0 USD" right-aligned f_right = font(17) zero_usd = "0 USD" zw = text_w(zero_usd, f_right) draw_text(tbl_right - zw - 8, ty4, zero_usd, f_right) # ─── FEE SLIP TABLE ─────────────────────────────────────────── fee_top = r4_top + row_h + 30 fee_left = tbl_left fee_right = tbl_right # Column widths fc = [100, 90, 90, 75, 75, 90, 80, 130, 80, 75] # Fee Slip Detail | Tuition | Hostel | Mess | Visa | Medical | L&M | Transportation | Extra | Total headers = ["Fee Slip\nDetail", "Tuition\nFees", "Hostel\nFees", "Mess\nFees", "Visa\nFees", "Medical\nFees", "L&M\nFees", "Transportation\nFees", "Extra\nFees", "Total"] values = ["2025–26", "4200", "600", "0", "200", "150", "100", "0", "100", "6550"] f_fh = font(14, bold=True) f_fv = font(16) fee_row_h1 = 50 # header row fee_row_h2 = 38 # value row # Draw header row draw_rect_border(fee_left, fee_top, fee_right, fee_top + fee_row_h1 + fee_row_h2, width=2) x = fee_left for i, (hdr, cw) in enumerate(zip(headers, fc)): # vertical lines if i > 0: draw.line([(x, fee_top),(x, fee_top+fee_row_h1+fee_row_h2)], fill=(80,80,80), width=1) cx_col = x + cw//2 lines = hdr.split('\n') if len(lines)==2: draw_text_centered(cx_col, fee_top+6, lines[0], f_fh) draw_text_centered(cx_col, fee_top+22, lines[1], f_fh) else: draw_text_centered(cx_col, fee_top+16, lines[0], f_fh) x += cw # Horizontal line between header and values draw.line([(fee_left, fee_top+fee_row_h1),(fee_right, fee_top+fee_row_h1)], fill=(80,80,80), width=1) # Draw value row x = fee_left vy = fee_top + fee_row_h1 + 10 for i, (val, cw) in enumerate(zip(values, fc)): cx_col = x + cw//2 draw_text_centered(cx_col, vy, val, f_fv) x += cw # ─── TOTALS ─────────────────────────────────────────────────── tot_top = fee_top + fee_row_h1 + fee_row_h2 + 14 f_tot = font(17) draw_text(fee_left+4, tot_top, "Total Slip Amount: 6550 USD", f_tot) draw_text(fee_left+4, tot_top+24, "Total Receive Amount: 6550 USD", f_tot) # ─── TRANSACTION TABLE ──────────────────────────────────────── tr_top = tot_top + 65 tr_left = fee_left tr_right = fee_right # Columns: Tr No | Date | Received Amount | Paid on tc = [120, 220, 340, 200] # roughly equal to fill width tr_headers = ["Tr No:", "Date", "Received Amount", "Paid on"] transactions = [ ("4301", "17-Oct-2025", "1075 USD", "Office"), ("4464", "18-Oct-2025", "1207 USD", "Office"), ("8524", "10-Jan-2026", "229 USD", "Office"), ("9041", "23-Jan-2026", "119 USD", "Office"), ("9122", "26-Jan-2026", "500 USD", "India Acc"), ("9123", "26-Jan-2026", "1075 USD", "India Acc"), ("10893", "19-May-2026", "2345 USD", "KICB bank"), ] # Adjust last col to fill total_tc = sum(tc) scale = (tr_right - tr_left) / total_tc tc = [int(c*scale) for c in tc] tc[-1] = (tr_right - tr_left) - sum(tc[:-1]) f_th = font(17, bold=True) f_tv = font(17) tr_row_h = 38 # Header row draw_rect_border(tr_left, tr_top, tr_right, tr_top + tr_row_h, width=2) x = tr_left for i, (hdr, cw) in enumerate(zip(tr_headers, tc)): if i > 0: draw.line([(x, tr_top),(x, tr_top+tr_row_h)], fill=(80,80,80), width=1) cx_c = x + cw//2 draw_text_centered(cx_c, tr_top+10, hdr, f_th) x += cw # Data rows for ri, row in enumerate(transactions): ry = tr_top + (ri+1)*tr_row_h draw_rect_border(tr_left, ry, tr_right, ry+tr_row_h, width=1) # bold for some rows (bold in original for certain entries) bold_rows = {0,1,3,5,6} # matching original bold entries fnt = font(17, bold=(ri in bold_rows)) x = tr_left for ci, (val, cw) in enumerate(zip(row, tc)): if ci > 0: draw.line([(x, ry),(x, ry+tr_row_h)], fill=(80,80,80), width=1) cx_c = x + cw//2 draw_text_centered(cx_c, ry+10, val, fnt) x += cw # ─── CURRENT BALANCE ────────────────────────────────────────── cb_y = tr_top + (len(transactions)+1)*tr_row_h + 18 f_cb = font(16) cb_text = "Current Balance: -0 USD" cb_w = text_w(cb_text, f_cb) draw_text(tr_right - cb_w - 4, cb_y, cb_text, f_cb) # ─── PAID STAMP ─────────────────────────────────────────────── stamp_cx = tr_right - 110 stamp_cy = cb_y + 95 stamp_r = 55 # Outer dashed circle for angle in range(0, 360, 8): rad = math.radians(angle) x1 = stamp_cx + (stamp_r-3)*math.cos(rad) y1 = stamp_cy + (stamp_r-3)*math.sin(rad) x2 = stamp_cx + stamp_r*math.cos(rad) y2 = stamp_cy + stamp_r*math.sin(rad) draw.line([(x1,y1),(x2,y2)], fill=(80,80,80), width=2) draw.ellipse([stamp_cx-stamp_r+6, stamp_cy-stamp_r+6, stamp_cx+stamp_r-6, stamp_cy+stamp_r-6], outline=(80,80,80), width=2) f_paid = font(22, bold=True) draw_text_centered(stamp_cx, stamp_cy-12, "PAID", f_paid, (60,60,60)) # Dot decorations for angle in range(0, 360, 30): rad = math.radians(angle) dx = stamp_cx + (stamp_r-10)*math.cos(rad) dy = stamp_cy + (stamp_r-10)*math.sin(rad) draw.ellipse([dx-2,dy-2,dx+2,dy+2], fill=(80,80,80)) # ─── SIGNATURE LINE ─────────────────────────────────────────── sig_y = stamp_cy + stamp_r + 10 draw.line([(stamp_cx-70, sig_y),(stamp_cx+70, sig_y)], fill=(60,60,60), width=1) f_sig = font(15) draw_text_centered(stamp_cx, sig_y+8, "Authority Signature", f_sig) # ─── SAVE ───────────────────────────────────────────────────── out = "/home/daytona/workspace/payment-slip/payment_slip_clean.png" img.save(out, dpi=(150,150)) print(f"Saved: {out}") print(f"Size: {img.size}") PYEOF
python3 << 'PYEOF' from PIL import Image, ImageDraw, ImageFont import math FONT_REG = "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf" FONT_BOLD = "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf" # Tighter canvas, more A4-proportioned, white background inside a warm outer W, H = 1200, 1650 img = Image.new("RGB", (W, H), color=(235, 225, 215)) draw = ImageDraw.Draw(img) # White inner document area doc_left = 70 doc_top = 55 doc_right = W - 70 doc_bottom = H - 55 draw.rectangle([doc_left, doc_top, doc_right, doc_bottom], fill=(255,255,255)) def font(size, bold=False): path = FONT_BOLD if bold else FONT_REG return ImageFont.truetype(path, size) def tw(txt, fnt): bbox = fnt.getbbox(txt) return bbox[2] - bbox[0] def th(fnt): bbox = fnt.getbbox("Ag") return bbox[3] - bbox[1] def dt(x, y, txt, fnt, color=(25,25,25)): draw.text((x, y), txt, font=fnt, fill=color) def dtc(cx, y, txt, fnt, color=(25,25,25)): w = tw(txt, fnt) draw.text((cx - w//2, y), txt, font=fnt, fill=color) def rect(x1,y1,x2,y2, fill=None, outline=(70,70,70), width=1): draw.rectangle([x1,y1,x2,y2], fill=fill, outline=outline, width=width) def hline(x1,x2,y,color=(70,70,70),w=1): draw.line([(x1,y),(x2,y)], fill=color, width=w) def vline(x,y1,y2,color=(70,70,70),w=1): draw.line([(x,y1),(x,y2)], fill=color, width=w) # ─── HEADER ─────────────────────────────────────────────────── hdr_t = doc_top hdr_b = hdr_t + 110 rect(doc_left, hdr_t, doc_right, hdr_b, fill=(48,48,48), outline=(48,48,48), width=1) # Logo lcx = doc_left + 62 lcy = (hdr_t + hdr_b)//2 lr = 40 draw.ellipse([lcx-lr, lcy-lr, lcx+lr, lcy+lr], outline=(180,180,180), width=2) draw.ellipse([lcx-lr+6, lcy-lr+6, lcx+lr-6, lcy+lr-6], outline=(150,150,150), width=1) # Building draw.rectangle([lcx-12, lcy-6, lcx+12, lcy+16], fill=(160,160,160)) draw.polygon([(lcx-16, lcy-6),(lcx,lcy-20),(lcx+16,lcy-6)], fill=(160,160,160)) draw.rectangle([lcx-4, lcy+2, lcx+4, lcy+16], fill=(48,48,48)) fl = font(9) dtc(lcx, lcy+22, "1993", fl, (160,160,160)) # Header text fh1 = font(27, bold=True) fh2 = font(24, bold=True) tcx = (lcx + lr + doc_right) // 2 + 10 dtc(tcx, hdr_t+14, "Jalal-Abad State University named after B.Osmonov", fh1, (255,255,255)) dtc(tcx, hdr_t+52, "2025–26 Payment Slip", fh2, (255,255,255)) # ─── ADDRESS ────────────────────────────────────────────────── fa = font(16) ay = hdr_b + 16 dtc(W//2, ay, "Office Address: #57, Lenin Street, Jalal-Abad, Kyrgyz Republic – 715600", fa) # ─── INFO TABLE ─────────────────────────────────────────────── tl = doc_left tr_ = doc_right tt = ay + 42 rh = 40 # standard row height fl2 = font(17) fb2 = font(17, bold=False) # Table width tw_ = tr_ - tl # Column positions (absolute x) # Layout: [label_w=108][val_w=190][label2_w=135][val2 fills rest] c0 = tl c1 = tl + 108 c2 = c1 + 190 c3 = c2 + 135 c4 = tr_ def info_row(y, h, cols_data, dividers): """cols_data: list of (x_start, x_end, text, bold, align)""" rect(tl, y, tr_, y+h) for xd in dividers: vline(xd, y, y+h) for (xs, xe, txt, bold, align) in cols_data: fnt = font(17, bold=bold) pad = 8 cy_text = y + (h - th(fnt))//2 if align == 'left': dt(xs+pad, cy_text, txt, fnt) elif align == 'center': cx = (xs + xe)//2 dtc(cx, cy_text, txt, fnt) elif align == 'right': w_ = tw(txt, fnt) dt(xe - w_ - pad, cy_text, txt, fnt) # Row 1: Class | 4 | Name: | KAREMU PRANATHI info_row(tt, rh, [(c0,c1,"Class:",False,'left'),(c1,c2,"4",False,'left'), (c2,c3,"Name:",False,'left'),(c3,c4,"KAREMU PRANATHI",False,'left')], [c1,c2,c3]) # Row 2: Group | 8 | Father Name: | SANTA RATNA RAJU KAREMU info_row(tt+rh, rh, [(c0,c1,"Group:",False,'left'),(c1,c2,"8",False,'left'), (c2,c3,"Father Name:",False,'left'),(c3,c4,"SANTA RATNA RAJU KAREMU",False,'left')], [c1,c2,c3]) # Row 3: Campus (tall) | Student Id | 4301 | Mobile | # Recalculate columns for row 3 # Campus label | campus value | Student Id | 4301 | Mobile | (empty) r3y = tt + 2*rh r3h = 62 cc0 = tl cc1 = tl+108 # campus label end cc2 = cc1+200 # campus value end cc3 = cc2+120 # Student Id end cc4 = cc3+80 # 4301 end cc5 = cc4+105 # Mobile: end cc6 = tr_ rect(tl, r3y, tr_, r3y+r3h) for xd in [cc1,cc2,cc3,cc4,cc5]: vline(xd, r3y, r3y+r3h) f17 = font(17) fs = font(15) pad_y = (r3h - 3*18)//2 dt(tl+8, r3y+12, "Campus:", f17) dt(cc1+8, r3y+4, "Jalal-Abad State", fs) dt(cc1+8, r3y+22, "University named", fs) dt(cc1+8, r3y+40, "after B.Osmonov", fs) cy3 = r3y + (r3h - th(f17))//2 dt(cc2+8, cy3, "Student Id:", f17) dt(cc3+8, cy3, "4301", f17) dt(cc4+8, cy3, "Mobile:", f17) # Row 4: Session (underlined) | September | Status | Pursuing | Arrear | 0 USD r4y = r3y + r3h # Different column layout s0=tl; s1=tl+108; s2=s1+155; s3=s2+88; s4=s3+105; s5=s4+100; s6=tr_ rect(tl, r4y, tr_, r4y+rh) for xd in [s1,s2,s3,s4,s5]: vline(xd, r4y, r4y+rh) cy4 = r4y + (rh - th(f17))//2 # "Session" with underline dt(s0+8, cy4, "Session", f17) sess_w = tw("Session", f17) # underline just the word draw.line([(s0+8, cy4+th(f17)+1),(s0+8+sess_w, cy4+th(f17)+1)], fill=(25,25,25), width=1) dt(s1+8, cy4, "September", f17) dt(s2+8, cy4, "Status", f17) dt(s3+8, cy4, "Pursuing", f17) dt(s4+8, cy4, "Arrear", f17) # 0 USD right-aligned in last cell zusd = "0 USD" zw = tw(zusd, f17) dt(s6-zw-8, cy4, zusd, f17) # ─── FEE SLIP TABLE ─────────────────────────────────────────── ft = r4y + rh + 28 fl_ = tl fr_ = tr_ ftw = fr_ - fl_ # 10 columns fcols = [100, 88, 88, 74, 74, 88, 78, 128, 78, 74] total_fc = sum(fcols) fcols = [int(c * ftw / total_fc) for c in fcols] fcols[-1] = ftw - sum(fcols[:-1]) fhdrs = ["Fee Slip\nDetail","Tuition\nFees","Hostel\nFees","Mess\nFees","Visa\nFees", "Medical\nFees","L&M\nFees","Transportation\nFees","Extra\nFees","Total"] fvals = ["2025–26","4200","600","0","200","150","100","0","100","6550"] frh1 = 48 # header row frh2 = 36 # value row f_fh = font(14, bold=True) f_fv = font(16) rect(fl_, ft, fr_, ft+frh1+frh2, width=2) x = fl_ xs_list = [fl_] for cw in fcols: x += cw xs_list.append(x) for i in range(1, len(xs_list)-1): vline(xs_list[i], ft, ft+frh1+frh2) # Header text for i, hdr in enumerate(fhdrs): cx = (xs_list[i] + xs_list[i+1])//2 lines = hdr.split('\n') if len(lines)==2: dtc(cx, ft+6, lines[0], f_fh) dtc(cx, ft+22, lines[1], f_fh) else: dtc(cx, ft+14, lines[0], f_fh) hline(fl_, fr_, ft+frh1) # Values for i, val in enumerate(fvals): cx = (xs_list[i] + xs_list[i+1])//2 vy = ft + frh1 + (frh2 - th(f_fv))//2 dtc(cx, vy, val, f_fv) # ─── TOTALS ─────────────────────────────────────────────────── toty = ft + frh1 + frh2 + 12 f_tot = font(17) dt(fl_+4, toty, "Total Slip Amount: 6550 USD", f_tot) dt(fl_+4, toty+24, "Total Receive Amount: 6550 USD", f_tot) # ─── TRANSACTION TABLE ──────────────────────────────────────── trt = toty + 62 trl = fl_ trr = fr_ trw = trr - trl # 4 columns: Tr No | Date | Received Amount | Paid on trcols_raw = [110, 210, 340, 200] tot_trc = sum(trcols_raw) trcols = [int(c * trw / tot_trc) for c in trcols_raw] trcols[-1] = trw - sum(trcols[:-1]) trhdr = ["Tr No:", "Date", "Received Amount", "Paid on"] transactions = [ ("4301", "17-Oct-2025", "1075 USD", "Office"), ("4464", "18-Oct-2025", "1207 USD", "Office"), ("8524", "10-Jan-2026", "229 USD", "Office"), ("9041", "23-Jan-2026", "119 USD", "Office"), ("9122", "26-Jan-2026", "500 USD", "India Acc"), ("9123", "26-Jan-2026", "1075 USD", "India Acc"), ("10893", "19-May-2026", "2345 USD", "KICB bank"), ] trrh = 36 f_trh = font(17, bold=True) f_trv = font(17) trxs = [trl] x = trl for c in trcols: x += c trxs.append(x) # Header rect(trl, trt, trr, trt+trrh, width=2) for i in range(1, len(trxs)-1): vline(trxs[i], trt, trt+trrh) for i, h in enumerate(trhdr): cx = (trxs[i]+trxs[i+1])//2 cy_h = trt + (trrh - th(f_trh))//2 dtc(cx, cy_h, h, f_trh) # Data rows - all normal weight to match original for ri, row in enumerate(transactions): ry = trt + (ri+1)*trrh rect(trl, ry, trr, ry+trrh, width=1) for i in range(1, len(trxs)-1): vline(trxs[i], ry, ry+trrh) cy_r = ry + (trrh - th(f_trv))//2 for ci, val in enumerate(row): cx = (trxs[ci]+trxs[ci+1])//2 dtc(cx, cy_r, val, f_trv) # ─── CURRENT BALANCE ────────────────────────────────────────── cby = trt + (len(transactions)+1)*trrh + 16 f_cb = font(16) cbt = "Current Balance: -0 USD" cbw = tw(cbt, f_cb) dt(trr - cbw - 4, cby, cbt, f_cb) # ─── PAID STAMP ─────────────────────────────────────────────── stamp_cx = trr - 115 stamp_cy = cby + 100 stamp_r = 52 # Outer dotted ring for angle in range(0, 360, 6): rad = math.radians(angle) x1 = stamp_cx + (stamp_r-2)*math.cos(rad) y1 = stamp_cy + (stamp_r-2)*math.sin(rad) x2 = stamp_cx + (stamp_r+2)*math.cos(rad) y2 = stamp_cy + (stamp_r+2)*math.sin(rad) # Only draw dots (every other) if angle % 12 < 6: draw.ellipse([x1-2,y1-2,x1+2,y1+2], fill=(70,70,70)) # Inner circle draw.ellipse([stamp_cx-stamp_r+8, stamp_cy-stamp_r+8, stamp_cx+stamp_r-8, stamp_cy+stamp_r-8], outline=(70,70,70), width=2) # PAID text f_paid = font(24, bold=True) dtc(stamp_cx, stamp_cy-13, "PAID", f_paid, (60,60,60)) # Small stars/dots inside stamp for angle in [0, 72, 144, 216, 288]: rad = math.radians(angle) dx = int(stamp_cx + 35*math.cos(rad)) dy = int(stamp_cy + 35*math.sin(rad)) draw.ellipse([dx-2,dy-2,dx+2,dy+2], fill=(70,70,70)) # Signature (squiggly lines to simulate handwriting) sx_base = stamp_cx - 50 sy_base = stamp_cy - 55 # Simulate a signature with curves sig_pts = [] for i in range(60): t = i / 60 sx = sx_base + t*100 sy = sy_base + math.sin(t*math.pi*4)*8 + math.sin(t*math.pi*7)*4 sig_pts.append((sx,sy)) draw.line(sig_pts, fill=(40,40,40), width=2) # Second stroke sig_pts2 = [] for i in range(30): t = i/30 sx = sx_base + 10 + t*80 sy = sy_base + 14 + math.sin(t*math.pi*3)*6 sig_pts2.append((sx,sy)) draw.line(sig_pts2, fill=(40,40,40), width=2) # Auth signature line sig_line_y = stamp_cy + stamp_r + 12 hline(stamp_cx-72, stamp_cx+72, sig_line_y, (50,50,50)) f_sig = font(15) dtc(stamp_cx, sig_line_y+6, "Authority Signature", f_sig) # ─── SAVE ───────────────────────────────────────────────────── out = "/home/daytona/workspace/payment-slip/payment_slip_v2.png" img.save(out, dpi=(150,150)) print(f"Saved: {out} Size: {img.size}") PYEOF
python3 << 'PYEOF' from PIL import Image, ImageDraw, ImageFont import math FONT_REG = "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf" FONT_BOLD = "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf" W, H = 1200, 1480 img = Image.new("RGB", (W, H), color=(235, 225, 215)) draw = ImageDraw.Draw(img) doc_left = 70 doc_top = 52 doc_right = W - 70 doc_bottom = H - 52 draw.rectangle([doc_left, doc_top, doc_right, doc_bottom], fill=(255,255,255)) def font(size, bold=False): return ImageFont.truetype(FONT_BOLD if bold else FONT_REG, size) def tw(txt, fnt): bb = fnt.getbbox(txt); return bb[2]-bb[0] def th_font(fnt): bb = fnt.getbbox("Ag"); return bb[3]-bb[1] def dt(x, y, txt, fnt, color=(25,25,25)): draw.text((x, y), txt, font=fnt, fill=color) def dtc(cx, y, txt, fnt, color=(25,25,25)): draw.text((cx - tw(txt,fnt)//2, y), txt, font=fnt, fill=color) def dtr(xr, y, txt, fnt, color=(25,25,25)): draw.text((xr - tw(txt,fnt), y), txt, font=fnt, fill=color) def box(x1,y1,x2,y2, fill=None, outline=(68,68,68), lw=1): draw.rectangle([x1,y1,x2,y2], fill=fill, outline=outline, width=lw) def hl(x1,x2,y, c=(68,68,68), w=1): draw.line([(x1,y),(x2,y)], fill=c, width=w) def vl(x,y1,y2, c=(68,68,68), w=1): draw.line([(x,y1),(x,y2)], fill=c, width=w) # ─── HEADER ─────────────────────────────────────────────────── ht=doc_top; hb=ht+110 box(doc_left,ht,doc_right,hb, fill=(48,48,48), outline=(48,48,48)) # University logo (left side) lcx=doc_left+65; lcy=(ht+hb)//2; lr=42 draw.ellipse([lcx-lr,lcy-lr,lcx+lr,lcy+lr], outline=(185,185,185), width=2) draw.ellipse([lcx-lr+7,lcy-lr+7,lcx+lr-7,lcy+lr-7], outline=(155,155,155), width=1) # Simplified building/pillar draw.polygon([(lcx-14,lcy-8),(lcx,lcy-22),(lcx+14,lcy-8)], fill=(165,165,165)) draw.rectangle([lcx-13,lcy-8,lcx+13,lcy+18], fill=(165,165,165)) draw.rectangle([lcx-5,lcy+2,lcx+5,lcy+18], fill=(48,48,48)) draw.rectangle([lcx-10,lcy+2,lcx-6,lcy+14], fill=(48,48,48)) draw.rectangle([lcx+6,lcy+2,lcx+10,lcy+14], fill=(48,48,48)) dtc(lcx, lcy+22, "1993", font(9), (165,165,165)) tcx = (lcx+lr + doc_right)//2 + 15 dtc(tcx, ht+13, "Jalal-Abad State University named after B.Osmonov", font(27,True), (255,255,255)) dtc(tcx, ht+52, "2025–26 Payment Slip", font(24,True), (255,255,255)) # ─── ADDRESS ────────────────────────────────────────────────── ay = hb+15 dtc(W//2, ay, "Office Address: #57, Lenin Street, Jalal-Abad, Kyrgyz Republic – 715600", font(16)) # ─── INFO TABLE ─────────────────────────────────────────────── tl=doc_left; tr=doc_right; tt=ay+42; rh=40 f17=font(17); f15=font(15) c0=tl; c1=tl+108; c2=c1+190; c3=c2+135; c4=tr def crow(y,h,segs,divs): box(tl,y,tr,y+h) for d in divs: vl(d,y,y+h) for (xs,xe,txt,bold,align) in segs: f=font(17,bold=bold); cy=y+(h-th_font(f))//2 if align=='L': dt(xs+8,cy,txt,f) elif align=='C': dtc((xs+xe)//2,cy,txt,f) elif align=='R': dtr(xe-8,cy,txt,f) crow(tt,rh,[(c0,c1,"Class:",False,'L'),(c1,c2,"4",False,'L'),(c2,c3,"Name:",False,'L'),(c3,c4,"KAREMU PRANATHI",False,'L')],[c1,c2,c3]) crow(tt+rh,rh,[(c0,c1,"Group:",False,'L'),(c1,c2,"8",False,'L'),(c2,c3,"Father Name:",False,'L'),(c3,c4,"SANTA RATNA RAJU KAREMU",False,'L')],[c1,c2,c3]) # Campus row (tall) r3y=tt+2*rh; r3h=62 cc0=tl; cc1=tl+108; cc2=cc1+200; cc3=cc2+120; cc4=cc3+78; cc5=cc4+108; cc6=tr box(tl,r3y,tr,r3y+r3h) for d in [cc1,cc2,cc3,cc4,cc5]: vl(d,r3y,r3y+r3h) dt(tl+8, r3y+12, "Campus:", f17) dt(cc1+8,r3y+3, "Jalal-Abad State", f15) dt(cc1+8,r3y+21, "University named", f15) dt(cc1+8,r3y+39, "after B.Osmonov", f15) cy3=r3y+(r3h-th_font(f17))//2 dt(cc2+8,cy3,"Student Id:",f17); dt(cc3+8,cy3,"4301",f17); dt(cc4+8,cy3,"Mobile:",f17) # Session row r4y=r3y+r3h s0=tl;s1=tl+108;s2=s1+155;s3=s2+88;s4=s3+105;s5=s4+100;s6=tr crow(r4y,rh,[],[s1,s2,s3,s4,s5]) cy4=r4y+(rh-th_font(f17))//2 dt(s0+8,cy4,"Session",f17) sw=tw("Session",f17) draw.line([(s0+8,cy4+th_font(f17)+1),(s0+8+sw,cy4+th_font(f17)+1)],fill=(25,25,25),width=1) dt(s1+8,cy4,"September",f17); dt(s2+8,cy4,"Status",f17) dt(s3+8,cy4,"Pursuing",f17); dt(s4+8,cy4,"Arrear",f17) dtr(tr-8,cy4,"0 USD",f17) # ─── FEE TABLE ──────────────────────────────────────────────── ft_top=r4y+rh+28; ftw=tr-tl fcols=[100,88,88,74,74,88,78,128,78,74] s=ftw/sum(fcols); fcols=[int(c*s) for c in fcols]; fcols[-1]=ftw-sum(fcols[:-1]) fxs=[tl] for c in fcols: fxs.append(fxs[-1]+c) fhdrs=["Fee Slip\nDetail","Tuition\nFees","Hostel\nFees","Mess\nFees","Visa\nFees","Medical\nFees","L&M\nFees","Transportation\nFees","Extra\nFees","Total"] fvals=["2025–26","4200","600","0","200","150","100","0","100","6550"] frh1=48; frh2=36; f_fh=font(14,True); f_fv=font(16) box(tl,ft_top,tr,ft_top+frh1+frh2,lw=2) for i in range(1,len(fxs)-1): vl(fxs[i],ft_top,ft_top+frh1+frh2) for i,h in enumerate(fhdrs): cx=(fxs[i]+fxs[i+1])//2; lines=h.split('\n') if len(lines)==2: dtc(cx,ft_top+6,lines[0],f_fh); dtc(cx,ft_top+22,lines[1],f_fh) else: dtc(cx,ft_top+16,lines[0],f_fh) hl(tl,tr,ft_top+frh1) for i,v in enumerate(fvals): cx=(fxs[i]+fxs[i+1])//2; vy=ft_top+frh1+(frh2-th_font(f_fv))//2; dtc(cx,vy,v,f_fv) # ─── TOTALS ─────────────────────────────────────────────────── toty=ft_top+frh1+frh2+12; f_tot=font(17) dt(tl+4,toty,"Total Slip Amount: 6550 USD",f_tot) dt(tl+4,toty+26,"Total Receive Amount: 6550 USD",f_tot) # ─── TRANSACTION TABLE ──────────────────────────────────────── trt=toty+62 trw=tr-tl; trcols=[110,210,340,200] s2=trw/sum(trcols); trcols=[int(c*s2) for c in trcols]; trcols[-1]=trw-sum(trcols[:-1]) trxs=[tl] for c in trcols: trxs.append(trxs[-1]+c) trhdr=["Tr No:","Date","Received Amount","Paid on"] rows=[("4301","17-Oct-2025","1075 USD","Office"),("4464","18-Oct-2025","1207 USD","Office"), ("8524","10-Jan-2026","229 USD","Office"),("9041","23-Jan-2026","119 USD","Office"), ("9122","26-Jan-2026","500 USD","India Acc"),("9123","26-Jan-2026","1075 USD","India Acc"), ("10893","19-May-2026","2345 USD","KICB bank")] trrh=36; f_trh=font(17,True); f_trv=font(17) box(tl,trt,tr,trt+trrh,lw=2) for i in range(1,len(trxs)-1): vl(trxs[i],trt,trt+trrh) for i,h in enumerate(trhdr): dtc((trxs[i]+trxs[i+1])//2,trt+(trrh-th_font(f_trh))//2,h,f_trh) for ri,row in enumerate(rows): ry=trt+(ri+1)*trrh; box(tl,ry,tr,ry+trrh) for i in range(1,len(trxs)-1): vl(trxs[i],ry,ry+trrh) cy=ry+(trrh-th_font(f_trv))//2 for ci,v in enumerate(row): dtc((trxs[ci]+trxs[ci+1])//2,cy,v,f_trv) # ─── CURRENT BALANCE ────────────────────────────────────────── cby=trt+(len(rows)+1)*trrh+16; f_cb=font(16) dtr(tr-4,cby,"Current Balance: -0 USD",f_cb) # ─── SIGNATURE + STAMP ──────────────────────────────────────── stamp_cx=tr-118; stamp_cy=cby+108; stamp_r=55 # Handwritten signature above stamp import random; random.seed(42) sig_x0=stamp_cx-62; sig_y0=stamp_cy-70 # First stroke - main signature wave pts1=[] for i in range(80): t=i/79 x=sig_x0+t*125 y=sig_y0 + math.sin(t*math.pi*3.5)*11 + math.sin(t*math.pi*8)*4 - t*8 pts1.append((x,y)) draw.line(pts1, fill=(40,40,40), width=2) # Second stroke - underline/flourish pts2=[] for i in range(50): t=i/49 x=sig_x0+5+t*110 y=sig_y0+18+math.sin(t*math.pi*2)*5+t*4 pts2.append((x,y)) draw.line(pts2, fill=(40,40,40), width=2) # Small tail loop pts3=[] for i in range(25): t=i/24; angle=t*math.pi*1.5 x=sig_x0+90+math.cos(angle)*12 y=sig_y0+8+math.sin(angle)*8 pts3.append((x,y)) draw.line(pts3, fill=(40,40,40), width=2) # Stamp outer dashed/dotted ring for angle_d in range(0,360,5): rad=math.radians(angle_d) if angle_d%10<5: dx=int(stamp_cx+(stamp_r-1)*math.cos(rad)) dy=int(stamp_cy+(stamp_r-1)*math.sin(rad)) draw.ellipse([dx-2,dy-2,dx+2,dy+2],fill=(65,65,65)) # Inner border circle draw.ellipse([stamp_cx-stamp_r+9,stamp_cy-stamp_r+9,stamp_cx+stamp_r-9,stamp_cy+stamp_r-9], outline=(65,65,65),width=2) # PAID text f_paid=font(26,True) dtc(stamp_cx,stamp_cy-14,"PAID",f_paid,(55,55,55)) # Small decorative dots inside ring for angle_d in range(15,360,30): rad=math.radians(angle_d) dx=int(stamp_cx+(stamp_r-4.5)*math.cos(rad)) dy=int(stamp_cy+(stamp_r-4.5)*math.sin(rad)) draw.ellipse([dx-2,dy-2,dx+2,dy+2],fill=(65,65,65)) # Authority Signature line and text asl_y=stamp_cy+stamp_r+14 hl(stamp_cx-78,stamp_cx+78,asl_y,(50,50,50)) dtc(stamp_cx,asl_y+6,"Authority Signature",font(15)) # ─── SAVE ───────────────────────────────────────────────────── out="/home/daytona/workspace/payment-slip/payment_slip_final.png" img.save(out, dpi=(150,150)) print(f"Saved: {out} Size:{img.size}") PYEOF
python3 << 'PYEOF' from PIL import Image img = Image.open("/home/daytona/workspace/payment-slip/payment_slip_final.png") # Crop to remove extra whitespace at bottom - content ends around y=1200 cropped = img.crop((0, 0, img.width, 1270)) out = "/home/daytona/workspace/payment-slip/payment_slip_clean_final.png" cropped.save(out, dpi=(150,150)) print(f"Cropped size: {cropped.size}") PYEOF
payment slip clean final
Image · PNG