Mike Driscoll: Rotating Images in ReportLab

There are times when you want to rotate images or other objects in ReportLab while creating a PDF. For example, you might want to rotate an image by 45 degrees for watermarking purposes. Or you might need an image that runs vertically along one of the edges of the PDF.

You can rotate images by using ReportLab’s canvas methods or by using its higher level Flowables that you can find in the platypus. module. Let’s start by looking at how to do this with the canvas directly!

Rotating Images Using Canvas

Rotating images using the canvas is kind of confusing. The reason being that when you rotate the canvas, you may end up inadvertently rotating other elements on your canvas if you’re not careful.

Let’s take a look at the code:

# image_on_canvas.py   from reportlab.lib import utils from reportlab.lib.pagesizes import letter from reportlab.pdfgen import canvas     def add_image(image_path):     img = utils.ImageReader(image_path)     img_width, img_height = img.getSize()     aspect = img_height / float(img_width)       my_canvas = canvas.Canvas("canvas_image.pdf",                               pagesize=letter)     my_canvas.saveState()     my_canvas.rotate(45)     my_canvas.drawImage(image_path, 150, 10,                         width=100, height=(100 * aspect))     my_canvas.restoreState()     my_canvas.save()   if __name__ == '__main__':     image_path = 'snakehead.jpg'     add_image(image_path)

Here you use ReportLab’s utils function to extract the image’s width and height. Then you create the canvas and save its current state. This will allow you to modify the canvas from this point forward and then restore it later. If you’d like to have some text or shapes before the rotated image, you would put that code before the call to saveState().

After saving the canvas state, you can use the canvas’s rotate() method to rotate the canvas 45 degrees. Then you draw the image to the canvas. Finally you use restoreState() to restore the state back to what it was before you rotated it.

Note: When rotating the canvas, the x/y position is now at a 45 degree angle, so you will have to take that into account while positioning the image on your canvas.

When I ran this code, I ended up with a document that looked like this:

Rotated image with ReportLab

You can also download the PDF here.

Now let’s find out how to do the same thing using a Flowable!

Rotating Images Using the Image Flowable

Flowables are objects in ReportLab that come from their platypus module, which stands for Page Layout and Typography Using Scripts. This module is basically a high-level interface to the canvas methods that abstracts the drawing bits away and makes creating multipage documents much simpler.

The quickest way to create a rotated image using a Flowable in ReportLab is to subclass the Image Flowable. Let’s take a look!

from reportlab.lib.pagesizes import letter from reportlab.platypus import Image, SimpleDocTemplate   class RotatedImage(Image):       def wrap(self, availWidth, availHeight):         height, width = Image.wrap(self, availHeight, availWidth)         return width, height       def draw(self):         self.canv.rotate(45)         Image.draw(self)   doc = SimpleDocTemplate("image_with_rotation.pdf", pagesize=letter) flowables = []   img = RotatedImage('snakehead.jpg',                    width=50, height=50                    ) img.hAlign = 'CENTER' flowables.append(img) doc.build(flowables)

Here you subclass Image and override the wrap() and draw() methods. The main piece that you will care about is in the draw() method where you call self.canv.rotate(45). The Image class has its own canvas in it that you can manipulate. In this case, you tell it that you want to always draw the image at a 45 degree angle.

Next you create a document template and create an instance of RotatedImage. Then you tell the image to be centered on the page. Finally you build() the document.

When you run this code, you should see the following:

Rotated image with ReportLab Flowable

You can get the actual PDF here if you’d rather see the file.

Wrapping Up

Now you know how to rotate images using ReportLab. You learned how to rotate an image using the low-level canvas methods and you also learned how to rotate an Image Flowable. You can use this knowledge to rotate other kinds of objects as well. For example, you can rotate text and shapes using the same methodology. You will always be rotating the canvas to get the needed effect. Have fun and happy coding!

Want to learn more about working with PDFs in Python? Then check out my book:

ReportLab: PDF Processing with Python

Purchase now on Leanpub

Related Reading

The post Rotating Images in ReportLab appeared first on The Mouse Vs. The Python.

Planet Python

Mike Driscoll: Lucid Programming Podcast – Writing Books About Python

I was recently interviewed on the Lucid Programming Podcast by Vincent Russo about writing books about Python.

You can listen to the audio here:

If you’d like to know more about how I write books, you might enjoy this article I wrote on the topic. I also wrote an article on the Pros and Cons of Indy Publishing.

Last week, I was honored to be on the Profitable Python podcast.

Related Podcasts

Other podcasts I have been on:

The post Lucid Programming Podcast – Writing Books About Python appeared first on The Mouse Vs. The Python.

Planet Python

Mike Driscoll: New Malicious Python Libraries Found Targeting Linux

ZDNet published an article recently about a newly discovered set of malware-related Python packages on the Python Package Index (PyPI). These packages contained a backdoor that would only activate when installed on Linux.

These packages were named:

  • libpeshnx
  • libpesh
  • libar

They were written by a user named ruri12. These packages were removed by the PyPI team on July 9, 2019. However they were available since November 2017 and had been downloaded fairly regularly.

See the original article for more details.

As always, when using a package that you aren’t familiar with, be sure to do your own thorough vetting to be sure you are not installing malware accidentally.

Related Reading

The post New Malicious Python Libraries Found Targeting Linux appeared first on The Mouse Vs. The Python.

Planet Python

Mike Driscoll: Intro to Black – The Uncompromising Python Code Formatter

There are several Python code checkers available. For example, a lot of developers enjoy using Pylint or Flake8 to check their code for errors. These tools use static code analysis to check your code for bugs or naming issues. Flake8 will also check your code to see if you are adhering to PEP8, Python’s style guide.

However there is a new tool that you can use called Black. Black is a Python code formatter. It will reformat your entire file in place according to the Black code style, which is pretty close to PEP8.


Installing Black is easy. You can just use pip for that:

pip install black

Now that it’s installed, let’s give Black a try!

Using Black

Black requires you to have some code to run it against. Let’s create a simple function that has lots of parameters and then run Black on that script.

Here’s an example:

def long_func(x, param_one=None, param_two=[], param_three={}, param_four=None, param_five="", param_six=123456):     print("This function has several params")

Now in your terminal, try running black against your code file like this:

black long_func.py

When you run this command, you should see the following output:

reformatted long_func.py
All done! ✨ 🍰 ✨
1 file reformatted.

This means that your file has been reformatted to follow the Black standard.

Let’s open the file up and see what it looks like:

def long_func(     x,     param_one=None,     param_two=[],     param_three={},     param_four=None,     param_five="",     param_six=123456, ):     print("This function has several params")

As you can see, Black has put each of the parameters on their own line.

Checking Files for Formatting

If you don’t want Black to change your file, but you want to know if Black thinks a file should be changed, you can use one of the following command flags:

  • –check – which checks if the file should be reformatted, but doesn’t actually modify the file
  • –diff – which writes out a diff of what Black would do to the file, but doesn’t modify the file

I like to use these to do a test run on my files and see how Black will reformat my code. I haven’t been using Black a long time, so this let’s me see if I like what Black is going to do without actually doing anything.

Wrapping Up

I like Black. I think it could be really useful, especially in an organization when it comes to enforcing a certain Python style. Note that Black defaults to 88 characters for its line length, but you can change that using -l or --line-length if you need to. There are also a few other options you might find useful listed on the project’s page. If you get a chance, I think you should give Black a try!

Related Reading

The post Intro to Black – The Uncompromising Python Code Formatter appeared first on The Mouse Vs. The Python.

Planet Python

Mike Driscoll: Book Contest: Jupyter Notebook 101

Last year, I released a book entitled Jupyter Notebook 101. In celebration of a successful launch, I have decided to do a little contest.


  • Tweet about why you’d want to win the book and include my handle: @driscollis
  • Send me a direct message on Twitter or via my contact form with a link to your Tweet
  • If you don’t have Twitter, feel free to message me through the website to tell me why you’d like a copy

The contest will run starting now until Thursday, July 4th @ 11:59 p.m. CST.

Runners up will receive a free copy of the eBook. The grand prize will be a signed paperback copy + the eBook version!

The post Book Contest: Jupyter Notebook 101 appeared first on The Mouse Vs. The Python.

Planet Python