imgkit
imgkit copied to clipboard
Exporting image to a variable can include internal warnings from miscellanous components, producing an invalid output.
Basically, I'm using the code as following:
options = {
"xvfb" : "",
'format' : 'png',
}
img = imgkit.from_string(rendered_html, False, options=options)
print("Image generated")
with open("test.png", "wb") as fp:
fp.write(img)
buf = io.BytesIO(img)
im = Image.open(buf)
im.save("figure.png")
buf.close()
PIL fails to open the bytes array with OSError: cannot identify image file <_io.BytesIO object at 0x7fde9c07d888>
. Saving the image, Irfanview can open the file, but other viewers report it as invalid.
Opening the image in a hex editor yields:
00000000: 6c69 6270 6e67 2077 6172 6e69 6e67 3a20 6943 4350 3a20 6b6e :libpng warning: iCCP: kn
00000018: 6f77 6e20 696e 636f 7272 6563 7420 7352 4742 2070 726f 6669 :own incorrect sRGB profi
00000030: 6c65 0a6c 6962 706e 6720 7761 726e 696e 673a 2069 4343 503a :le.libpng warning: iCCP:
00000048: 206b 6e6f 776e 2069 6e63 6f72 7265 6374 2073 5247 4220 7072 : known incorrect sRGB pr
00000060: 6f66 696c 650a 4c6f 6164 696e 6720 7061 6765 2028 312f 3229 :ofile.Loading page (1/2)
00000078: 0a5b 3e20 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 :.[>
00000090: 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 :
000000a8: 2020 2020 2020 2020 2020 2020 2020 5d20 3025 0d5b 3d3d 3d3d : ] 0%.[====
000000c0: 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d :========================
000000d8: 3d3d 3e20 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 :==>
000000f0: 2020 2020 2020 2020 5d20 3530 250d 5b3d 3d3d 3d3d 3d3d 3d3d : ] 50%.[=========
00000108: 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d :========================
00000120: 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d :========================
00000138: 3d3d 3d5d 2031 3030 250d 5265 6e64 6572 696e 6720 2832 2f32 :===] 100%.Rendering (2/2
00000150: 2920 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 :)
00000168: 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 :
00000180: 2020 2020 200a 5b3e 2020 2020 2020 2020 2020 2020 2020 2020 : .[>
00000198: 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 :
000001b0: 2020 2020 2020 2020 2020 2020 2020 2020 2020 205d 2030 250d : ] 0%.
000001c8: 5b3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3d3d 3e20 2020 2020 2020 :[===============>
000001e0: 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 :
000001f8: 2020 2020 2020 2020 2020 2020 205d 2032 3525 0d89 504e 470d : ] 25%..PNG.
00000210: 0a1a 0a00 0000 0d49 4844 5200 0004 0000 0000 c508 0600 0000 :.......IHDR.............
00000228: ca77 8097 0000 0009 7048 5973 0000 0f61 0000 0f61 01a8 3fa7 :.w......pHYs...a...a..?.
00000240: 6900 0020 0049 4441 5478 0100 0880 f77f 01ff ffff ff00 0000 :i.. .IDATx..............
00000258: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 :........................
00000270: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 :........................
00000288: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 :........................
000002a0: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 :........................
So there's some output stuff at the beginning of the file (line breaks added manually):
libpng warning: iCCP: known incorrect sRGB profile.
libpng warning: iCCP: known incorrect sRGB profile.
Loading page (1/2).
[> ] 0%.
[==============================> ] 50%.
[============================================================]100%.
Rendering (2/2).
[> ] 0%.
[===============> ] 25%.
.PNG
It looks like the stdout of something internal (wkhtmltopdf
?) is getting captured into the "image" output, somehow.
A really, really horrible workaround hack (that only works for .png
files) is the following:
# PNG File header
header = bytes((137, 80, 78, 71, 13, 10, 26, 10))
img = img[img.index(header):]
Basically, it truncates everything before the png
start-of-file header.
A fix for this would be nice.
I don't have the same exact issue, but similar. I don't even get anything saved to the variable. The raised error prevents that When I use imgkit.from_url
with path=False
, I get some OSError. This doesn't happen when I provide a path.
I drilled down and inspected the module code to find that IMGKit.to_img
is raising an error from stderr
text from wkhtmltoimage
. Below are the updates I made to IMGKit.to_img that I'm using by mock
ing the original function. I know it's hacky and doesn't solve the root cause, but it works for my purposes. Maybe I'll look further into it once I finish this project I'm working on. This is what the relevant part of my patch of to_img
looks like...and now I have it working 100%.
- Note: I also had to reimport
subprocess
andsys
at the beginning of the updated function.
# 1. commented this out
# if "Error" in stderr:
# raise OSError("wkhtmltoimage reported an error:\n" + stderr)
if exit_code != 0:
xvfb_error = ""
if "QXcbConnection" in stderr:
xvfb_error = 'You need to install xvfb(sudo apt-get install xvfb, ' \
'yum install xorg-x11-server-Xvfb, etc), ' \
'then add option: {"xvfb": ""}.'
raise OSError( # 2. tabbed this raise over since we'd reach here as well...
"wkhtmltoimage exited with non-zero code {0}. error:\n{1}\n\n{2}".format(
exit_code, stderr, xvfb_error
)
)