Image aspect ratio using Reportlab in Python

21,639

Solution 1

You can use the original image's size to calculate its aspect ratio, then use that to scale your target width, height. You can wrap this up in a function to make it reusable:

from reportlab.lib import utils

def get_image(path, width=1*cm):
    img = utils.ImageReader(path)
    iw, ih = img.getSize()
    aspect = ih / float(iw)
    return Image(path, width=width, height=(width * aspect))

story = []
story.append(get_image('stack.png', width=4*cm))
story.append(get_image('stack.png', width=8*cm))
frame.addFromList(story, c)

Example using a 248 x 70 pixel stack.png:

enter image description here

Solution 2

i had a similar problem and i think this works:

   image = Image(absolute_path)
   image._restrictSize(1 * inch, 2 * inch)
   story.append(image)

I hope this helps!

Share:
21,639
citn
Author by

citn

Updated on July 14, 2022

Comments

  • citn
    citn almost 2 years

    I want to insert an image inside a frame. I found two ways to do this:

    1. drawImage(self, image, x, y, width=None, height=None, mask=None, preserveAspectRatio=False, anchor='c')
    2. Image(filename, width=None, height=None)

    My question is: how can I add an image in a frame while preserving its aspect ratio?

    from reportlab.lib.units import cm
    from reportlab.pdfgen.canvas import Canvas
    from reportlab.platypus import Frame, Image
    
    c = Canvas('mydoc.pdf')
    frame = Frame(1*cm, 1*cm, 19*cm, 10*cm, showBoundary=1)
    
    """
    If I have a rectangular image, I will get a square image (aspect ration 
    will change to 8x8 cm). The advantage here is that I use coordinates relative
    to the frame.
    """
    story = []
    story.append(Image('myimage.png', width=8*cm, height=8*cm))
    frame.addFromList(story, c)
    
    """
    Aspect ration is preserved, but I can't use the frame's coordinates anymore.
    """
    c.drawImage('myimage.png', 1*cm, 1*cm, width=8*cm, preserveAspectRatio=True)
    
    c.save()
    
  • citn
    citn about 13 years
    Thanks for this workaround. I hope someone will add this to the API.
  • jimh
    jimh almost 8 years
    This is the best answer to this question. There are similar questions we should be merging into this one.
  • Glrs
    Glrs over 3 years
    Great! I just added **kwargs to maintain any extra features you want to pass. It looks like this: def get_image(path, width=1*cm, **kwargs) and return Image(path, width=width, height=(width * aspect), **kwargs). So now I can do get_image('stack.png', width=8*cm, hAligh='CENTER')