我正在撰写一份包含表格和图片混合的报告。实际上,图像[图形]以.png格式保存到文件系统中。
实际呈现PDF的方法是:
def _render_report(report_data):
file_name = get_file_name() # generate random filename for report
rpt = Report(settings.MEDIA_ROOT + os.sep + file_name)
Story = []
for (an, sam, event), props in report_data.iteritems():
Story.append(Paragraph("%s - sample %s results for %s" % (an.name, sam.name, event.name), styles["Heading2"]))
data_list = [['Lab', 'Method', 'Instrument', 'Unit', 'Raw Result', 'Converted Result', 'Outlier']]
for (index, series) in props['frame'].iterrows():
data_list.append(_format([
Paragraph(Lab.objects.get(pk=series['labs']).name, styles['BodyText']),
Paragraph(Method.objects.get(pk=series['methods']).name, styles['BodyText']),
Paragraph(Instrument.objects.get(pk=series['instruments']).name, styles['BodyText']),
Paragraph(Unit.objects.get(pk=series['units']).name, styles['BodyText']),
series['raw_results'],
series['results'],
series['outlier']
]))
table = Table(data_list, colWidths=[45 * mm, 35 * mm, 35 * mm, 25 * mm, 35 * mm, 35 * mm, 35 * mm], repeatRows=1)
Story.append(table)
Story.append(PageBreak())
if props['graph'] is not None:
Story.append(Image("/tmp/%s" % props['graph'], width=10 * inch, height=6 * inch))
Story.append(PageBreak())
rpt.draw(Story, onFirstPage=setup_header_and_footer, onLaterPages=setup_header_and_footer)
return file_name
背景资料
上面使用的“Report”类只是SimpleDocTemplate
周围的一个瘦包装器,它设置了一些默认值,但委托给SimpleDocTemplate的build
实现。它的代码是:
class Report(object):
def __init__(self, filename, doctitle="Report", docauthor="<default>",
docsubject="<default>", doccreator="<default>", orientation="landscape", size=A4):
DEFAULTS = {
'leftMargin' : 10 * mm,
'rightMargin' : 10 * mm,
'bottomMargin' : 15 * mm,
'topMargin' : 36 * mm,
'pagesize' : landscape(size) if orientation == "landscape" else portrait(size),
'title' : doctitle,
'author' : docauthor,
'subject' : docsubject,
'creator' : doccreator
}
self.doc = SimpleDocTemplate(filename, **DEFAULTS)
def draw(self, flowables, onFirstPage=setup_header_and_footer, onLaterPages=setup_header_and_footer):
self.doc.build(flowables, onFirstPage=setup_header_and_footer,
onLaterPages=setup_header_and_footer, canvasmaker=NumberedCanvas)
我已经查看了
问题
表,标题和页面模板呈现正常,但图像为空白。今天早些时候,我在设置本报告使用的模板时遇到了this issue。解决方法是使用canvas.drawInlineImage(...
代替canvas.DrawImage(...
。因此看起来我的设置有问题;我可以使用一些关于如何调试它的指针。
更新
我能够应用this linked question中使用的相同解决方法的变体(使用canvas.drawInlineImage
代替canvas.drawImage
。我将“图像”子类化如下:
class CustomImage(Image):
"""
Override - to use inline image instead; inexplicable bug with non inline images
"""
def draw(self):
lazy = self._lazy
if lazy>=2: self._lazy = 1
self.canv.drawInlineImage(self.filename,
getattr(self,'_offs_x',0),
getattr(self,'_offs_y',0),
self.drawWidth,
self.drawHeight
)
if lazy>=2:
self._img = None
self._lazy = lazy
“stock”Image类的唯一更改是使用self.canv.drawInlineImage
之前的self.canvas.drawImage
。
这种“有用”的意义是图像最终在我的PDF中可见。 drawImage
无效的原因仍然是个谜。
我试过@ PedroRomano的建议(确保图像RGBA),甚至尝试过JPEG图像而不是PNG。这些并没有什么区别。
答案 0 :(得分:0)
最佳解决方案是使用reportlab以supported作为postscript的矢量格式生成图形。很多UNIX软件都可以开箱即用,在Windows上你可以使用优秀的PDFCreator。
如果必须为图形使用光栅图像,请尝试将图像转换为JPEG格式。可以使用DCTDecode过滤器将这些内容轻松嵌入到PDF文件中。 (例如jpeg2pdf does。)
答案 1 :(得分:0)
我最终通过使用自定义Image
子类来结束此事:
class CustomImage(Image):
"""
Override - to use inline image instead; inexplicable bug with non inline images
"""
def draw(self):
lazy = self._lazy
if lazy>=2: self._lazy = 1
self.canv.drawInlineImage(self.filename,
getattr(self,'_offs_x',0),
getattr(self,'_offs_y',0),
self.drawWidth,
self.drawHeight
)
if lazy>=2:
self._img = None
self._lazy = lazy
以矢量图形格式保存图形,例如EPS,保存为JPEG,保存为带有和不带alpha通道的PNG都不会产生任何影响。