Hello list
I’ve trying for a while a “python only” solution to remove white spaces that Basemap generate to keep the aspect ratio. I found these two threads that explain the issue better:
http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg14430.html
http://www.mail-archive.com/matplotlib-users@…1753…forge.net/msg14262.html
In the past I relied on ImageMagick’s “convert” command with the “-trim white” option for the job. However, just recently I came across with this other list and a PIL solution:
http://mail.python.org/pipermail/image-sig/2008-July/005092.html
Here is how I’m doing:
savefig(‘mapa.png’, dpi=300)
from PIL import Image
im = Image.open(“mapa.png”)
def trim(im, border):
from PIL import ImageChops
bg = Image.new(im.mode, im.size, border)
diff = ImageChops.difference(im, bg)
bbox = diff.getbbox()
if bbox:
return im.crop(bbox)
else:
found no content
raise ValueError(“cannot trim; image was empty”)
im2=trim(im,‘white’)
im2.show()
This works and the aspect ratio is preserved, but as you can see, it is not a very smart implementation. I save and then reload it again… any suggestions to improve this are welcome.
Also, I have not tried this on figures with labels and annotations.
Thanks for any input.
···
Filipe Pires Alvarenga Fernandes
University of Massachusetts Dartmouth
200 Mill Road - Fairhaven, MA
Tel: (508) 910-6381
Email: falvarengafernandes@…1874…
ocefpaf@…1361…
ocefpaf@...287...
http://ocefpaf.tiddlyspot.com/
2010/3/28 Filipe Pires Alvarenga Fernandes <ocefpaf@...287...>:
Hello list
I've trying for a while a "python only" solution to remove white spaces that
Basemap generate to keep the aspect ratio. I found these two threads that
explain the issue better:
I think maybe you can make use of the Agg Backend to achieve a
Python-only solution to obtain a PIL Image from a figure without
bypassing over the HDD:
Furthemore, if this doesn't work, maybe you can use a StringIO as
"file", then seek() the StringIO and reread with PIL from the
"file-like" StringIO, or something like that?
···
#
# Render the Figure to a PIL Image ...
#
# Prepare figure to be of pixel extent *shape* ...
dpi = figure.dpi
figure.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi)
# Create the rendering Canvas ...
#
# We also convert the picture to an RGB string.
canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(figure)
canvas.draw()
image_string = canvas.tostring_rgb()
# Create a PIL Image from RGB string ...
image = Image.fromstring("RGB", shape, image_string)
# Now do whatever you want with the Image.
Friedrich
Thanks Friedrich,
However, my knowledge of python is very limited, even though I think I
understood what you suggested I do not know how to get the shape (of
the figure?) for this part:
fig.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi)
error is:
Traceback (most recent call last):
File "blueearth-map.py", line 108, in <module>
fig.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi)
TypeError: 'function' object is unsubscriptable
It seems that it ended up calling a function shape instead of a variable shape.
I'm sending attached the script if you are interested in looking at it.
Thanks again. Filipe.
blueearth-map.py (3.4 KB)
···
On Sun, Mar 28, 2010 at 3:35 PM, Friedrich Romstedt <friedrichromstedt@...287...> wrote:
2010/3/28 Filipe Pires Alvarenga Fernandes <ocefpaf@...287...>:
> Hello list
> I've trying for a while a "python only" solution to remove white spaces that
> Basemap generate to keep the aspect ratio. I found these two threads that
> explain the issue better:
I think maybe you can make use of the Agg Backend to achieve a
Python-only solution to obtain a PIL Image from a figure without
bypassing over the HDD:
Furthemore, if this doesn't work, maybe you can use a StringIO as
"file", then seek() the StringIO and reread with PIL from the
"file-like" StringIO, or something like that?
#
# Render the Figure to a PIL Image ...
#
# Prepare figure to be of pixel extent *shape* ...
dpi = figure.dpi
figure.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi)
# Create the rendering Canvas ...
#
# We also convert the picture to an RGB string.
canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(figure)
canvas.draw()
image_string = canvas.tostring_rgb()
# Create a PIL Image from RGB string ...
image = Image.fromstring("RGB", shape, image_string)
# Now do whatever you want with the Image.
Friedrich
2010/3/30 Filipe Pires Alvarenga Fernandes <ocefpaf@...287...>:
However, my knowledge of python is very limited, even though I think I
understood what you suggested I do not know how to get the shape (of
the figure?) for this part:
fig.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi)
error is:
Traceback (most recent call last):
File "blueearth-map.py", line 108, in <module>
fig.set_size_inches(float(shape[0]) / dpi, float(shape[1]) / dpi)
TypeError: 'function' object is unsubscriptable
It seems that it ended up calling a function shape instead of a variable shape.
You're completely right, I assumed that you fill in some 2-element
vector in *shape*, it was intended as an /argument/. The function
attemted to be indexed is imported from numpy by matplotlib.pyplot:
There is a code line "from numpy import *".
So, simply put some line somewhere like:
shape = [500, 500] .
You have to set or have to calculate the figure's shape in pixels
somewhere, because you need it to convert the rgb string back into a
PIL image. It's not that nice, I know, for your problem?
Friedrich