Включение изображения в кодировке base64 в PDF-файл, сгенерированный ReportLab - PullRequest
3 голосов
/ 02 апреля 2012

Я пытаюсь декодировать изображение в кодировке base64 и поместить его в PDF-файл, созданный с помощью ReportLab. В настоящее время я делаю это так (image_data - это изображение в кодировке base64, story - это уже история ReportLab):

# There is some "story" I append every element
img_height = 1.5 * inch  # max image height
img_file = tempfile.NamedTemporaryFile(mode='wb', suffix='.png')
img_file.seek(0)
img_file.write(image_data.decode('base64'))
img_file.seek(0)
img_size = ImageReader(img_file.name).getSize()
img_ratio = img_size[0] / float(img_size[1])
img = Image(img_file.name,
    width=img_ratio * img_height,
    height=img_height,
)
story.append(img)

и это работает (хотя мне все еще некрасиво). Я думал о том, чтобы избавиться от временного файла (разве файловый объект не добился цели?).

Чтобы избавиться от временного файла, я попытался использовать модуль StringIO, чтобы создать файлоподобный объект и передать его вместо имени файла:

# There is some "story" I append every element
img_height = 1.5 * inch  # max image height
img_file = StringIO.StringIO()
img_file.seek(0)
img_file.write(image_data.decode('base64'))
img_file.seek(0)
img_size = ImageReader(img_file).getSize()
img_ratio = img_size[0] / float(img_size[1])
img = Image(img_file,
    width=img_ratio * img_height,
    height=img_height,
)
story.append(img)

Но это дает мне IOError со следующим сообщением: « не может идентифицировать файл изображения ».

Я знаю, что ReportLab использует PIL для чтения изображений, отличных от jpg, но есть ли способ избежать создания именованных временных файлов и делать это только с файловыми объектами, без записи файлов на диск?

Ответы [ 4 ]

2 голосов
/ 03 апреля 2012

Вы должны обернуть StringIO () на PIL.Image.open, так что просто img_size = ImageReader(PIL.Image.open(img_file)).getSize(). Это на самом деле тонкая оболочка вокруг Image.size, как предполагает ответ Томмазо. Кроме того, на самом деле нет необходимости самостоятельно рассчитывать размер desc, режим отчета bound. Image может сделать это за вас:

img_height = 1.5 * inch  # max image height
img_file = StringIO.StringIO(image_data.decode('base64'))
img_file.seek(0)
img = Image(PIL.Image.open(img_file),
            width=float('inf'),
            height=img_height,
            kind='bound')
)
story.append(img)
0 голосов
/ 03 июня 2019

Это решение работает для меня. Я использую Flask с Google App Engine.

from reportlab.platypus import Image
from reportlab.lib.units import mm
import cStringIO
from base64 import b64decode

story=[]
encoded_image = "...."
decoded_img = b64decode(encoded_image)
img_string = cStringIO.StringIO(decoded_img)
img_string.seek(0)
im = Image(img_string, 180*mm, 100*mm, kind='bound')
story.append(im)

Я получил изображение от клиента и сохранил в базе данных:

from base64 import b64decode
image = request.files['image'].read()
encoded_image = b64encode(image)
0 голосов
/ 19 ноября 2012

Этот код работает для меня без PIL, так как изображение уже в формате JPEG: raw просто вытаскивает строку base64 из словаря. Я просто оборачиваю декодированную «строку» в StringIO.

        raw = element['photographs'][0]['jpeg']
        photo = base64.b64decode(raw)
        c.drawImage(ImageReader(StringIO.StringIO(photo)), 0.5*inch, self.y, height = self.PHOTOHEIGHT, preserveAspectRatio = True)
0 голосов
/ 03 апреля 2012

Я не знаком с ReportLab, но если вы можете использовать PIL напрямую, это будет работать:

...
img = Image.open(img_file)
width, height = img.size
...

вы можете посмотреть здесь для класса PIL Image ссылки

...