chrisjsewell / ipypublish

A workflow for creating and editing publication ready scientific reports and presentations, from one or more Jupyter Notebooks, without leaving the browser!
http://ipypublish.readthedocs.io
BSD 3-Clause "New" or "Revised" License
224 stars 37 forks source link

Specify resolution and size to be displayed inline in gridconcat, vconcat and hconcat #107

Open Benfeitas opened 5 years ago

Benfeitas commented 5 years ago

I'm trying to use images_gridconcat to display a few images that I have stored locally. However, once they are displayed in a Jupyter notebook their resolution becomes much worse, probably owing to their new size. Is there a way to have them being shown with another size inline?

Adjusting width or height in nb_setup.images_gridconcat(images, width=3000, height=2000) does not change their inline display.

I was also able to use:

mygrid=nb_setup.images_gridconcat(images) mygrid.resize((3000,2000), PIL.Image.ANTIALIAS)

But the resolution issue is still there.

chrisjsewell commented 5 years ago

Hey @Benfeitas do you have an example image to replicate this issue, in particular, what format are these images? Funnily enough, yesterday I had an issue with resolution of postscript (.eps) files, which I fixed by scaling the vector image before rasterizing (see https://stackoverflow.com/a/56568354/5033292):

from PIL import Image

eps_image = Image.open('image.eps')
# Rasterise onto 4x higher resolution grid
eps_image.load(scale=4) 
Benfeitas commented 5 years ago

Well, that may be it as the images are .png. I had thought that having them as png would be fine since individually they look quite good, just not when you generate the new figure through gridconcat. The problem is that I can only write them as pdf, png or svg, so I guess I will need some intermediate step somewhere to do the file conversion to eps

Benfeitas commented 5 years ago

I was able to have images_gridconcat read PIL objects by reading each pdf individually. Specifically I used pdf2image to build a PIL object from each .pdf (source). .convert("RGBA") is needed (source)

However, the resolution problem is still there. for some reason, img1.load(scale=4) doesn't work either - "scale" is not recognized.

img1=pdf2image.convert_from_path(fl[0])[0].convert("RGBA")
img=nb_setup.images_gridconcat([[img1,img1],[img1,img1]],aspaths=False) img.resize((1000,800), PIL.Image.ANTIALIAS)

This all seems a problem that's not really related with ipypublish now, as it is mostly due to PIL's incompatibility with pdf or svg.

chrisjsewell commented 5 years ago

This all seems a problem that's not really related with ipypublish now, as it is mostly due to PIL's incompatibility with pdf or svg.

Yeh that's the main issue there. To have optimal resolution, you should preferably be using vector graphics (pdf, svg, eps, ...), rather than rasterized (png, jpeg, ...). But PIL only handles rasterized, converting vector graphics to rasterized on input.

Obviously, you can just use methods in IPython.display to display single vector graphics in their native form in the notebook. I wonder if there is a program / python package out there to easily concatenate vector graphics?

chrisjsewell commented 5 years ago

So, svgutils definitely seems the way forward here. I've just been trying it out in the notebook, and it works well.

chrisjsewell commented 5 years ago

svglib also works well for converting the final svg to pdf