Retrieving the ImagePadding in absolute units

Consider the following graphic:

g = Graphics[Circle[], Frame -> True, FrameLabel -> {"one", "two"}]


Retrieving the ImagePadding by traditional means does not work:

AbsoluteOptions[g, ImagePadding]

(* ==> {ImagePadding -> All} *)


My guess for the reason behind this is that it is the Front End that can compute the actual value of the ImagePadding to use, so this can't be obtained without first rasterizing the image in the front end.

Is there some trick to get a numerical value for the ImagePadding so I can align two figures (make them have the same ImagePadding) and use an optimal value (not too small cutting off something, not too large wasting space), perhaps by asking the Front End directly?

Note that the ImagePadding is in absolute coordinates (printer's points, not plot coordinates).

-
to align plots i always explicitly set image padding in all plots. is there some reason you do not want to do that? – Mike Honeychurch Feb 21 '12 at 21:33
@Mike The question is: what padding should we use to ensure that all tick marks and labels are visible and no space is wasted? If there's a lot of label / tick / font size and style tweaking, each of those will require me to manually re-adjust the image padding. Heike's solution works quite well and spared me this (very real) trouble. – Szabolcs Feb 21 '12 at 22:00
ok. I understand now :) – Mike Honeychurch Feb 21 '12 at 22:42

This almost works but seems to be 1 point off some of the time

im = Image[Show[g, LabelStyle -> White, Background -> White]];
BorderDimensions[im]


For example for

g = Graphics[Circle[], Frame -> True, FrameLabel -> {"one", "two"},
ImagePadding -> {{35, 20}, {40, 50}}]


The output is

{{35, 19}, {40, 50}}

-
Off by 1-2 pixels is not a big deal. The solution is still usable. Off by 6-8 would be too inaccurate. – Szabolcs Feb 21 '12 at 13:45

This works sometimes (for framed graphics only):

absoluteImagePadding[g_] :=
Module[{img, lines, small, big, x1, x2, y1, y2},
img = Rasterize[Show[Graphics[{}], Sequence @@ Options[g]], "Image"];
lines = ImageLines[ColorNegate[img], .25];
{small, big} =
Sort@Cases[lines, {{_, a_}, {_, b_}} /; Abs[a - b] < 2 :> Mean[{a, b}]];
{y1, y2} = Round[{small, ImageDimensions[img][[2]] - big}];
{small, big} =
Sort@Cases[lines, {{a_, _}, {b_, _}} /; Abs[a - b] < 2 :> Mean[{a, b}]];
{x1, x2} = Round[{small, ImageDimensions[img][[1]] - big}];
{{x1, x2}, {y1, y2}}
]


It works by rasterizing the image, detecting the frame lines and measuring their position. It is an extremely hackish and fragile workaround though.

-

Edit: more seriously this time, this actually should be helpful.

fill = Show[#,
Epilog -> {
Black, Rectangle[ImageScaled[{0, 0}], ImageScaled[{1, 1}]],
Red, Rectangle[Scaled[{0, 0}], Scaled[{1, 1}]]
}
] &;

rle = Part[Length /@ Split @ #, {1, -1}] &;

imgpad[g_] := With[{dat = ImageData[fill @ g]},
{rle @ dat[[#]], Reverse @ rle @ dat[[All, #2]]} & @@ Quotient[Dimensions @ dat, 2]
]


Usage:

imgpad[graphic]


I don't have the function BorderDimensions but I presume this could be substituted for the part after the fill.

-
You need to use ImageData to get the image data (not Part, in the bin function). The Image format changed in version 8, but ImageData works. The last number returned is incorrect and needs to be adjusted to the image height here (I get {{30, 1}, {32, 223}} instead of {{35, 1}, {32, 0}}) – Szabolcs Feb 21 '12 at 14:28
@Szabolcs please tell me if this is working now. – Mr.Wizard Feb 21 '12 at 14:38
It still doesn't work correctly. imgpad[DensityPlot[x, {x, -1, 1}, {y, -1, 1}]] gives me {{17, 1}, {13, 341}}. Sorry, really don't have time to dig into why right now ... just an example where it gives an incorrect reasult – Szabolcs Feb 21 '12 at 15:04
@Szabolcs your test code returns: {{31, 3}, {20, 2}} on my system. – Mr.Wizard Feb 21 '12 at 15:06
This should be linked from the version compatibility testing question ... I'll try to figure out what's going on later. BTW Heike's method gives {{17, 1}, {14, 0}} for the same DensityPlot – Szabolcs Feb 21 '12 at 15:08