Create a trifold pamplet for copd with the reference image and change the presented name to J.JERO.F.SHERIN
ls /tmp/workspace/ 2>/dev/null || mkdir -p /tmp/workspace/copd-pamphlet
mkdir -p /tmp/workspace/copd-pamphlet && python3 -c "from PIL import Image, ImageDraw, ImageFont; print('PIL OK'); import reportlab; print('ReportLab OK')"
~/copd-pamphlet/create_pamphlet.py
from PIL import Image, ImageDraw, ImageFont
import textwrap
import os
# ── Palette (matching reference) ────────────────────────────────────────────
TEAL = (0, 141, 153) # right-panel / header BG
CORAL = (204, 80, 80) # section headers (left panel top, etc.)
SALMON = (220, 100, 90) # lifestyle header block
PINK_HEADER = (220, 100, 90) # section label bars
LIGHT_PINK = (245, 200, 200) # food section BG
CREAM = (253, 248, 240) # body background
WHITE = (255, 255, 255)
BLACK = (20, 20, 20)
DARK_BLUE = (10, 40, 90)
ORANGE = (230, 120, 0)
TEAL_DARK = (0, 110, 120)
GOLD = (210, 160, 0)
LIGHT_BLUE = (200, 230, 240)
PANEL_GREY = (245, 243, 238)
# ── Canvas dimensions ────────────────────────────────────────────────────────
# A4 landscape = 3508 x 2480 px @300dpi → two A4 pages stacked (front+back)
# We'll produce two separate images: front and back
W_PANEL = 1169 # ~1/3 of A4 landscape
H = 2480
FULL_W = W_PANEL * 3
def load_font(size, bold=False):
paths = [
f"/usr/share/fonts/truetype/dejavu/DejaVuSans{'-Bold' if bold else ''}.ttf",
f"/usr/share/fonts/truetype/liberation/LiberationSans{'-Bold' if bold else ''}.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
]
for p in paths:
if os.path.exists(p):
try:
return ImageFont.truetype(p, size)
except:
continue
return ImageFont.load_default()
def draw_rounded_rect(draw, xy, radius, fill, outline=None, outline_width=3):
x0, y0, x1, y1 = xy
draw.rectangle([x0+radius, y0, x1-radius, y1], fill=fill)
draw.rectangle([x0, y0+radius, x1, y1-radius], fill=fill)
draw.ellipse([x0, y0, x0+2*radius, y0+2*radius], fill=fill)
draw.ellipse([x1-2*radius, y0, x1, y0+2*radius], fill=fill)
draw.ellipse([x0, y1-2*radius, x0+2*radius, y1], fill=fill)
draw.ellipse([x1-2*radius, y1-2*radius, x1, y1], fill=fill)
if outline:
draw.arc([x0, y0, x0+2*radius, y0+2*radius], 180, 270, fill=outline, width=outline_width)
draw.arc([x1-2*radius, y0, x1, y0+2*radius], 270, 360, fill=outline, width=outline_width)
draw.arc([x0, y1-2*radius, x0+2*radius, y1], 90, 180, fill=outline, width=outline_width)
draw.arc([x1-2*radius, y1-2*radius, x1, y1], 0, 90, fill=outline, width=outline_width)
draw.line([x0+radius, y0, x1-radius, y0], fill=outline, width=outline_width)
draw.line([x0+radius, y1, x1-radius, y1], fill=outline, width=outline_width)
draw.line([x0, y0+radius, x0, y1-radius], fill=outline, width=outline_width)
draw.line([x1, y0+radius, x1, y1-radius], fill=outline, width=outline_width)
def section_header(draw, x0, y0, x1, y1, text, bg=CORAL, fg=WHITE, font=None):
draw_rounded_rect(draw, (x0, y0, x1, y1), 10, fill=bg)
if font is None:
font = load_font(52, bold=True)
bbox = draw.textbbox((0,0), text, font=font)
tw, th = bbox[2]-bbox[0], bbox[3]-bbox[1]
draw.text(((x0+x1)//2 - tw//2, (y0+y1)//2 - th//2), text, fill=fg, font=font)
def wrap_text(draw, text, x, y, max_w, font, fill=BLACK, line_spacing=8):
words = text.split()
lines = []
current = ""
for word in words:
test = (current + " " + word).strip()
bb = draw.textbbox((0,0), test, font=font)
if bb[2]-bb[0] <= max_w:
current = test
else:
if current:
lines.append(current)
current = word
if current:
lines.append(current)
cy = y
for line in lines:
draw.text((x, cy), line, fill=fill, font=font)
bb = draw.textbbox((0,0), line, font=font)
cy += bb[3]-bb[1] + line_spacing
return cy
def bullet_text(draw, items, x, y, max_w, font, fill=BLACK, bullet="•", spacing=14):
bf = load_font(font.size if hasattr(font,'size') else 36, bold=True)
cy = y
for item in items:
draw.text((x, cy), bullet, fill=fill, font=bf)
cy = wrap_text(draw, item, x+50, cy, max_w-50, font, fill, line_spacing=6)
cy += spacing
return cy
# ════════════════════════════════════════════════════════════════════════════
# FRONT SIDE (Panel 1=Treatment/Lifestyle | Panel 2=Middle/Credentials |
# Panel 3=Cover/Definition)
# ════════════════════════════════════════════════════════════════════════════
def build_front():
img = Image.new("RGB", (FULL_W, H), CREAM)
draw = ImageDraw.Draw(img)
PAD = 40
P1X = 0 # panel 1 left edge
P2X = W_PANEL # panel 2
P3X = W_PANEL*2 # panel 3 (cover)
# ── Panel vertical dividers ──────────────────────────────────────────────
draw.line([(W_PANEL, 0), (W_PANEL, H)], fill=(200,200,200), width=4)
draw.line([(W_PANEL*2, 0), (W_PANEL*2, H)], fill=(200,200,200), width=4)
# ═══════════════════════════════════════════════
# PANEL 3 – COVER (right panel when folded)
# ═══════════════════════════════════════════════
# Full teal background
draw.rectangle([P3X, 0, FULL_W, H], fill=TEAL)
# "COPD" big title – light gold bar at top
draw.rectangle([P3X, 0, FULL_W, 180], fill=(185, 100, 60)) # coral/brown bar
f_title = load_font(110, bold=True)
draw.text((P3X + 70, 30), "COPD", fill=WHITE, font=f_title)
# Definition text (white, large bold)
f_def_bold = load_font(50, bold=True)
f_def = load_font(46)
definition = (
"Chronic Obstructive Pulmonary Disease (COPD) is a chronic "
"inflammatory lung disease that causes obstructed airflow from "
"the lungs. Symptoms include breathing difficulty, cough, mucus "
"production, and wheezing."
)
cy = 220
cy = wrap_text(draw, definition, P3X+PAD, cy, W_PANEL-2*PAD, f_def_bold, fill=WHITE, line_spacing=12)
# Sub-note
cy += 20
f_small = load_font(40)
sub = ("It is typically caused by long-term exposure to irritating gases "
"or particulate matter, most often from cigarette smoke.")
cy = wrap_text(draw, sub, P3X+PAD, cy, W_PANEL-2*PAD, f_small, fill=(220,240,245), line_spacing=10)
# Lung illustration placeholder (colored box)
cy += 40
lung_y0, lung_y1 = cy, cy + 480
draw.rectangle([P3X+60, lung_y0, FULL_W-60, lung_y1], fill=(0,100,115))
draw.rectangle([P3X+60, lung_y0, FULL_W-60, lung_y1], outline=(255,255,255), width=4)
# simple lung symbol
f_lung = load_font(200)
draw.text((P3X+280, lung_y0+100), "🫁", fill=WHITE, font=f_lung)
f_cap = load_font(38)
draw.text((P3X+80, lung_y1-60), "Airway obstruction in COPD", fill=(200,240,245), font=f_cap)
# Bottom note
cy = lung_y1 + 40
note = ("The thin transparent airway lining becomes inflamed, narrowed, "
"and produces excess mucus — making breathing hard.")
f_note = load_font(42)
wrap_text(draw, note, P3X+PAD, cy, W_PANEL-2*PAD, f_note, fill=(210,240,250), line_spacing=10)
# ═══════════════════════════════════════════════
# PANEL 1 – TREATMENT + LIFESTYLE (left panel)
# ═══════════════════════════════════════════════
y = 30
# TREATMENT header
section_header(draw, P1X+PAD, y, P1X+W_PANEL-PAD, y+90, "TREATMENT",
bg=CORAL, font=load_font(58, bold=True))
y += 110
# Table header
col_w = [220, 220, 380, 290]
headers = ["Type of COPD", "First-line Tx", "Drug Examples", "Dosage"]
table_x = P1X + PAD
table_y = y
th_h = 60
f_th = load_font(30, bold=True)
f_td = load_font(28)
cx = table_x
for i, (hdr, cw) in enumerate(zip(headers, col_w)):
draw.rectangle([cx, table_y, cx+cw, table_y+th_h], fill=(230,170,140))
draw.rectangle([cx, table_y, cx+cw, table_y+th_h], outline=BLACK, width=2)
bb = draw.textbbox((0,0), hdr, font=f_th)
draw.text((cx + cw//2 - (bb[2]-bb[0])//2, table_y + th_h//2 - (bb[3]-bb[1])//2),
hdr, fill=BLACK, font=f_th)
cx += cw
# Table rows
rows = [
("Stable\nMild COPD", "SABA /\nSAMA", "Salbutamol,\nIpratropium", "100–200 mcg\n4–6h PRN"),
("Stable\nModerate", "LABA +\nLAMA", "Salmeterol,\nTiotropium", "50 mcg bd /\n18 mcg od"),
("Stable\nSevere", "ICS + LABA\n+LAMA", "Budesonide,\nFormoterol", "200/6 mcg\nbd inhaler"),
("COPD\nExacerbation", "SABA + OCS\n+Abx", "Salbutamol NEB,\nPrednisolone","2.5 mg NEB\n30–40 mg od"),
("O₂\nTherapy", "Target\nSpO₂ 88–92","Controlled O₂", "24–28%\nVenturi mask"),
]
row_h = 100
for r, row in enumerate(rows):
ry = table_y + th_h + r*row_h
cx = table_x
for c, (cell, cw) in enumerate(zip(row, col_w)):
bg_c = CREAM if r%2==0 else (240,235,228)
draw.rectangle([cx, ry, cx+cw, ry+row_h], fill=bg_c)
draw.rectangle([cx, ry, cx+cw, ry+row_h], outline=(180,180,180), width=1)
if c == 0:
f_cell = load_font(28, bold=True)
fc = CORAL
else:
f_cell = f_td
fc = BLACK
# wrap cell text
lines = cell.split("\n")
ty = ry + 12
for ln in lines:
draw.text((cx+8, ty), ln, fill=fc, font=f_cell)
bb = draw.textbbox((0,0), ln, font=f_cell)
ty += bb[3]-bb[1] + 4
cx += cw
y = table_y + th_h + len(rows)*row_h + 30
# LIFESTYLE MODIFICATION header
section_header(draw, P1X+PAD, y, P1X+W_PANEL-PAD, y+90,
"LIFE STYLE MODIFICATION", bg=SALMON, font=load_font(46, bold=True))
y += 110
# Lifestyle subtitle
f_ls_title = load_font(40, bold=True)
draw.text((P1X+PAD, y), "LIFESTYLE MODIFICATIONS FOR COPD", fill=TEAL_DARK, font=f_ls_title)
y += 60
# Lifestyle bullets with icon boxes
ls_items = [
("🚭", "Quit Smoking", "The single most important step"),
("🏃", "Exercise Regularly", "Pulmonary rehab & walking"),
("😷", "Avoid Pollutants", "Dust, fumes, chemical vapors"),
("💉", "Annual Flu Vaccine", "Prevents exacerbations"),
("🌬️", "Breathing Exercises", "Pursed-lip & diaphragmatic"),
("🥗", "Healthy Diet", "High-calorie, small frequent meals"),
("💊", "Medication Adherence", "Use inhalers as prescribed"),
("🏠", "Avoid Triggers", "Cold air, smoke, allergens"),
]
f_ls_head = load_font(36, bold=True)
f_ls_body = load_font(30)
col2_x = P1X + PAD + 580
for i, (icon, head, body) in enumerate(ls_items):
col = i % 2
row = i // 2
ix = P1X + PAD + col * 560
iy = y + row * 175
# icon box
draw_rounded_rect(draw, (ix, iy, ix+70, iy+70), 8, fill=TEAL)
draw.text((ix+8, iy+5), icon, fill=WHITE, font=load_font(44))
draw.text((ix+80, iy+5), head, fill=DARK_BLUE, font=f_ls_head)
draw.text((ix+80, iy+48), body, fill=(80,80,80), font=f_ls_body)
# ═══════════════════════════════════════════════
# PANEL 2 – MIDDLE (food + college credentials)
# ═══════════════════════════════════════════════
mx = P2X + PAD
my = 30
# Food to Take header
f_food_title = load_font(52, bold=True)
draw.text((P2X + 180, my), "Food to be taken", fill=BLACK, font=f_food_title)
my += 80
# Blue divider line
draw.line([(P2X+PAD, my), (P2X+W_PANEL-PAD, my)], fill=TEAL, width=6)
my += 20
# Food grid – good foods
good_foods = [("🐟 Fish", LIGHT_BLUE), ("🥦 Vegetables", (200,240,200)),
("🥜 Nuts", (240,220,180)), ("🍊 Citrus Fruits", (255,230,180)),
("🫐 Berries", (220,200,240)), ("🥚 Eggs", (255,245,200))]
fcols = 3
fw, fh = 290, 130
for i, (food, fc) in enumerate(good_foods):
fx = P2X + PAD + (i % fcols) * (fw + 20)
fy = my + (i // fcols) * (fh + 15)
draw_rounded_rect(draw, (fx, fy, fx+fw, fy+fh), 12, fill=fc)
f_fi = load_font(44)
bb = draw.textbbox((0,0), food, font=f_fi)
draw.text((fx + fw//2-(bb[2]-bb[0])//2, fy+fh//2-(bb[3]-bb[1])//2),
food, fill=BLACK, font=f_fi)
my += 2*(fh+15) + 30
# Food to Avoid header
draw.text((P2X+170, my), "Food to be avoid", fill=BLACK, font=f_food_title)
my += 70
# Pink background panel for avoid foods
draw.rectangle([P2X+PAD, my, P2X+W_PANEL-PAD, my+300], fill=(250,210,200))
bad_foods = [("🚬 Smoke/Fumes", "Avoid all"), ("🧂 Salty Foods", "Causes water retention"),
("🥛 Dairy", "Increases mucus"), ("🍺 Alcohol", "Weakens immunity"),
("🌶️ Spicy Foods", "Triggers cough"), ("🍞 Processed Foods", "Inflammation")]
f_bf = load_font(34)
for i, (food, tip) in enumerate(bad_foods):
bfx = P2X + PAD + 20 + (i%2)*450
bfy = my + 20 + (i//2)*95
draw.text((bfx, bfy), food, fill=(160,20,20), font=load_font(36, bold=True))
draw.text((bfx, bfy+40), tip, fill=(80,20,20), font=f_bf)
my += 330
# ─── College credentials block ──────────────────────────────────────────
# College logo placeholder circle
draw.ellipse([P2X+80, my+10, P2X+180, my+110], fill=TEAL, outline=CORAL, width=6)
f_logo = load_font(50)
draw.text((P2X+98, my+28), "UCP", fill=WHITE, font=f_logo)
f_coll = load_font(48, bold=True)
draw.text((P2X+200, my+10), "UNITED COLLEGE OF", fill=CORAL, font=f_coll)
draw.text((P2X+300, my+62), "PHARMACY", fill=CORAL, font=f_coll)
my += 130
f_place = load_font(38)
draw.text((P2X+150, my), "Periyanaickenpalayam, Coimbatore", fill=TEAL_DARK, font=f_place)
my += 55
# Department info
f_dept = load_font(34, bold=True)
depts = ["DEPARTMENT OF PHARMACY PRACTICE",
"PHARMACOTHERAPEUTICS",
"PATIENT COUNSELLING LEAFLET"]
for d in depts:
bb = draw.textbbox((0,0), d, font=f_dept)
draw.text((P2X + W_PANEL//2-(bb[2]-bb[0])//2, my), d, fill=ORANGE, font=f_dept)
my += 45
my += 20
# Presented by
f_pb = load_font(44, bold=True)
draw.text((P2X+260, my), "PRESENTED BY:", fill=BLACK, font=f_pb)
my += 55
# NAME – J.JERO.F.SHERIN
f_name = load_font(52, bold=True)
draw.text((P2X+160, my), "J.JERO.F.SHERIN", fill=DARK_BLUE, font=f_name)
my += 60
f_pharmd = load_font(48, bold=True)
draw.text((P2X+300, my), "PHARM D", fill=DARK_BLUE, font=f_pharmd)
my += 65
draw.text((P2X+290, my), "GUIDANCE:", fill=BLACK, font=f_pb)
my += 55
f_guide = load_font(36, bold=True)
draw.text((P2X+80, my), "Dr.R.DINESH KUMAR, B.pharm., PharmD(PB)", fill=TEAL_DARK, font=f_guide)
my += 50
draw.text((P2X+290, my), "APPROVED BY:", fill=BLACK, font=f_pb)
my += 50
draw.text((P2X+80, my), "Dr.M.ALAGAR RAJA, M.pharm., PhD", fill=TEAL_DARK, font=f_guide)
my += 55
f_principal = load_font(42, bold=True)
draw.text((P2X+320, my), "PRINCIPAL", fill=BLACK, font=f_principal)
my += 50
draw.text((P2X+100, my), "UNITED COLLEGE OF PHARMACY", fill=BLACK, font=f_principal)
return img
# ════════════════════════════════════════════════════════════════════════════
# BACK SIDE (Panel 4=Types/S&S | Panel 5=Causes/Diagnosis | Panel 6=Complications)
# ════════════════════════════════════════════════════════════════════════════
def build_back():
img = Image.new("RGB", (FULL_W, H), CREAM)
draw = ImageDraw.Draw(img)
PAD = 40
P1X = 0
P2X = W_PANEL
P3X = W_PANEL*2
draw.line([(W_PANEL, 0), (W_PANEL, H)], fill=(200,200,200), width=4)
draw.line([(W_PANEL*2, 0), (W_PANEL*2, H)], fill=(200,200,200), width=4)
# ═══════════════════════════════════════════════
# PANEL 4 – TYPES + SIGNS & SYMPTOMS
# ═══════════════════════════════════════════════
y = 30
# TYPES header
section_header(draw, P1X+PAD, y, P1X+W_PANEL-PAD, y+90, "TYPES",
bg=CORAL, font=load_font(62, bold=True))
y += 110
f_type_title = load_font(42, bold=True)
draw.text((P1X+200, y), "Types of COPD", fill=BLACK, font=f_type_title)
draw.line([(P1X+PAD, y+56), (P1X+W_PANEL-PAD, y+56)], fill=(180,180,180), width=3)
y += 75
types = [
("Chronic Bronchitis", "Persistent cough, excess mucus,\nairway inflammation"),
("Emphysema", "Alveolar wall destruction,\nair trapping, barrel chest"),
("Asthma-COPD Overlap", "Features of both asthma and\nCOPD – persistent airflow limit."),
("Bronchiectasis", "Airway dilation, recurrent\ninfection, copious sputum"),
]
f_tt = load_font(38, bold=True)
f_tb = load_font(32)
for tname, tdesc in types:
# colored label box
draw_rounded_rect(draw, (P1X+PAD, y, P1X+W_PANEL-PAD, y+50), 8, fill=TEAL)
draw.text((P1X+PAD+20, y+8), tname, fill=WHITE, font=f_tt)
y += 58
for line in tdesc.split("\n"):
draw.text((P1X+PAD+20, y), line, fill=(60,60,60), font=f_tb)
y += 38
y += 12
y += 20
# SIGNS & SYMPTOMS header (teal BG, like reference)
section_header(draw, P1X+PAD, y, P1X+W_PANEL-PAD, y+90, "SIGNS & SYMPTOMS",
bg=TEAL, font=load_font(50, bold=True))
y += 110
symptoms = [
("🌬️", "Shortness of Breath", "Especially on exertion"),
("🤧", "Chronic Cough", "Productive with mucus"),
("🎵", "Wheezing", "High-pitched breathing sound"),
("😫", "Chest Tightness", "Pressure or heaviness"),
("💧", "Excess Mucus/Sputum", "Clear, yellow or green"),
("🔵", "Cyanosis", "Blue lips/fingertips (severe)"),
("😴", "Fatigue", "Due to low oxygen levels"),
("⚖️", "Weight Loss", "Common in advanced COPD"),
]
f_sh = load_font(40, bold=True)
f_sb = load_font(32)
for icon, sym, detail in symptoms:
draw.text((P1X+PAD, y), icon, fill=TEAL_DARK, font=load_font(44))
draw.text((P1X+PAD+70, y+2), sym, fill=DARK_BLUE, font=f_sh)
draw.text((P1X+PAD+70, y+46), detail, fill=(80,80,80), font=f_sb)
y += 95
# ═══════════════════════════════════════════════
# PANEL 5 – CAUSES + DIAGNOSIS
# ═══════════════════════════════════════════════
cx_mid = P2X + PAD
my = 30
# CAUSES header – pink/coral
section_header(draw, P2X+PAD, my, P2X+W_PANEL-PAD, my+90, "CAUSES",
bg=CORAL, font=load_font(62, bold=True))
my += 110
# causes pink box
draw.rectangle([P2X+PAD, my, P2X+W_PANEL-PAD, my+560], fill=(245,200,195))
causes = [
("🚬", "Cigarette Smoking", "Primary cause – ~80-90% of cases"),
("🏭", "Air Pollution", "Industrial fumes, biomass smoke"),
("💨", "Occupational Dust", "Coal, silica, cotton dust"),
("🧬", "Alpha-1 Deficiency", "Genetic risk – rare"),
("😷", "Respiratory Infect.", "Recurrent childhood infections"),
("🌫️", "Indoor Pollutants", "Burning wood/coal indoors"),
]
f_ch = load_font(38, bold=True)
f_cb = load_font(30)
icol = 2
iw = (W_PANEL-2*PAD-20)//icol
for i, (icon, name, detail) in enumerate(causes):
cx2 = P2X + PAD + 10 + (i%icol)*iw
cy2 = my + 15 + (i//icol)*180
draw.text((cx2, cy2), icon, fill=DARK_BLUE, font=load_font(54))
draw.text((cx2, cy2+60), name, fill=(140,20,20), font=f_ch)
lines2 = detail.split(" – ")
ty2 = cy2+100
for ln in lines2:
draw.text((cx2, ty2), ln, fill=(80,20,20), font=f_cb)
ty2 += 34
my += 580
# DIAGNOSIS header
section_header(draw, P2X+PAD, my, P2X+W_PANEL-PAD, my+90, "DIAGNOSIS",
bg=CORAL, font=load_font(58, bold=True))
my += 110
diagnoses = [
("🌬️", "Spirometry (PFTs)", "FEV₁/FVC < 0.70 confirms COPD"),
("📋", "Medical History", "Smoking, occupational exposure"),
("🫁", "Chest X-Ray", "Hyperinflation, flat diaphragm"),
("🔬", "CT Scan", "Gold standard – emphysema extent"),
("🩸", "Arterial Blood Gas", "pO₂, pCO₂, pH – severe disease"),
("🧪", "Sputum Culture", "Identify infectious organisms"),
("❤️", "6-Min Walk Test", "Functional exercise capacity"),
("💡", "Pulse Oximetry", "SpO₂ monitoring & titration"),
]
f_dh = load_font(36, bold=True)
f_db = load_font(30)
for icon, name, detail in diagnoses:
draw.text((P2X+PAD, my), icon, fill=TEAL, font=load_font(44))
draw.text((P2X+PAD+70, my+2), name, fill=DARK_BLUE, font=f_dh)
draw.text((P2X+PAD+70, my+42), detail, fill=(80,80,80), font=f_db)
my += 88
# ═══════════════════════════════════════════════
# PANEL 6 – COMPLICATIONS + INHALER USE
# ═══════════════════════════════════════════════
ry = 30
# COMPLICATION header
section_header(draw, P3X+PAD, ry, P3X+W_PANEL-PAD, ry+90, "COMPLICATION",
bg=CORAL, font=load_font(54, bold=True))
ry += 110
# Pink complication box
draw.rectangle([P3X+PAD, ry, P3X+W_PANEL-PAD, ry+700], fill=(240,195,195))
complications = [
("Respiratory Failure", "Hypoxemia and hypercapnia"),
("Pulmonary Hypertension", "Right heart overload"),
("Cor Pulmonale", "Right ventricular enlargement"),
("Pneumothorax", "Ruptured emphysematous bullae"),
("Depression & Anxiety", "Chronic disease burden"),
("Polycythemia", "Compensatory RBC increase"),
("Cachexia", "Malnutrition, muscle wasting"),
]
f_comp_h = load_font(38, bold=True)
f_comp_b = load_font(30)
for i, (comp, detail) in enumerate(complications):
cy3 = ry + 15 + i*96
draw.text((P3X+PAD+10, cy3), f"• {comp}", fill=(150,20,20), font=f_comp_h)
draw.text((P3X+PAD+35, cy3+44), detail, fill=(80,20,20), font=f_comp_b)
ry += 720
# HOW TO USE INHALER header
section_header(draw, P3X+PAD, ry, P3X+W_PANEL-PAD, ry+90, "HOW TO USE INHALER",
bg=(190, 120, 60), font=load_font(44, bold=True))
ry += 110
steps = [
("1", "Shake the inhaler 4-5 times before use"),
("2", "Exhale fully, away from the inhaler"),
("3", "Place mouthpiece between lips, seal tightly"),
("4", "Press & inhale slowly and deeply (3-5 sec)"),
("5", "Hold breath for 10 seconds"),
("6", "Wait 30 sec between puffs if needed"),
("7", "Rinse mouth after corticosteroid inhalers"),
]
f_sn = load_font(42, bold=True)
f_sd = load_font(34)
for num, text in steps:
# Step number circle
draw.ellipse([P3X+PAD, ry, P3X+PAD+60, ry+60], fill=TEAL)
bb = draw.textbbox((0,0), num, font=f_sn)
draw.text((P3X+PAD+30-(bb[2]-bb[0])//2, ry+30-(bb[3]-bb[1])//2),
num, fill=WHITE, font=f_sn)
wrap_text(draw, text, P3X+PAD+75, ry+8, W_PANEL-PAD-80, f_sd, fill=BLACK, line_spacing=5)
ry += 80
return img
# ── Save outputs ─────────────────────────────────────────────────────────────
front = build_front()
back = build_back()
front.save("/tmp/workspace/copd-pamphlet/COPD_Pamphlet_Front.jpg", "JPEG", quality=95)
back.save( "/tmp/workspace/copd-pamphlet/COPD_Pamphlet_Back.jpg", "JPEG", quality=95)
print("Done! Saved front and back.")
cd /tmp/workspace/copd-pamphlet && python3 create_pamphlet.py 2>&1
ls -lh /tmp/workspace/copd-pamphlet/ && python3 -c " from PIL import Image front = Image.open('/tmp/workspace/copd-pamphlet/COPD_Pamphlet_Front.jpg') back = Image.open('/tmp/workspace/copd-pamphlet/COPD_Pamphlet_Back.jpg') print('Front size:', front.size) print('Back size:', back.size) # Save combined PDF front_rgb = front.convert('RGB') back_rgb = back.convert('RGB') front_rgb.save('/tmp/workspace/copd-pamphlet/COPD_Pamphlet_Complete.pdf', save_all=True, append_images=[back_rgb]) print('PDF saved.') "
COPD Pamphlet Front
Image · JPG
COPD Pamphlet Back
Image · JPG
COPD Pamphlet Complete
PDF Document · PDF