2012-04-02 104 views
2

我想解碼base64編碼的圖像,並將其放入使用ReportLab生成的PDF中。目前,我那樣做(image_data是base64編碼圖像,story已經是ReportLab的故事):在ReportLab生成的PDF中包含base64編碼的圖像

# 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) 

但是這給了我IO錯誤以下消息:「無法識別圖像文件」。

我知道ReportLab使用PIL來讀取不同於JPG的圖像,但是有什麼辦法可以避免創建指定的臨時文件,並且只對文件類對象執行此操作,而無需將文件寫入磁盤?

回答

0

我不熟悉的ReportLab的,但如果你可以使用PIL直接這將工作:

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

,你可以看看這裏PIL Image類references

2

你應該換StringIO的()由PIL.Image.open,所以只需img_size = ImageReader(PIL.Image.open(img_file)).getSize()。正如Tommaso的回答所暗示的,它實際上是Image.size的一個簡單封裝。而且,實際上是沒有必要來計算自己的遞減大小,reportlab.Image的bound模式可以爲你做到這一點:

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

此代碼爲我工作沒有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)