6
$\begingroup$

I work with histograms and would like to export it to EPS format. I've noticed that my exported image loses the PlotRangeClipping option that I set up when I export the plot. This is true for at least EPS, PNG and PDF.

Based on this question and its accepted answer, I defined the function

OutlinedExport[name_,gr_,opts:OptionsPattern[]]:=
Export[
    name,
    First@ImportString[
        ExportString[
            gr,
            "PDF"
        ],
        "PDF",
        "TextOutlines"->True
    ],
    FilterRules[
        {opts},
        Options[Export]
    ]
]

Now here is an example of histogram

data = Table[InverseCDF[NormalDistribution[0, 1], Random[]], {i, 1000}];
PlotB = Histogram[data, 20,
    PlotRange -> {{-2, 2}, Automatic},
    Frame->True]
OutlinedExport["output2.pdf", PlotB, ImageSize -> 600]

which appears to have lost the clipping during the export.

The questions are :

  • Is there a way to preserve clipping as defined through options like PlotRangeClipping and PlotRangePadding ?

  • If the problem is related with the OutlinedExport, is there a way to answer my question while also keeping the outline of fonts (which I need but have here removed for the sake of example) ?

$\endgroup$

3 Answers 3

5
$\begingroup$

Since there is clearly a bug in Import with the PDF format, there can only be workarounds and compromise solutions. By exporting as in your own answer, you will retain the setting of PlotRangeClipping because at no point is it necessary to re-import the exported PDF to Mathematica. However, this way you almost certainly will run into missing font problems when importing the PDF (or EPS) into other graphics programs. For example, Adobe Illustrator and likewise Inkscape will be unable to display your graphic with the correct fonts in general.

I tried this with Inkscape and your exported file test.pdf, and it doesn't work properly.

So you could resort to finger-painting as in Mr.Wizard's answer where the clipped parts are hidden behind added rectangles, so that the result of outlinedExport look correct.

Or you could retreat to another approach which I invented long ago, relying on an external program to convert fonts to outlines. That's what I used to do before Mathematica even had the ability to produce outlined fonts at all. The external dependence is ghostscript.

If you want to go that route, here is an updated version of that procedure:

gsExport[exportName_, ob_, opts : OptionsPattern[]] := Module[
  {device,
   printOption = First@Options[$FrontEnd, PrintingStyleEnvironment],
   out = FileNameJoin[{$TemporaryDirectory, 
      "MathematicaOutput" <> StringJoin[Map[ToString, DateList[]]] <> 
       ".pdf"}]
   },
  SetOptions[$FrontEnd, PrintingStyleEnvironment -> "Working"];
  Export[
   out,
   ob,
   "PDF",
   FilterRules[{opts}, Options[Export]]
   ];
  SetOptions[$FrontEnd, printOption];
  device = 
   If[ToLowerCase[FileExtension[exportName]] == "eps", "epswrite", 
    "pdfwrite", "pdfwrite"];
  Run["gs -sDEVICE=" <> device <> " -dNOCACHE -sOutputFile=" <> 
    exportName <> " -q -dbatch -dNOPAUSE " <> out <> " -c quit"];
  DeleteFile[out]
  ]

It takes the export file name and the graphics object (ob) as the first two arguments, and also accepts additional options appropriate for PDF export. By default it exports to PDF with the provided name (exportName), but if you specify an en extension .eps you will get encapsulated postscript instead. The fonts are replaced y outlines by executing gs via Run. This assumes that gs is installed and in your system's executable PATH.

I thought this approach was obsolete by now, but apparently there are still enough bugs in Mathematica that open-source solutions must come to the rescue once again.

Update:

The above solution continues to work with gs version 9.16, but according to this answer on StackOverflow (and thanks to Szabolcs for pointing it out) there is a new option that you could use in the future, if you encounter problems: replace -dNOCACHE by -dNoOutputFonts.

$\endgroup$
1
  • $\begingroup$ Nice alternative. Thanks ! $\endgroup$
    – Pschoofs
    Aug 3, 2012 at 7:19
6
$\begingroup$

Since the clipping is lost, and I cannot find a way to make Import/Export retain it, I suggest adding it manually:

PlotC =
 Show[
  PlotB,
  Graphics[{White, Rectangle[Scaled[{-1, 0}], Scaled[{0, 1}]], 
                   Rectangle[Scaled[{ 1, 0}], Scaled[{2, 1}]]}]
 ]

OutlinedExport["output4.pdf", PlotC, ImageSize -> 600]

Mathematica graphics

This works by drawing a white rectangle on either side of the plot range behind the frame labels (here shown in pink instead):

Show[PlotB, 
 Graphics[{LightRed, Rectangle[Scaled[{-1, 0}], Scaled[{0, 1}]], 
                     Rectangle[Scaled[{ 1, 0}], Scaled[{2, 1}]]}]]

Mathematica graphics

You may need larger $x$ values inside Scaled to cover the full range, e.g.:

Rectangle[Scaled[{-100, 0}], Scaled[{0, 1}]]

$\endgroup$
2
$\begingroup$

Actually the problem comes from the OutlinedExport function defined above which does not keep any clipping options. Fortunately, it seems possible to do without and keep the font embedding in the pdf.

The second answer from the question referred above actually answers this one too.

SetOptions[$FrontEnd, PrintingStyleEnvironment -> "Working"];
data = Table[InverseCDF[NormalDistribution[0, 1], Random[]], {i, 1000}];
PlotB = Histogram[data, 20, PlotRange -> {{-2, 2}, Automatic},
  FrameTicksStyle -> {
    Directive[
        Bold,
        FontFamily -> "Palatino Linotype",
        FontSize -> 14
        ],
    Directive[
        Bold,
        FontFamily -> "Palatino Linotype",
        FontSize -> 14
        ]
    },
  Frame -> True,
  PlotRangeClipping -> True,
  ImagePadding -> {{80, 10}, {60, 5}},
  PlotRangePadding -> Scaled[0.02],
  FrameLabel -> {
    Style[
        "blahblah",
        FontFamily -> "Palatino Linotype",
        FontSize -> 16
        ],
    Style[
        "blahblah",
        FontFamily -> "Palatino Linotype",
        FontSize -> 16]
    }]
Export["test.pdf", PlotB, ImageSize -> 600]

The function Export keeps then the font embedding as well as the PlotRangeClipping. It works for EPS, PDF,...

$\endgroup$
1
  • 1
    $\begingroup$ This does indeed work for exporting with embedded fonts as requested (+1). Interestingly though, if I now re-import that file using Import["test.pdf"][[1]], the clipping is lost again! What this shows is that the problem is clearly with Mathematica's PDF import. In my outlinedExport function which you were using, this must also be the place where things go wrong. I'll think about another workaround to that workaround.. $\endgroup$
    – Jens
    Aug 2, 2012 at 20:51

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.