servoz
servoz

Reputation: 657

A simple method for rotating images in reportlab

How can we easily rotate an image using reportlab? I have not found an easy method. The only way found comes from http://dods.ipsl.jussieu.fr/orchidee/SANORCHIDEE/TEMP/TEMP_LOCAL/cdat_portable/lib_new_wrong_gcc/python2.4/site-packages/reportlab/test/test_graphics_images.py using for example:

>>> from reportlab.graphics.shapes import Image, Drawing
>>> from reportlab.platypus import SimpleDocTemplate
>>> from reportlab.lib.pagesizes import A4, portrait
>>> from reportlab.lib.units import mm
>>> img = Image(-202/25.4, -125/25.4, 210/25.4, 138/25.4, 'uneBelleImage.png') # (x, y [from lower left corner], width, height, path, **kw)
>>> d = Drawing(0, 0) # (width, height, *nodes, **keywords)
>>> d.add(img)
>>> d.scale(100,100) #(%width, %height)
>>> d.rotate(90)
>>> report=[]
>>> report.append(d)
>>> page = SimpleDocTemplate('toto.pdf', pagesize = portrait(A4), rightMargin=20*mm, leftMargin=20*mm, topMargin=10*mm, bottomMargin = 10*mm)
>>> page.build(report)

This is working, but it is using a sledgehammer to crack a nut. Is there a more direct method, using for example the classical reportlab.platypus.Image?

Upvotes: 6

Views: 4885

Answers (2)

Jean-Francois T.
Jean-Francois T.

Reputation: 12940

Another alternative is to perform the transformation in PIL using img.transpose (https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.transpose) and add the transformed image.

Worked better for me:

from dataclasses import dataclass
from pathlib import Path

from PIL import Image
from reportlab.lib.utils import ImageReader
from reportlab.pdfgen.canvas import Canvas


@dataclass
class Position:
    """Information for a position"""

    x: float
    y: float
    width: float
    height: float


def write_image(canvas: Canvas, img: Path, pos: Position) -> None:
    """Put an image at a given position"""
    # As the canvas might be upside down, we need to flip the image vertically
    # The easiest way seems to be using PIL (Flowable seems a bit complicated)
    im = Image.open(img).transpose(Image.FLIP_TOP_BOTTOM)

    y = canvas._pagesize[1] - pos.y if canvas.bottomup else pos.y
    canvas.drawImage(ImageReader(im), pos.x, y, width=pos.width, height=pos.height)


c = Canvas("my_report.pdf", bottomup=0)
pos = Position(100, 100, 20, 30)
write_image(c, Path("my_image.png"), pos)
c.save()

Upvotes: 4

Mir Ilias
Mir Ilias

Reputation: 515

to modify an existing flowable, you should create a derived class and override the methods you need to change to get the desired behaviour. So, to create a rotated image you need to override the wrap and draw methods of the existing Image class like this :

from reportlab.platypus.flowables import Image

class RotatedImage(Image):

    def wrap(self,availWidth,availHeight):
        h, w = Image.wrap(self,availHeight,availWidth)
        return w, h
    def draw(self):
        self.canv.rotate(90)
        Image.draw(self)

I = RotatedImage('../images/somelogo.gif')

Upvotes: 5

Related Questions