Reputation: 737
I'm working with the Indigo library for a web based chemistry project. Long story short, they wrote a nice Python interface for it, which I'm using through CGI. There are several output formats, SVG and PNG being included. I'm not a Python pro, so I'm getting a little stumped on the author's idea of a buffer. The following works:
#!python
from indigo import *
from indigo_renderer import *
from struct import *
print "Content-type: image/svg+xml"
print
indigo = Indigo()
renderer = IndigoRenderer(indigo);
mol1 = indigo.loadMolecule("ONc1cccc1");
indigo.setOption("render-output-format", "svg");
indigo.setOption("render-highlight-color-enabled", "true");
image = renderer.renderToBuffer(mol1);
output = image.tostring()
print output
That is, the above code spits out properly formatted SVG XML with no unwanted leading or tailing characters. Firefox recognized the content type and rendered it fine.
However, I'm having a hard time understanding what I'm supposed to do for PNG:
I change the code to:
from indigo import *
from indigo_renderer import *
from struct import *
print "Content-type: image/png"
print
indigo = Indigo()
renderer = IndigoRenderer(indigo);
mol1 = indigo.loadMolecule("ONc1cccc1");
indigo.setOption("render-output-format", "png");
indigo.setOption("render-highlight-color-enabled", "true");
image = renderer.renderToBuffer(mol1);
output = image
print output
and I get this (which isn't what I was expecting for a PNG):
array('c', '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00[ truncated by me ]')
If I try the toString() method, I do get a nice blob of binary (I didn't spend any effort attempting to interpret it), but it's still apparently broken. I have a feeling this needs to be decoded prior to being dumped to the client (I used to do it with PHP) - which is probably rather simple, but I couldn't find much help from the documentation (or perhaps I found what I was looking for and it was beyond my comprehension). I'm just not sure what's going on, and would appreciate some advice.
Upvotes: 3
Views: 3540
Reputation: 737
(Apologies for putting this in the comments as well as here). Solve the problem - Windows sure made this a pain, but for now it will have to do. Unfortunately the code will have to change when I start finalizing it for my Linux VPS, but here's what I did. The output is a character array, and tostring() works as expected, just dumping the raw contents. All I need to do is force the output to write as binary to prevent corruption. To write to a file in binary is trivial, but to write to stdout as binary is platform specific. See: link Thanks for the help. I found the guidance here:
Win32 Binary Write Final code was:
#!python
from indigo import *
from indigo_renderer import *
from array import *
import sys, cgitb, cgi
cgitb.enable()
httpArgs = cgi.FieldStorage()
print "Content-type: image/png"
print
indigo = Indigo()
renderer = IndigoRenderer(indigo)
mol1 = indigo.loadMolecule("ONc1cccc1")
indigo.setOption("render-output-format", "png")
indigo.setOption("render-highlight-color-enabled", "true")
outputStream = renderer.renderToBuffer(mol1)
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
else:
sys.exit()
sys.stdout.write(outputStream.tostring())
Upvotes: 0
Reputation: 727
According to what your output is, it is a PNG file. Just save it to a file in wb
mode.
As you are a PHP developer, I would only use what you have to in python:
Option one:
Save to a file and pick it up with PHP
...
output = image
f=open ("someFileName.png", wb)
f.write(output[1])
f.close()
Then use "someFileName.png"
with your PHP wrapper.
Option two: call the python script form the PHP wrapper. Pass the image data to the wrapper as the exit code.
...
output = image
import sys
sys.exit(output[1])
Upvotes: 1