26
$\begingroup$

Bug persisting through 11.3


I understand that Mathematica has a bug when exporting images. The ticks are scaled not correctly when exporting at high resolution. For example: when you do:

Export["xx.png", plot, ImageResolution -> 360];

The image looks good, but all the frame ticks are all gone. When you do

Export["xx.png", plot, ImageResolution -> 100];

The ticks are there, but the resolution of the image is not good enough.

I tried the trick of using ImportString and ExportString:

ImportString[ExportString[plot, "PDF"]

It works, but creates another problem: the PlotRangeClipping option is missing, and the figure has plot lines sticking out all the way to the boundary of the image, not the boundary of the axes.

Can someone provide an easy and relatively universal workaround?

$\endgroup$
10
  • 1
    $\begingroup$ See here: stackoverflow.com/questions/8805451/… $\endgroup$
    – Szabolcs
    Commented Jun 23, 2014 at 22:33
  • 1
    $\begingroup$ Do you need it to be a rasterized image? If not, you can probably export it as a vector graphic (.pdf or .eps) which can scale to whatever size you need later, and then you don't need to define a resolution on export. $\endgroup$
    – ThomasH
    Commented Jun 24, 2014 at 8:31
  • 1
    $\begingroup$ Hi. Exporting it as a vector graphic .pdf or .eps does work. However, neither of these are friendly with Microsoft, so I can't easily put them in the context. $\endgroup$
    – Jun Yang
    Commented Jun 24, 2014 at 15:24
  • 2
    $\begingroup$ Adding "PNG" to export doesn't have any effect. $\endgroup$ Commented Jan 15, 2016 at 20:48
  • 2
    $\begingroup$ The PNG exporter is not scaling the ticks so they end of too small to see. A work-around is to export in PDF and convert the PDF image to PNG in an external app. I did the conversion in OS X's Preview app and got good results. $\endgroup$
    – m_goldberg
    Commented Jan 16, 2016 at 1:09

5 Answers 5

7
$\begingroup$

The following workaround can be seen as an alternative to simpler and more reliable (but in some situations not appropriate) workaround suggested by Jens. It is not perfect because in addition to being significantly more complicated it has several limitations due to abundance of bugs in Export-related functionality:

  • ImageSize must be specified in Export explicitly, it is not sufficient to provide it inside of Graphics expression

  • Scaled font size specification for tick mark labels must be provided via the FrameTicksStyle option in order to the default ImagePadding -> All behaving properly

  • The font size of PlotLabel must be absolute because specifying it as Scaled reveals a bug

  • I'm sure there also are other situations when handling of Scaled font size is broken and absolute font size must be specified

  • The distance between the tick mark labels and the frame gets smaller when you increase ImageSize and there is no proper way to control this distance

The following is a way to generate scalable tick marks and tick mark labels for all types of plots using only built-in (but undocumented) functions of version 10. Please note that it works correctly only for version 10 and already includes a fix for this bug (tested with versions 10.2 and 10.3.1):

data = Array[# &, 600];

linearFrameTicks = {
   {Most /@ Charting`ScaledTicks[{Identity, Identity}][##] &, 
    Most /@ Charting`ScaledFrameTicks[{Identity, Identity}][##] &}, 
   {Most /@ Charting`ScaledTicks[{Identity, Identity}][##] &, 
    Most /@ Charting`ScaledFrameTicks[{Identity, Identity}][##] &}};
p1 = Show[ListPlot[data, Frame -> True, FrameStyle -> Thickness[.003], 
    FrameTicksStyle -> Directive[FontSize -> Scaled[.02], Thickness[.003]]], 
   FrameTicks -> linearFrameTicks, PlotLabel -> "Linear FrameTicks", 
   LabelStyle -> FontSize -> 40, ImageSize -> 1000];
Export["p1.png", p1, ImageSize -> 1000]

p1

linearLogFrameTicks = {
   {Most /@ Charting`ScaledTicks[{Log, Exp}][##] &, 
    Most /@ Charting`ScaledFrameTicks[{Log, Exp}][##] &}, 
   {Most /@ Charting`ScaledTicks[{Identity, Identity}][##] &, 
    Most /@ Charting`ScaledFrameTicks[{Identity, Identity}][##] &}};
p2 = Show[ListLogPlot[data, Frame -> True, FrameStyle -> Thickness[.003], 
    FrameTicksStyle -> Directive[FontSize -> Scaled[.02], Thickness[.003]]], 
   FrameTicks -> linearLogFrameTicks, PlotLabel -> "LinearLog FrameTicks", 
   LabelStyle -> FontSize -> 40, ImageSize -> 1000];
Export["p2.png", p2, ImageSize -> 1000]

p2

logLinearFrameTicks = {
   {Most /@ Charting`ScaledTicks[{Identity, Identity}][##] &, 
    Most /@ Charting`ScaledFrameTicks[{Identity, Identity}][##] &}, 
   {Most /@ Charting`ScaledTicks[{Log, Exp}][##] &, 
    Most /@ Charting`ScaledFrameTicks[{Log, Exp}][##] &}};
p3 = Show[ListLogLinearPlot[data, Frame -> True, FrameStyle -> Thickness[.003], 
    FrameTicksStyle -> Directive[FontSize -> Scaled[.02], Thickness[.003]]], 
   FrameTicks -> logLinearFrameTicks, PlotLabel -> "LogLinear FrameTicks", 
   LabelStyle -> FontSize -> 40, ImageSize -> 1000];
Export["p3.png", p3, ImageSize -> 1000]

p3

logLogFrameTicks = {
   {Most /@ Charting`ScaledTicks[{Log, Exp}][##] &, 
    Most /@ Charting`ScaledFrameTicks[{Log, Exp}][##] &}, 
   {Most /@ Charting`ScaledTicks[{Log, Exp}][##] &, 
    Most /@ Charting`ScaledFrameTicks[{Log, Exp}][##] &}};
p4 = Show[ListLogLogPlot[data, Frame -> True, FrameStyle -> Thickness[.003], 
    FrameTicksStyle -> Directive[FontSize -> Scaled[.02], Thickness[.003]]], 
   FrameTicks -> logLogFrameTicks, PlotLabel -> "LogLog FrameTicks", 
   LabelStyle -> FontSize -> 40, ImageSize -> 1000];
Export["p4.png", p4, ImageSize -> 1000]

p4

$\endgroup$
1
  • $\begingroup$ Still works with V11. $\endgroup$
    – Johu
    Commented Aug 28, 2018 at 14:41
6
$\begingroup$

OK, I'll just put up this work-around - it's not perfect because the scaling of the ticks has never worked properly, to my knowledge:

list = {{{10., 5.}, {40., 20.}, {160., 80.}}, {{10., 1.83772}, {40., 
     13.6754}, {160., 67.3509}}, {{10., 8.16228}, {40., 
     26.3246}, {160., 92.6491}}};

myPlot = ListPlot[list, Frame -> True, 
   FrameLabel -> {"Sample Size n", "Number of Successes: k "}, 
   FrameTicksStyle -> Directive[Large, FontSize -> 12], 
   ImageSize -> 6*72];

Export["plot.png", Style[myPlot, Magnification -> 1], 
 ImageResolution -> 360, ImageSize -> 6*72]

plot

This doesn't display very well at the small ImageSize that was specified in the question, so I tripled that size. You can adjust the Magnification to vary the relative size of the ticks. For this image size, a value of 1 seems to work best. It's counter-intuitive, but you have to include the Style command even though it seems to do nothing.

For a smaller image size, you should choose a larger value, e.g., Magnification -> 2 to get the ticks to be visible.

$\endgroup$
5
  • $\begingroup$ (+1) Quite unexpectedly but it works (versions 9.0.1 and 10.3.1)! Actually ImageResolution does nothing here as well as RasterSize: the final size (in the sense of resolution of generated raster image) is determined by the ImageSize option of Export. This option controls the pixel size of the plot in versions 9.0.1 and 10.3.1 but unfortunately does nothing in version 8.0.4. $\endgroup$ Commented Feb 16, 2016 at 7:25
  • $\begingroup$ @AlexeyPopkov You're right - I copied the ImageResolution option from the question... $\endgroup$
    – Jens
    Commented Feb 16, 2016 at 7:45
  • $\begingroup$ I joined others in voting to close this as a duplicate. Assuming you do not disagree with that closure, do you think this should be merged, which will move your answer to that question? $\endgroup$
    – Mr.Wizard
    Commented Feb 16, 2016 at 14:37
  • $\begingroup$ @Mr.Wizard Of course, that's fine. $\endgroup$
    – Jens
    Commented Feb 16, 2016 at 15:15
  • $\begingroup$ A magnification other than 1 might be preferable in some cases - see this $\endgroup$ Commented Oct 30, 2016 at 13:52
5
$\begingroup$

It is doof but it is working (I had the same problem):

Export["p5.png", 
 Import[Export["p5.pdf", p5, ImageSize -> 360, 
   ImageResolution -> 1000]], ImageResolution -> 1000]

where p5 the name of your plot

$\endgroup$
5
  • $\begingroup$ Yes! It works. Thank you! $\endgroup$
    – tanghe2014
    Commented Mar 5, 2017 at 1:11
  • $\begingroup$ Could you modify your code to a function, then others can use it easier? $\endgroup$
    – tanghe2014
    Commented Mar 5, 2017 at 1:21
  • 2
    $\begingroup$ This is great in many cases, but if you specify a font for the plot (e.g. to use the LaTeX font), then the initial output as a PDF removes that formatting and the rasterized version will have the default Mathematica font. $\endgroup$ Commented Apr 26, 2017 at 17:28
  • 1
    $\begingroup$ Per Aaron, I am getting characters in my plot labels removed or scrambled. (Looks good otherwise.) It is crazy this is still broken. $\endgroup$ Commented Aug 15, 2018 at 17:37
  • 2
    $\begingroup$ 3 years later, and it's still broken for me... I can't believe I just literally can't properly export a PDF of a plot I'm staring at. $\endgroup$ Commented Oct 3, 2018 at 22:40
4
$\begingroup$

UPDATE

Starting from Mathematica version 9 one can use comparatively simple workaround suggested by Jens. For previous versions the only known workaround is providing manual Ticks specifications, see below.


Original answer

This problem is described here as well.

Slava Nadvorny suggests using manual Ticks specifications. In this case they will scale with ImageResolution.

The CustomTicks package will make it considerably easier to create manual tick specifications.

$\endgroup$
2
  • 3
    $\begingroup$ BTW I believe this is a bug. Why don't you ask support at wolfram.com about it? If more people complain there's higher chance that it'll be fixed. $\endgroup$
    – Szabolcs
    Commented Jun 23, 2014 at 22:35
  • 10
    $\begingroup$ I envy your optimism... $\endgroup$
    – Jens
    Commented Jun 24, 2014 at 3:17
0
$\begingroup$

I finally create a rasterized eps file with sufficent quality for my needs without losing the ticks. Maybe can be helpful even for other file formats outputs.

Try this double rasterization, where you can increase the ImageResolution value, but I do not recomend to increase the RasterSize beyond 515 or the ticks will disappear:

myPlot

Rasterize[%, "Graphics", RasterSize -> 500];

Rasterize[%, "Graphics", ImageResolution -> 350]

Export["myPlot.eps", %]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.