18
$\begingroup$

I have a plot with some whitespace I'd like to get rid of. Ideally, I'd like to use a command like ImageCrop, but for non-raster graphics (ImageCrop rasterizes the graphic). The Mathematica documentation tells you how to do this by hand (under the "cropping" section):

http://reference.wolfram.com/mathematica/tutorial/InteractiveGraphicsLayout.html

...but there doesn't seem to be a way to do this via a command. I've tried all sorts of combinations of FrameMargins, ImageMargins, ImagePadding, etc, but to no avail. Even if I could just manually specify the number of pixels to crop by, that would be an improvement over the current situation, but ideally the best solution would be to replicate ImageCrop for non-raster graphics.

$\endgroup$
7
  • $\begingroup$ Have you looked into the option setting Method -> {"ShrinkWrap" -> True}? $\endgroup$ May 15, 2012 at 4:46
  • $\begingroup$ Gave that a try, it seems to have bizarre behavior, it crops out the tick labels entirely. It might only work for raw Graphics objects? I'm trying to do this with a Plot object. $\endgroup$
    – Guillochon
    May 15, 2012 at 4:57
  • 3
    $\begingroup$ Could you please give code for your plot and indicate which white spaces? $\endgroup$ May 15, 2012 at 5:20
  • $\begingroup$ The big question here: do you want to do this with the 'contents' of the graphics, i.e. all the graphics primitives? Or do you want this to work for all labels, tick marks, frames, etc.? If you only need the former, Show[g, PlotRange -> All, PlotRangePadding -> 0] should do it. If you need the latter, then you just opened Pandora's box ... $\endgroup$
    – Szabolcs
    May 15, 2012 at 7:47
  • $\begingroup$ If you need the latter, you can start with dirty hacks like this: mathematica.stackexchange.com/questions/2091/… (I uesd this several times, but I don't like it at all.) $\endgroup$
    – Szabolcs
    May 15, 2012 at 7:48

1 Answer 1

18
$\begingroup$

Edit

Come to think of it, one case where I often want to crop the output is Graphics3D (one can do it with ViewAngle etc., but it's not always convenient - one could also convert to bitmap, but again that's not always desirable). So I decided to allow the cropGraphics function below to be used with any object, not just 2D Graphics. Here is an example:

q = Show[ExampleData[{"Geometry3D", "Cow"}], ImageSize -> 360, 
  Background -> Darker[Green]]

Cow

cg = cropGraphics[q, -0.8, -0.4, 200, 200]

CowCropped

In the simple form defined below, cropGraphics requires the input object to have an explicit ImageSize setting. But it works for a wide range of objects. It can even be used to convert Overlay objects to Graphics while at the same time cropping them.

Speaking of Overlay, here is a continuation of the above example:

plot = Overlay[{Plot[Sin[x], {x, 0, 2 Pi}, GridLines -> Automatic, 
    Frame -> True, ImageSize -> 360],
   Magnify[cg, .5]}, Alignment -> {.5, .5}]

Overlay

This is an overlay with the cropped graphics created previously. Now crop this plot once again:

cropGraphics[plot, 0.5, 0, 300, 120]

cropped crop

End Edit

Here is the function that does the above. It is based on Inset, and it assumes for simplicity that the graphic you want to crop is going to be positioned in the crop window by placing the original coordinate {0,0} (in the coordinate system of the graphics) at a scaled position {x,y}. Here, x and y are between 0 and 1, with x = 0.5 corresponding to the center of the crop window. I'll explain this in an example:

cropGraphics[g_, x_, y_, w_, h_] := 
 Graphics[Inset[g, {x, y}, {0, 0}], PlotRange -> {{0, 1}, {0, 1}}, 
  ImageSize -> {w, h}, AspectRatio -> Full]

Here is a sample graphic; I would suggest always giving it a definite setting of ImageSize to begin with:

pl = Graphics[{{Red, Rectangle[{0, 0}, {.5, .5}]}, {Blue, 
    Disk[{1, 1}, .5]}}, PlotRange -> {{0, 1.5}, {0, 1.5}}, 
  ImageSize -> 400]

Example graphic

For reference, the bottom left corner of the square is at {0, 0}, and the graphics is 400 pixels wide and high.

Now we crop it:

cropGraphics[pl, 0, 0, 300, 300]

cropped 1

The coordinates 0, 0 mean that the bottom left corner of the square is still where it was before, but the new image width and height are 300.

If we want to crop part of the square instead, all we have to do is move its lower left corner {0, 0} outside the crop window by giving it negative scaled coordinates:

cropGraphics[pl, -.25, -.1, 300, 300]

crop 2

Finally, an example of a non-square crop area:

cropGraphics[pl, 0.5, -.24, 400, 300]

crop 2

One could improve on this by changing the scaled coordinates x and y to something absolute in pixels, but I wanted to keep it simple for now, to focus on the main issue: use Inset with a variable position in a "wrapper" graphic whose coordinate system ranges from 0 to 1 to make the inset position a scaled coordinate, and whose ImageSize has the value desired for the crop.

$\endgroup$
2
  • $\begingroup$ Related: cropping graphics without converting it to raster. $\endgroup$ Oct 30, 2013 at 18:47
  • $\begingroup$ (+1) It is really usefull; however, when try import the cropped .eps file the size of the exported file become very large which is strange! Also, It seems that the quality has been reduced a little. $\endgroup$ May 23, 2017 at 9:46

Your Answer

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

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