Code to generate a PDF greeting card using a user specified image, and text.
You can try it out online here: http://utilitymill.com/utility/Greeting_Card_Generator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | from cStringIO import StringIO
from reportlab import rl_config
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.units import inch
from reportlab.lib.colors import black,white,red,pink,green,blue,yellow,lightgrey
from PIL import Image
width, height = letter #keep for later
def add_fold_lines(c):
"""Add lines to show where to fold card"""
# choose some colors
c.setFillColor(lightgrey)
# line settings
c.setLineWidth(1)
c.setDash(1,5) #n points on, m off
# draw some lines
c.line(width/2,0,width/2,height) #vertical
c.line(0,height/2,width,height/2) #horz.
def put_in_front_picture(c,str_img,img_url):
assert not (str_img and img_url)
if img_url:
import urllib2
data=urllib2.urlopen(img_url).read()
else:
data=str_img
image_file = StringIO(data)
img = Image.open(image_file)
#resize image:
img=img.resize((width/2,height/2),Image.BILINEAR)
#c.drawImage caused AttributeError: jpeg_fh
c.drawInlineImage(img, x=width/2,y=0, width=width/2,
height=height/2)
def write_text(c,front_text,inside_text):
#call canvas.getAvailableFonts() to see all fonts
# change color
c.setFillColor(COLOR_FRONT)
c.setFont("Helvetica", 28)
line_pos=int(.4*height)
for line in front_text.split('\n'):
c.drawCentredString(3*(width/4), line_pos, line)
line_pos-=int(.05*height)
c.setFillColor(black)
c.setFont("Helvetica", 16)
c.rotate(180) #write text upside down so it's right when folded.
line_pos=-3*(height/4)
for line in inside_text.split('\n'):
c.drawCentredString(-width/4, line_pos, line)
line_pos-=int(.05*height)
#write branding text
c.rotate(180) #put back to right side up
c.setFont("Helvetica", 8)
c.drawCentredString(width/4, int(.13*height),
"Created while fondly thinking of you at")
c.drawCentredString(width/4, int(.1*height),
"http://utilitymill.com/utility/Greeting_Card_Generator")
def generate_card(IMG_FILE,IMG_URL,TEXT_FRONT,TEXT_INSIDE):
"""Main function to generate PDF and print to stdout. Designed to be
run as a CGI application."""
if not (IMG_FILE or IMG_URL):
print 'You must upload an image file or provide a URL to one'
return
tmp = StringIO()
#Canvas Setup
c = canvas.Canvas(tmp, pagesize=letter, pageCompression=0)
#If output size is important set pageCompression=1, but remember that, compressed documents
#will be smaller, but slower to generate. Note that images are always compressed, and this option will only
#save space if you have a very large amount of text and vector graphics on each page.
#Do I need 'MacRomanEncoding' for Macs?
#Note: 0,0 coordinate in canvas is bottom left.
c.setAuthor('Utility Mill - utilitymill.com/utility/greeting_card_generator')
c.setTitle('Beautiful, expensive greeting card created at utilitymill.com')
#add_fold_lines(c) #early feedback says lines aren't necessary. Uncomment here to put them in
put_in_front_picture(c,IMG_FILE,IMG_URL)
write_text(c,TEXT_FRONT.replace('\r',''),TEXT_INSIDE.replace('\r',''))
#The showPage method saves the current page of the canvas
c.showPage()
#The save method stores the file and closes the canvas.
c.save()
tmp.seek(0)
print 'Content-Type: application/pdf'
print tmp.read()
generate_card(IMG_FILE,IMG_URL,TEXT_FRONT,TEXT_INSIDE)
|
Hopefully this is an instructive example of using ReportLab's PDF toolkit. And maybe it will even save you money on greeting cards.
You can always see the latest version of this code here: http://utilitymill.com/edit/Greeting_Card_Generator and update it there if you have improvements.
Notes: 1. If you're European, you may want to change the paper size to A4? 2. I haven't tested the generated PDF's on Macs. Do they need any special fonts? 3. This was designed to be run on a server and thus it prints the output to stdout as a CGI script would do. You could easily modify it to save a file instead if you want to run it locally.