24

Reportlabにバーコード画像を挿入しようとしています。これについて多くの質問があることは知っていますが、それらはすべて、ディレクトリまたはファイルシステムにすでにイメージファイルがあることを前提としています。

ReportlabにはEAN13バーコードの問題があるため、pyBarcodeという別のパッケージを使用して画像を生成することにしました。

最初に画像をStringIOインスタンスに保存して直接渡しましたreportlab.platypus.flowables.Imageが、うまくいかなかったようです。それから私はドキュメントを読みました:

PIL / Java 1.4(Python / Java Imaging Library)でサポートされている形式がサポートされています。

これは、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のImage関数の最初の引数として何を渡す必要がありますか?

4

4 に答える 4

14

私は提案された方法に運がなかった。

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がreportlab.lib.utilsのクラスImageReaderの属性であることがわかります。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, ...)
于 2014-11-26T22:15:04.767 に答える
11

「PIL/Java1.4(Python / Java Imaging Library)でサポートされているフォーマットがサポートされている」という繰り返しの宣言は、によってサポートされているデータフォーマットPILがサポートされていることを意味しますreportlab(読み取りに使用PILするため)。

これで、コードを覗いてみるとreportlab.platypus.flowables.Image、ファイル名またはファイルオブジェクトのいずれかを入力として受け入れることがわかります。前者はあなたが望むものではないので、後者に焦点を当てましょう。うまくStringIOいかなかったとおっしゃいましたが、気をつければうまくいきます。あなたはおそらくそれで何か間違ったことをしました、ここに2つの正しい使い方があります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'など)とその幅、高さがわかっている場合は、に基づく4番目の(正しい)方法を使用できますPIL.Image.fromstring(...).save(mystrio, 'someformat')

于 2012-12-20T03:18:33.070 に答える
0

PILのドキュメントが言っていることは、画像データを処理するために内部でPILを使用しているということだと思います。

ソースコードにあるものから、ファイルオブジェクトを直接渡すことができるので、read()メソッドを使用して次のようにします。

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

どういうわけか、生の画像データをファイルのようなオブジェクト(StringIOなど)でラップできると思います。

編集:それはあなたが前にやっていたことだと思います、ごめんなさい。とにかく、それは正しい方法のようです。その場合の問題点を教えていただければ、解決できるかもしれません。

于 2012-12-19T14:23:54.473 に答える
0

キャンバスに描画するか、multiBuildのフロー可能な要素を構築するかに応じて、2つの異なるパターンが役立つことがわかりました。BytesIOバッファーに保存されたmatplotlibフィギュアを使用していますが、同じバッファーがバーコードのニーズに対応すると思います。

両方のための:

import io

キャンバスの場合:

from reportlab.lib.units import inch
from reportlab.lib.utils import ImageReader

# assume a proper Canvas object is instantiated as c

buf = io.BytesIO(the_barcode.getvalue())
buf.seek(0)
c.drawImage(ImageReader(buf), 0.5*inch, 5.5*inch, )

ドキュメントのフロー可能な要素の場合:

from reportlab.platypus.flowables import Image

# assume story is a list of flowable elements for multiBuild

buf = io.BytesIO(the_barcode.getvalue())
buf.seek(0)
story.append(Image(buf))

多くの試行錯誤の末、これらは私のために働きました。

于 2022-01-22T04:21:31.117 に答える