Generating a pdf from an image using PIL and django

By : Saket Bhushan

In this post we shall be performing small image manipulation on the server side and allowing the user to download the pdf. This might be found useful if you design a quiz app and want to generate a certificate for the users. The various methods which can be followed to generate the certificate are:

  1. Have an image file to serve as a template, use css to place the username at the desired location.
  2. Have a pdf file, which can be edited to take the username of the current user if he has passed certain test.
  3. Have an image template ready, upon which we could do some image manipulation to add the user's name at a specified location and render it.

You might think why not to render the entire certificate from pure html/css but putting the signature and logo are tough that way, which is a pre-requisite for a certificate, hence choosing any of the above methods might be something that you want to go about.

Initially we went for the first method, we used pisa library, but the results were not satisfactory, when we tried to render html text over png image and then generate the pdf.

If you want to choose the second method the relevant libraries which can be thought of are: pyPDF and ReportLab, but as per this stackoverflow post things can get trivial if we use this method eventually we went with the third approach, which helped us. The libraries which we used were PIL and imagemagick.

The code is pretty much self explanatory, inside your views use the following snippets:

import PIL
from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw
# subprocess will be used to run command line arguments
import subpprocess

def download(request):
    # set the path to the font and the font size    
    font = ImageFont.truetype("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf", 20)
    text = "Sample Text which you want to display"
    # the rgb value of the color    
    tcolor = (255, 0, 0)
    # the position of the image where you intend to print the stuff
    text_pos = (100,500)
    '''open the image file in RGB format, this is important if we miss 
 convert it wont take the color(RGB) parameter and error will be thrown ''' 
    img ="path_to_file/certificate.png").convert('RGB')
    draw = ImageDraw.Draw(img)
    draw.text(text_pos, text, fill=tcolor, font=font)
    del draw
    # save the manipulated image as the next file"path_to_image/test.png")
    # we want to send a pdf 
    response = HttpResponse(mimetype='application/pdf')
    filename = "certificate"
    response['Content-Disposition'] = 'attachment; filename=%s.pdf' % filename
    # here we use imagemagick to convert png image to certificate
    ret =["convert", "path_to_file/test.png", "path_to_file/certificate.pdf" ],\
    certi = open("path_to_file/certificate.pdf")
    return response

This seems to solve our problem, however there can be another better approach, readers are welcome to post their views/suggestions or a different/better methodology.

Can we help you build amazing apps? Contact us today.

© Agiliq, 2009-2012