Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to add a border to an image in ReportLab?

I'm building a PDF for some products that include images. A lot of these images have a white background so I would really like to add borders around them. I'm given an image url when creating the PDF, which I can pass directly to reportlab's Image() and it'll display it just fine. It's getting a border around it that's the tricky part.

After looking through ReportLab's userguide, Image() doesn't have the capability of applying a border directly. So there are a few tricks I thought I would attempt to see if I can simulate a border around the images.

At first, I figured creating frames for each image would not only be a pain, but the border for frames are just solid black lines for debugging and can't be customized in any way. I would like to be able to change the thickness and color of the border, so that option's not promising.

Then I noticed that Paragraph() is able to take a ParagraphStyle() which can apply certain styles, including a border. Image() doesn't have a ParagraphStyle() equivalent, so I thought maybe I could use Paragraph() instead by creating a string that contains an XML 'img' tag with the image url I have, then apply the ParagraphStyle() to it with a border. That approach successfully shows the images, but still no border :( Simple example code for that below:

from reportlab.platypus import Paragraph
from reportlab.lib.styles import Paragraph Style

Paragraph(
    text='<img src="http://placehold.it/150x150.jpg" width="150" height="150" />',
    style=ParagraphStyle(
        name='Image',
        borderWidth=3,
        borderColor=HexColor('#000000')
    )
)

I also tried searching to see if XML had a way to inline a style for a border, but didn't find anything.

Any suggestions appreciated! Thanks :) And let me know if it's not even possible if that's the case!

SOLUTION:

With G Gordon Worley III's idea, I was able to write a solution that works! Here's an example:

from reportlab.platypus import Table

img_width = 150
img_height = 150
img = Image(filename='url_of_img_here', width=img_width, height=img_height)
img_table = Table(
    data=[[img]],
    colWidths=img_width,
    rowHeights=img_height,
    style=[
        # The two (0, 0) in each attribute represent the range of table cells that the style applies to. Since there's only one cell at (0, 0), it's used for both start and end of the range
        ('ALIGN', (0, 0), (0, 0), 'CENTER'),
        ('BOX', (0, 0), (0, 0), 2, HexColor('#000000')), # The fourth argument to this style attribute is the border width
        ('VALIGN', (0, 0), (0, 0), 'MIDDLE'),
    ]
)

Then just add img_table to your list of flowables :)

like image 308
missmely Avatar asked Oct 22 '22 05:10

missmely


1 Answers

I think the approach you should take is to put the image inside of a table. Table styles work very well for what you want to do and provide a lot of flexibility. You just need a 1 by 1 table with the image displayed inside the only cell in the table.

like image 58
G Gordon Worley III Avatar answered Oct 24 '22 10:10

G Gordon Worley III