Why is canvas.print_figure to a png reduce the real size of my image

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Why is canvas.print_figure to a png reduce the real size of my image

David Goldsmith
Hi!  I spent a good part of yesterday trying to figure this out on my own, without success, so I'm posting.  I have a 3601x2401 pixel, 300 DPI figure I export to a png using print_figure; here's sample code:

PLB.imshow(rslt) # rslt is a 3601x2401 int-valued array
curfig = PLB.Figure
fig = PLB.gcf()
# next three lines are in my code; don't seem relevant, but I include them in case they are
ax = fig.gca()
ax.xaxis.set_ticks([])
ax.yaxis.set_ticks([])

fig.canvas.print_figure(fn + '.png',
dpi=300,
                        bbox_inches='tight', 
                        pad_inches=-1.0 / 72)
The resulting png is neither the right number of pixels by pixels, nor the right number of inches by incheses; what's more the resulting png differs depending on whether I use imshow or matshow (which I also tried).
What's going on, and how do I "fix" it?  (If I really am getting the full resolution figure, despite what the png is telling me are the pixel counts, why are the physical dimensions off, and why is the png telling me that the pixel counts are different?  If it has something to do with compression, is there some  undocumented way to say "no compression" and will that have the desired effect?)
Thanks!
DLG 


_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Why is canvas.print_figure to a png reduce the real size of my image

Jody Klymak
Hi David,

What are you trying to achieve as the output?  An image with no white space?  

`bbox_inches=tight` changes the size of the figure to get rid of white space around it.  Prob not what you really want.

Drilling down into `canvas` shouldn’t really be necessary. 

What is `PLB`?  etc?

This will get you pretty close if you just want an image w/ no white space.  But I’m not 100% sure that every pixel has been preserved…


```
import matplotlib.pyplot as plt
import numpy as np

im = np.floor(np.random.rand(3601,2401)*100)

fig, ax = plt.subplots(figsize = (2401/300, 3601/300), dpi=300)

# turn off axis and labels
ax.set_axis_off()
# fill the figure
ax.set_position([0., 0., 1., 1.])
ax.imshow(im)
fig.savefig('Test.png', dpi=300)
```




On 20 Oct 2017, at  14:38 PM, David Goldsmith <[hidden email]> wrote:

Hi!  I spent a good part of yesterday trying to figure this out on my own, without success, so I'm posting.  I have a 3601x2401 pixel, 300 DPI figure I export to a png using print_figure; here's sample code:

PLB.imshow(rslt) # rslt is a 3601x2401 int-valued array
curfig = PLB.Figure
fig = PLB.gcf()
# next three lines are in my code; don't seem relevant, but I include them in case they are
ax = fig.gca()
ax.xaxis.set_ticks([])
ax.yaxis.set_ticks([])

fig.canvas.print_figure(fn + '.png',
dpi=300,
                        bbox_inches='tight', 
                        pad_inches=-1.0 / 72)
The resulting png is neither the right number of pixels by pixels, nor the right number of inches by incheses; what's more the resulting png differs depending on whether I use imshow or matshow (which I also tried).
What's going on, and how do I "fix" it?  (If I really am getting the full resolution figure, despite what the png is telling me are the pixel counts, why are the physical dimensions off, and why is the png telling me that the pixel counts are different?  If it has something to do with compression, is there some  undocumented way to say "no compression" and will that have the desired effect?)
Thanks!
DLG 

_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users

--
Jody Klymak    






_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Why is canvas.print_figure to a png reduce the real size of my image

Warren Weckesser-2
In reply to this post by David Goldsmith


On Fri, Oct 20, 2017 at 5:38 PM, David Goldsmith <[hidden email]> wrote:
Hi!  I spent a good part of yesterday trying to figure this out on my own, without success, so I'm posting.  I have a 3601x2401 pixel, 300 DPI figure I export to a png using print_figure; here's sample code:



David,

If you are trying to write the numpy array directly to a PNG file, an alternative to matplotlib is a package that I created called numpngw: https://pypi.python.org/pypi/numpngw (github: https://github.com/WarrenWeckesser/numpngw).  Both those links show several examples of its use.   numpngw uses just Python and NumPy, so it is easy to install.

Warren


PLB.imshow(rslt) # rslt is a 3601x2401 int-valued array
curfig = PLB.Figure
fig = PLB.gcf()
# next three lines are in my code; don't seem relevant, but I include them in case they are
ax = fig.gca()
ax.xaxis.set_ticks([])
ax.yaxis.set_ticks([])

fig.canvas.print_figure(fn + '.png',
dpi=300,
                        bbox_inches='tight', 
                        pad_inches=-1.0 / 72)
The resulting png is neither the right number of pixels by pixels, nor the right number of inches by incheses; what's more the resulting png differs depending on whether I use imshow or matshow (which I also tried).
What's going on, and how do I "fix" it?  (If I really am getting the full resolution figure, despite what the png is telling me are the pixel counts, why are the physical dimensions off, and why is the png telling me that the pixel counts are different?  If it has something to do with compression, is there some  undocumented way to say "no compression" and will that have the desired effect?)
Thanks!
DLG 


_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users



_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Why is canvas.print_figure to a png reduce the real size of my image

David Goldsmith
In reply to this post by Jody Klymak
On Fri, Oct 20, 2017 at 3:00 PM Jody Klymak <[hidden email]> wrote:
Hi David,

What are you trying to achieve as the output?  An image with no white space?  

Yes, and no edge, but one that replaces that white space with my figure.  in other words, if what is going on is that my figure w/ the white space is what is 3600x2400, how do I get the full 3600x2400 to be my figure? (I don’t care if it puts white space around that because I figured out an “alternative” way to get rid of that).  But mostly, I’d just like to understand what’s going on, because what’s happening now makes absolutely no sense to me whatsoever.


`bbox_inches=tight` changes the size of the figure to get rid of white space around it.  Prob not what you really want.

OK, so that may be the problem: what’s the “proper” way to “get rid of” the white space, module what I said above.


Drilling down into `canvas` shouldn’t really be necessary. 

I’m all ears.

What is `PLB`?  etc?

import pylab as PLB

This will get you pretty close if you just want an image w/ no white space.  But I’m not 100% sure that every pixel has been preserved…


```
import matplotlib.pyplot as plt
import numpy as np

im = np.floor(np.random.rand(3601,2401)*100)

fig, ax = plt.subplots(figsize = (2401/300, 3601/300), dpi=300)

# turn off axis and labels
ax.set_axis_off()
# fill the figure
ax.set_position([0., 0., 1., 1.])
ax.imshow(im)
fig.savefig('Test.png', dpi=300)

Ok, I’ll try that, thanks.

DLG
```




On 20 Oct 2017, at  14:38 PM, David Goldsmith <[hidden email]> wrote:

Hi!  I spent a good part of yesterday trying to figure this out on my own, without success, so I'm posting.  I have a 3601x2401 pixel, 300 DPI figure I export to a png using print_figure; here's sample code:

PLB.imshow(rslt) # rslt is a 3601x2401 int-valued array
curfig = PLB.Figure
fig = PLB.gcf()
# next three lines are in my code; don't seem relevant, but I include them in case they are
ax = fig.gca()
ax.xaxis.set_ticks([])
ax.yaxis.set_ticks([])

fig.canvas.print_figure(fn + '.png',
dpi=300,
                        bbox_inches='tight', 
                        pad_inches=-1.0 / 72)
The resulting png is neither the right number of pixels by pixels, nor the right number of inches by incheses; what's more the resulting png differs depending on whether I use imshow or matshow (which I also tried).
What's going on, and how do I "fix" it?  (If I really am getting the full resolution figure, despite what the png is telling me are the pixel counts, why are the physical dimensions off, and why is the png telling me that the pixel counts are different?  If it has something to do with compression, is there some  undocumented way to say "no compression" and will that have the desired effect?)
Thanks!
DLG 

_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users

--
Jody Klymak    






_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Why is canvas.print_figure to a png reduce the real size of my image

David Goldsmith
In reply to this post by Warren Weckesser-2
Thanks.  Does it have pylab’s range of built in color maps?  Does it even use colormaps, or do I have to write my own (or “copy” them from MPL).

DLG

On Fri, Oct 20, 2017 at 3:28 PM Warren Weckesser <[hidden email]> wrote:
On Fri, Oct 20, 2017 at 5:38 PM, David Goldsmith <[hidden email]> wrote:
Hi!  I spent a good part of yesterday trying to figure this out on my own, without success, so I'm posting.  I have a 3601x2401 pixel, 300 DPI figure I export to a png using print_figure; here's sample code:



David,

If you are trying to write the numpy array directly to a PNG file, an alternative to matplotlib is a package that I created called numpngw: https://pypi.python.org/pypi/numpngw (github: https://github.com/WarrenWeckesser/numpngw).  Both those links show several examples of its use.   numpngw uses just Python and NumPy, so it is easy to install.

Warren


PLB.imshow(rslt) # rslt is a 3601x2401 int-valued array
curfig = PLB.Figure
fig = PLB.gcf()
# next three lines are in my code; don't seem relevant, but I include them in case they are
ax = fig.gca()
ax.xaxis.set_ticks([])
ax.yaxis.set_ticks([])

fig.canvas.print_figure(fn + '.png',
dpi=300,
                        bbox_inches='tight', 
                        pad_inches=-1.0 / 72)
The resulting png is neither the right number of pixels by pixels, nor the right number of inches by incheses; what's more the resulting png differs depending on whether I use imshow or matshow (which I also tried).
What's going on, and how do I "fix" it?  (If I really am getting the full resolution figure, despite what the png is telling me are the pixel counts, why are the physical dimensions off, and why is the png telling me that the pixel counts are different?  If it has something to do with compression, is there some  undocumented way to say "no compression" and will that have the desired effect?)
Thanks!
DLG 


_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users


_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Why is canvas.print_figure to a png reduce the real size of my image

Jody Klymak
In reply to this post by David Goldsmith


On 20 Oct 2017, at  15:33 PM, David Goldsmith <[hidden email]> wrote:

 But mostly, I’d just like to understand what’s going on, because what’s happening now makes absolutely no sense to me whatsoever.

Ha!  

I think you are approaching this from the point of view of an image processing library or something like Photoshop where you want your image to be 6x8 and 300 dpi, and you expect 1800x2400 pixels.  

Thats not *really* what matplotlib is for. It really is for presentation of scientific data.  So, I have a 500x600 matrix of data, I may use `imshow` to plot it up, but most people don’t care about the dpi of those pixels, so they will just set the dpi to something that shows all the data clearly.  Much more important is the ability to have axis labels, annotations, etc.  

Its not to say that you can’t be careful and get what you want.  I think what I sent you is pretty close.  But the library is not trying to conserve pixels.  

Anyway, what I sent should be clear enough.  I think what you were missing was setting the figure size to the size you wanted before trying to draw on it.

Cheers,   Jody





_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Why is canvas.print_figure to a png reduce the real size of my image

David Goldsmith
OK, thanks for your help.

What I’m doing is somewhere in between: I’m making my own “fractals,” “from scratch”; so if im going to the trouble of computing a 3600x2400 grid so that I can have a 300 DPI image end up being 12x8, that’s what I want to end up with (i don’t want to compute any more than I have to, but by the same token, I want to see everything I’m computing).  Anyway, i’ll see if that does what I’m after and reply again if not.  (Though I’d still like to know what’s going on under the hood, so that I can exploit that if I choose.)

Thanks again!

DLG

On Fri, Oct 20, 2017 at 3:44 PM Jody Klymak <[hidden email]> wrote:


On 20 Oct 2017, at  15:33 PM, David Goldsmith <[hidden email]> wrote:

 But mostly, I’d just like to understand what’s going on, because what’s happening now makes absolutely no sense to me whatsoever.

Ha!  

I think you are approaching this from the point of view of an image processing library or something like Photoshop where you want your image to be 6x8 and 300 dpi, and you expect 1800x2400 pixels.  

Thats not *really* what matplotlib is for. It really is for presentation of scientific data.  So, I have a 500x600 matrix of data, I may use `imshow` to plot it up, but most people don’t care about the dpi of those pixels, so they will just set the dpi to something that shows all the data clearly.  Much more important is the ability to have axis labels, annotations, etc.  

Its not to say that you can’t be careful and get what you want.  I think what I sent you is pretty close.  But the library is not trying to conserve pixels.  

Anyway, what I sent should be clear enough.  I think what you were missing was setting the figure size to the size you wanted before trying to draw on it.

Cheers,   Jody





_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Why is canvas.print_figure to a png reduce the real size of my image

Jody Klymak
Fair enough.  Just to be safe, just do dpi=600!  It’ll be big, but...

Cheers,   Jody

On Oct 20, 2017, at  16:02 PM, David Goldsmith <[hidden email]> wrote:

OK, thanks for your help.

What I’m doing is somewhere in between: I’m making my own “fractals,” “from scratch”; so if im going to the trouble of computing a 3600x2400 grid so that I can have a 300 DPI image end up being 12x8, that’s what I want to end up with (i don’t want to compute any more than I have to, but by the same token, I want to see everything I’m computing).  Anyway, i’ll see if that does what I’m after and reply again if not.  (Though I’d still like to know what’s going on under the hood, so that I can exploit that if I choose.)

Thanks again!

DLG

On Fri, Oct 20, 2017 at 3:44 PM Jody Klymak <[hidden email]> wrote:


On 20 Oct 2017, at  15:33 PM, David Goldsmith <[hidden email]> wrote:

 But mostly, I’d just like to understand what’s going on, because what’s happening now makes absolutely no sense to me whatsoever.

Ha!  

I think you are approaching this from the point of view of an image processing library or something like Photoshop where you want your image to be 6x8 and 300 dpi, and you expect 1800x2400 pixels.  

Thats not *really* what matplotlib is for. It really is for presentation of scientific data.  So, I have a 500x600 matrix of data, I may use `imshow` to plot it up, but most people don’t care about the dpi of those pixels, so they will just set the dpi to something that shows all the data clearly.  Much more important is the ability to have axis labels, annotations, etc.  

Its not to say that you can’t be careful and get what you want.  I think what I sent you is pretty close.  But the library is not trying to conserve pixels.  

Anyway, what I sent should be clear enough.  I think what you were missing was setting the figure size to the size you wanted before trying to draw on it.

Cheers,   Jody






_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: Why is canvas.print_figure to a png reduce the real size of my image

Warren Weckesser-2
In reply to this post by David Goldsmith


On Fri, Oct 20, 2017 at 6:36 PM, David Goldsmith <[hidden email]> wrote:
Thanks.  Does it have pylab’s range of built in color maps?  Does it even use colormaps, or do I have to write my own (or “copy” them from MPL).

No, numpngw doesn't use colormaps.  You'd have to map and scale the image to an array of integers yourself.  You could use matplotlib for the mapping.  For example, if foo is a 2-D array of floats with values between 0 and 1, you could do something like

    mapped_foo = mpl.cm.viridis(foo)  # Use matplotlib's 'viridis' colormap.
    maxint = 2**16
    img = np.floor(maxint*mapped_foo)
    img[img == maxint] = maxint - 1
    numpngw.write_png("foo.png", img.astype(np.uint16))

That would create a 16 bit RGB PNG file.

Warren




DLG

On Fri, Oct 20, 2017 at 3:28 PM Warren Weckesser <[hidden email]> wrote:
On Fri, Oct 20, 2017 at 5:38 PM, David Goldsmith <[hidden email]> wrote:
Hi!  I spent a good part of yesterday trying to figure this out on my own, without success, so I'm posting.  I have a 3601x2401 pixel, 300 DPI figure I export to a png using print_figure; here's sample code:



David,

If you are trying to write the numpy array directly to a PNG file, an alternative to matplotlib is a package that I created called numpngw: https://pypi.python.org/pypi/numpngw (github: https://github.com/WarrenWeckesser/numpngw).  Both those links show several examples of its use.   numpngw uses just Python and NumPy, so it is easy to install.

Warren


PLB.imshow(rslt) # rslt is a 3601x2401 int-valued array
curfig = PLB.Figure
fig = PLB.gcf()
# next three lines are in my code; don't seem relevant, but I include them in case they are
ax = fig.gca()
ax.xaxis.set_ticks([])
ax.yaxis.set_ticks([])

fig.canvas.print_figure(fn + '.png',
dpi=300,
                        bbox_inches='tight', 
                        pad_inches=-1.0 / 72)
The resulting png is neither the right number of pixels by pixels, nor the right number of inches by incheses; what's more the resulting png differs depending on whether I use imshow or matshow (which I also tried).
What's going on, and how do I "fix" it?  (If I really am getting the full resolution figure, despite what the png is telling me are the pixel counts, why are the physical dimensions off, and why is the png telling me that the pixel counts are different?  If it has something to do with compression, is there some  undocumented way to say "no compression" and will that have the desired effect?)
Thanks!
DLG 


_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users



_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users