imshow with PS backend

Hi,

I've just moved from MATLAB to matplotlib, and I'm really impressed
with the quality of the PS figures it generates with usetex and the
xpdf distiller. I've hit a couple of problems though, one I've manged
to solve (patch against 0.87.4 attached) and the other I'd be greatful
if you could help me with please.

I've been using imshow to basically put a set of axes round an image
produced my simulation code. Here's a minimal version of my script:

matplotlib-0.87.4-pdf_distiller_options.patch (2.98 KB)

···

----------------------------------------------
from pylab import *

rc('text', usetex=True)
rc('ps', usedistiller="xpdf")

figure(1,figsize=(6, 4))
im=imread('image.png') # a 301x318 image
imshow(im,interpolation='nearest',extent=[0.98, 20, 0.01, 0.5])
axis('normal');
savefig('image.eps')
--------------------------------------------

The first problem I noticed is that the distilling process was causing
some of my images to have (lossy) compression applied and others not.
It turns out that it is a feature of ps2pdf that it tries to detect
the content of the image and apply appropriate compression. You can
over ride this distiller options. My patch adds a new rc option
ps.image_compression that can be set to auto (preserves the current
behaviour), DCTEncode (applies lossy JPEG compression), and
FlateEncode (lossless compression). The distiller commands are
embedded in the ps file. I looked at making it a flag on each image,
but couldn't get it to work. Another way to do it is to pass extra
command line options to ps2pdf (-dAutoFilterColorImages=false
-sColorImageFilter=FlateEncode should do it for colour images). I
thought embedding it in the PS file would be more flexible.

My second problem involved the resolutions of the image. I'd like to
preserve the resolution of my image in the PS output, but I can't
figure out how to stop the image being resized and interpolated.
Obviously you need to do this for the bitmap backends, but for vector
ones surely you can just scale the original image in the vector
output.

Thanks in advance for you help and some great software!

JIM
---

Hi,

I've just moved from MATLAB to matplotlib, and I'm really impressed
with the quality of the PS figures it generates with usetex and the
xpdf distiller.

Glad to hear it.

I've hit a couple of problems though

[...]

The first problem I noticed is that the distilling process was causing
some of my images to have (lossy) compression applied and others not.
It turns out that it is a feature of ps2pdf that it tries to detect
the content of the image and apply appropriate compression. You can
over ride this distiller options. My patch adds a new rc option
ps.image_compression that can be set to auto (preserves the current
behaviour), DCTEncode (applies lossy JPEG compression), and
FlateEncode (lossless compression). The distiller commands are
embedded in the ps file. I looked at making it a flag on each image,
but couldn't get it to work. Another way to do it is to pass extra
command line options to ps2pdf (-dAutoFilterColorImages=false
-sColorImageFilter=FlateEncode should do it for colour images). I
thought embedding it in the PS file would be more flexible.

I'll look into this soon. I'm hesitant to add another rc option, maybe we can
consider using these settings as the defaults. I'll post again after I have
had a chance to play with it.

My second problem involved the resolutions of the image. I'd like to
preserve the resolution of my image in the PS output, but I can't
figure out how to stop the image being resized and interpolated.
Obviously you need to do this for the bitmap backends, but for vector
ones surely you can just scale the original image in the vector
output.

The resolution for Postscript is 72 dpi, and I'm not sure this can be changed.
Would you send me an example postscript file along with the original png?

···

On Thursday 27 July 2006 8:33 am, JIM MacDonald wrote:

+1 for that. I am having exactly the same problem.

···

On Thu, Jul 27, 2006 at 01:33:42PM +0100, JIM MacDonald wrote:

Another way to do it is to pass extra
command line options to ps2pdf (-dAutoFilterColorImages=false
-sColorImageFilter=FlateEncode should do it for colour images). I
thought embedding it in the PS file would be more flexible.

--
    Gaël

I'll look into this soon. I'm hesitant to add another rc option, maybe we can
consider using these settings as the defaults. I'll post again after I have
had a chance to play with it.

Defaulting to lossless FlateEncode compression seems like a good idea,
if the file is too big you can always run another distill cycle after
wards manually.

Another possibility would be to set the option based on the format of
the image loaded (I'm sure I read somewhere that it is planned to
support formats other than PNG). ie FlateEncode for GIF's and PNG's
and DCTEncode for JPEG's.

The resolution for Postscript is 72 dpi, and I'm not sure this can be changed.
Would you send me an example postscript file along with the original png?

Sure,
http://jimmacdonald.co.uk/matplotlib/image.png
http://jimmacdonald.co.uk/matplotlib/image.eps
http://jimmacdonald.co.uk/matplotlib/image.py

image.py generates image.eps from image.png. image.png is simple
enough for ps2pdf not to use DCT encoding. Looking at the postscript
shows that the image has resolution of 335x230 compared to the
original of 318x301.

JIM

···

---

I don't think this is a problem with the postscript backend. You're rescaling
the image in your script. Try something like this:

from pylab import *

rc('text', usetex=True)
rc('ps', usedistiller="xpdf")

figure(1,figsize=(6, 4))
im=imread('image.png')
imshow(im,interpolation='nearest')#,extent=[0.98, 20, 0.01, 0.5])
#axis('normal');
savefig('image.eps')

Darren

···

On Monday 31 July 2006 09:32, JIM MacDonald wrote:

> The resolution for Postscript is 72 dpi, and I'm not sure this can be
> changed. Would you send me an example postscript file along with the
> original png?

Sure,
http://jimmacdonald.co.uk/matplotlib/image.png
http://jimmacdonald.co.uk/matplotlib/image.eps
http://jimmacdonald.co.uk/matplotlib/image.py

image.py generates image.eps from image.png. image.png is simple
enough for ps2pdf not to use DCT encoding. Looking at the postscript
shows that the image has resolution of 335x230 compared to the
original of 318x301.

> I'll look into this soon. I'm hesitant to add another rc option, maybe we
> can consider using these settings as the defaults. I'll post again after
> I have had a chance to play with it.

Defaulting to lossless FlateEncode compression seems like a good idea,
if the file is too big you can always run another distill cycle after
wards manually.

Another possibility would be to set the option based on the format of
the image loaded (I'm sure I read somewhere that it is planned to
support formats other than PNG). ie FlateEncode for GIF's and PNG's
and DCTEncode for JPEG's.

[...]

Sure,
http://jimmacdonald.co.uk/matplotlib/image.png
http://jimmacdonald.co.uk/matplotlib/image.eps
http://jimmacdonald.co.uk/matplotlib/image.py

image.py generates image.eps from image.png. image.png is simple
enough for ps2pdf not to use DCT encoding. Looking at the postscript
shows that the image has resolution of 335x230 compared to the
original of 318x301.

Would you post an example where the ps2pdf flags make a big difference on the
output? I just tried with the above png, but I cant tell the difference
between the results with/without the new flags.

Darren

···

On Monday 31 July 2006 09:32, JIM MacDonald wrote:

Last image of http://scipy.org/GaelVaroquaux, the example script. You
can also have a look at the "pylab2pdf2 script, where I use
environmental variables to get a proper behaviour from GS and avoid this
problem.

···

On Mon, Jul 31, 2006 at 10:01:23AM -0400, Darren Dale wrote:

Would you post an example where the ps2pdf flags make a big difference on the
output? I just tried with the above png, but I cant tell the difference
between the results with/without the new flags.

--
    Gaël

I see. Thanks for pointing this out and providing the solution. The flags you
suggested are passed to ps2pdf as of svn 2639.

Darren

···

On Monday 31 July 2006 10:05, Gael Varoquaux wrote:

On Mon, Jul 31, 2006 at 10:01:23AM -0400, Darren Dale wrote:
> Would you post an example where the ps2pdf flags make a big difference on
> the output? I just tried with the above png, but I cant tell the
> difference between the results with/without the new flags.

Last image of http://scipy.org/GaelVaroquaux, the example script. You
can also have a look at the "pylab2pdf2 script, where I use
environmental variables to get a proper behaviour from GS and avoid this
problem.

Great ! Thanks.

    I like open source software so much because of these little details
:->.

···

On Mon, Jul 31, 2006 at 10:19:46AM -0400, Darren Dale wrote:

I see. Thanks for pointing this out and providing the solution. The flags you
suggested are passed to ps2pdf as of svn 2639.

--
    Gaël

Would you post an example where the ps2pdf flags make a big difference on the
output? I just tried with the above png, but I cant tell the difference
between the results with/without the new flags.

http://jimmacdonald.co.uk/matplotlib/MPD_SinPulse_g0.500.png

JIM

···

---

I don't think this is a problem with the postscript backend. You're rescaling
the image in your script. Try something like this:

from pylab import *

rc('text', usetex=True)
rc('ps', usedistiller="xpdf")

figure(1,figsize=(6, 4))
im=imread('image.png')
imshow(im,interpolation='nearest')#,extent=[0.98, 20, 0.01, 0.5])
#axis('normal');
savefig('image.eps')

I just tried that and it still rescales the image, this time to
243x230. I've found I can use the figsize kwarg to control the
resolution of the embedded image, but of course this means I can't
have the figure the size I want it.

JIM

···

---