Вставить изображение в Reportlab из PIL image или StringIO

Я пытаюсь вставить изображение штрих-кода в Reportlab. Я знаю, что есть много вопросов об этом, но все они предполагают что у вас уже есть файл изображения в папке или на файловой системе.

из-за того, что Reportlab имеет проблемы с штрих-кодами EAN13, я решил использовать другой пакет под названием pyBarcode для создания изображения для меня.

Первоначально я сохранил изображение в экземпляре StringIO и передал его непосредственно в reportlab.platypus.flowables.Image но похоже, это не сработало. Затем я прочитал документацию:

поддерживаются форматы, поддерживаемые Pil/Java 1.4 (библиотека изображений Python / Java).

означает ли это, что если я передаю изображение PIL, это должно работать? Я получил исключение, когда я попробовал следующее:

>>> import PIL
>>> from reportlab.platypus.flowables import Image
>>> fp = StringIO(the_barcode.getvalue())
>>> barcode_image = PIL.Image.open(fp)
>>> doc = SimpleDocTemplate('barcode.pdf')
>>> story = [Image(barcode_image)]
>>> Traceback (most recent call last):
  File "create.py", line 57, in <module>
    main()
  File "create.py", line 24, in main
    save_pdf(fp, STYLE, ART, COLOR, SIZE)
  File "create.py", line 28, in save_pdf
    fp = StringIO(fp.getvalue())
  File "/home/mark/.virtualenvs/barcode/local/lib/python2.7/site-packages/reportlab-2.6-py2.7-linux-i686.egg/reportlab/platypus/flowables.py", line 402, in __init__
    if not fp and os.path.splitext(filename)[1] in ['.jpg', '.JPG', '.jpeg', '.JPEG']:
  File "/home/mark/.virtualenvs/barcode/lib/python2.7/posixpath.py", line 95, in splitext
    return genericpath._splitext(p, sep, altsep, extsep)
  File "/home/mark/.virtualenvs/barcode/lib/python2.7/genericpath.py", line 91, in _splitext
    sepIndex = p.rfind(sep)
  File "/home/mark/.virtualenvs/barcode/local/lib/python2.7/site-packages/PIL/Image.py", line 512, in __getattr__
    raise AttributeError(name)
AttributeError: rfind

Как-то изображение PIL тоже не работает. Что я должен передать в качестве первого аргумента функции изображения Reportlab, если у меня нет имени файла изображения (потому что мои образы создаются в памяти)?

3 ответов


повторяющееся объявление "форматы, поддерживаемые Pil/Java 1.4 (библиотека изображений Python / Java), поддерживаются" просто означает, что форматы данных, поддерживаемые PIL поддерживает reportlab (так как он использует PIL читать их).

теперь, от подглядывания в reportlab.platypus.flowables.Image код можно увидеть, что он принимает в качестве входных данных либо имя файла, либо файловый объект. Первое-это не то, что вы хотите, поэтому давайте сосредоточимся на более позднем. Ты сказал StringIO кажется, не работает, но это так, если вы принимать какую-либо помощь. Вы, вероятно, сделали что-то не так с ним, вот два правильных способа использования StringIO:

import sys
import PIL
from cStringIO import StringIO
from reportlab.platypus.flowables import Image

# Method 1
data = open(sys.argv[1]).read()
img1 = StringIO(data)

# Method 2
img2 = StringIO()
PIL.Image.open(sys.argv[2]).save(img2, 'PNG')
img2.seek(0)

# Method 3 (fails)
img3 = StringIO(PIL.Image.open(sys.argv[2]).tostring())

story = [Image(img1), Image(img2)]
#Image(img3)

метод 3 терпит неудачу, потому что img3 теперь содержит необработанные данные изображения, поэтому он понятия не имеет о фактическом формате этих данных. Нет причин пытаться использовать этот метод для такой задачи.

если у вас есть необработанные данные, и вы знаете режим изображения ваших данных ("L", " RGB " и т. д.), а также его ширину, высоту, то вы можете использовать четвертый (правильный) метод on PIL.Image.fromstring(...).save(mystrio, 'someformat').


мне не повезло с предлагаемыми методами.

проверка кода в pdfdoc.py показывает, что AttributError является результатом обработки StringIO как имени файла:

    if source is None:
        pass # use the canned one.
    elif hasattr(source,'jpeg_fh'):
        self.loadImageFromSRC(source)   #it is already a PIL Image
    else:
        # it is a filename

дальнейшая проверка источника показывает, что jpeg_fh является атрибутом класса ImageReader в reportlab.движение за освобождение.а utils. ImageReader принимает изображения StringIO и PIL.

поэтому обертывание StringIO в ImageReader решило проблему для меня:

import PIL
from reportlab.lib.utils import ImageReader

io_img = StringIO(data)
pil_img = PIL.Image.open(StringIO(data))

reportlab_io_img = ImageReader(io_img)
reportlab_pil_img = ImageReader(pil_img)

canvas.drawImage(reportlab_io_img, ...)
canvas.drawImage(reportlab_pil_img, ...)

Я считаю, что PIL docs означает, что он использует PIL внутренне для обработки данных изображения.

из того, что я вижу в исходном коде, вы можете передать объект файла напрямую, так что, что-то с read() способ:

https://github.com/ejucovy/reportlab/blob/master/src/reportlab/platypus/flowables.py#L314

Я думаю, вы можете каким-то образом обернуть необработанные данные изображения в файловый объект (StringIO или подобный.)

EDIT: Я думаю, что это то, что вы делали раньше, к сожалению. В любом случае, это кажется правильным. Может, если вы расскажите в чем проблема в этом случае, мы сможем разобраться.