2012-12-19 3 views
15

Reportlab에 바코드 이미지를 삽입하려고합니다. 나는 이것에 대해 많은 질문을하지만, 은 모두 이미이라고 가정하고 디렉토리 나 파일 시스템에 이미지 파일을 가지고 있다고 가정합니다.PIL 이미지 또는 StringIO에서 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 함수의 첫 번째 인수로 전달해야하는 것은 무엇입니까?

답변

7

반복적 선언 단순히 (그들을 읽을 수 PIL을 사용하기 때문에) PIL에 의해 지원되는 데이터 형식 reportlab 지원하는 것을 의미한다 "PIL/자바 1.4 (파이썬/자바 이미징 라이브러리)가 지원하는 형식이 지원됩니다."

이제 reportlab.platypus.flowables.Image 코드를 보았을 때 파일 이름이나 파일 객체를 입력으로 받아들이는 것을 볼 수 있습니다. 전자는 사용자가 원하는 것이 아니므로 나중에 초점을 맞추십시오. 당신은 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) 

img3 이제 이미지의 원시 데이터를 보유하고 있기 때문에 3이 실패있어서, 그래서이의 실제 형식에 대한 아무 생각이 없습니다 : 당신은 아마 여기 StringIO을 사용하는 두 올바른 방법은 그것으로 뭔가 잘못했다 데이터. 이러한 작업을 위해이 방법을 사용하려고 시도 할 이유가 없습니다.

원시 데이터가 있고 데이터의 이미지 모드 ('L', 'RGB'등)와 너비, 높이를 알고있는 경우 PIL.Image.fromstring(...).save(mystrio, 'someformat')에 기반한 네 번째 (올바른) 방법을 사용할 수 있습니다.

+0

파이썬 3에서, 'IO 수입 BytesIO에서'대신 'cStringIO 수입 StringIO에서'사용. 그리고 'img2 = BytesIO()'대신 'img2 = StringIO()' –

0

필자는 PIL 문서가 의미하는 바는 이미지 데이터를 처리하기 위해 내부적으로 PIL을 사용한다는 것입니다. 나는 소스 코드에서 보는 것과

, 당신은 read() 방법, 무언가를 직접 파일 개체를 전달, 그렇게 할 수

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

을 당신이 어떻게 든에서 RAW 이미지 데이터를 포장 할 수 있습니다 추측 파일과 유사한 객체 (StringIO 또는 그와 같은 객체).

편집 : 내가 그랬던 것은 미안합니다. 어쨌든, 그것은 올바른 방법 인 것 같습니다. 어쩌면 당신이 그 문제가 뭔지 우리에게 말해 준다면, 우리는 그것을 해결할 수있을 것입니다.

8

나는 제안 된 방법으로 운이 없었습니다.

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에서 클래스하는 ImageReader의 속성임을 보여준다

파일명으로 StringIO 처리에서 AttributError 결과가, pdfdoc.py 프로그램의 코드를 검사 .utils. ImageReader는 StringIO 및 PIL 이미지를 모두 허용합니다. 그래서 ImageReader를에서 StringIO 포장

나를 위해 문제를 해결 :

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, ...)