imgkit icon indicating copy to clipboard operation
imgkit copied to clipboard

Exporting image to a variable can include internal warnings from miscellanous components, producing an invalid output.

Open fake-name opened this issue 5 years ago • 3 comments

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.

fake-name avatar Nov 11 '18 08:11 fake-name

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.

fake-name avatar Nov 11 '18 09:11 fake-name

A fix for this would be nice.

sorter avatar Jun 02 '20 21:06 sorter

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 mocking 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 and sys 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
                    )
                )

eparikh avatar Jul 17 '23 05:07 eparikh