5

I want to find the ImageSize or at least dimensions of any control object irrespective of it being an image or an any other control such as Buttons,etc.

This is my code for button:

button = Button["ew", Null, ImageSize -> {100, 50}]

ImageDimensions provides size of images only and not of control objects. So, initially, I rasterized my control object using Rasterize. And then displayed the image dimensions. However the image dimensions is not exact value.

rastButton = Rasterize[button, RasterSize -> 100]  
bt = Button["ew", Null, {ImageSize -> {100, 50}}]  
rastbt = Rasterize[bt, RasterSize -> 100]  
ImageSize[rastbt]  
ImageDimensions[rastbt]  
(*  Out[272] = {100, 52} *)

bt = Button["ew", Null, {ImageSize -> {100, 1}}]
rastbt = Rasterize[bt, RasterSize -> 100]
ImageSize[rastbt]
ImageDimensions[rastbt]
(* Out[272] = {100, 17} *)

I also believe Rasterize provides error values when I call Rasterize[button][[2, 2]]. Is this a bug? Is there any workaround to estimate the size of control objects?

Ultimately, the purpose of estimating the size is to place the control object very accurately in a grid layout within specified co ordinates.

kglr
  • 394,356
  • 18
  • 477
  • 896
niren
  • 743
  • 4
  • 13

3 Answers3

2

If you use the Option ImageSize for Rasterize then it is correct. Notice that 15 seems to be the minimum height for a button, such that the Rasterize result agrees.

   button=Button["ew",Null,ImageSize->{100,50}]
    rastButton=Rasterize[button,ImageSize->{100,50}]
    bt=Button["ew",Null,{ImageSize->{100,50}}]
    rastbt=Rasterize[bt,ImageSize->{100,50}]

    ImageDimensions[rastbt]
 (*
==> {100,50}
  *)
    bt=Button["ew",Null,{ImageSize->{100,15}}]
    rastbt=Rasterize[bt,ImageSize->{100,15}]
    ImageSize[rastbt]
    ImageDimensions[rastbt]
    (*
==> {100,15}
*)

Using ImportString and ExportString

ImageDimensions[
   ImportString[ExportString[#, "TIFF"], "TIFF"]] &@button

(* gives {100,52} *)

Appearance is the clue here:

buts = Button["xx", Null, Appearance -> #] & /@ {"DialogBox", 
   "Palette", "FramedPalette", "Frameless", 
   "Pressed", {"DialogBox", "Pressed"}}

Mathematica graphics

Mathematica graphics

Rolf Mertig
  • 17,172
  • 1
  • 45
  • 76
  • I used your idea to solve my problem as follows bt = Button[sd, Null, ImageSize -> {10, 20}]; Rasterize[bt][[2, 2]] ImageDimensions[Rasterize[bt, ImageSize -> {10, 20}]] Rasterize[bt][[2, 2]] It gives me result as (*{10, 28},{10, 20},{10, 28}*). I want to find exact button size. The idea you have given is Rasterize the button size and give result, but i want to extract exact size. – niren Jan 17 '13 at 08:17
  • So that i could place it with correct co ordinate and correct size irrespective of its original size. – niren Jan 17 '13 at 08:27
1

Just my $0.02, though I don't think you'll like what I have to say. There used to be a function called Developer'BoundingBox which was succeeded by options to Rasterize. You do not actually have to rasterize an object to gets its size. Rasterize[expr,"BoundingBox"] is enough. You can also supply option "RasterSize" which will return the size of the final image, but that depends more on ImageSize, ImageResolution and other parameters than on the actual component itself.

Here's the deal breaker however... Bounding box depends on font sizes and rendering. So If your object has any of its parts measured in ems, like Grid with ItemSize, you will not have an accurate BoundingBox:

Works:

Works without ItemSize

Broken:

Broken with ItemSize

Anyone who can explain this will be my personal hero, as I need this to work properly VERY MUCH.

Thank you!

Gregory Klopper
  • 1,370
  • 9
  • 21
  • It would be better to post actual code followed by screenshots of the output. As it is seen from your "broken" example Rasterize[expr,"BoundingBox"] determines the bounding box correctly. What happens is that inside of Overlay the document width seems to be counted by Scaled ItemSize smaller than just inside of the Cell. – Alexey Popkov Oct 30 '13 at 03:41
  • You're right about posting code in a copy-able way, my apologies, I rushed. You're touching on the core issue here: the Grid seems to be re-created in a Cell before it is rasterized. The problem is not just with use of Scaled, but line wrapping for long strings and other events which can occur during this process that cause Rasterize to be off. How would one retrieve the actual displayed Grid (or Column, or any other complex construct for that matter) size, as displayed, not as re-interpreted in a new Cell? – Gregory Klopper Oct 30 '13 at 04:22
  • AFAIK currently there is no such way in general. Sometimes CurrentValue with Dynamic allows to get information you seek but there are only few specific cases (search for "currentvalue" this site). One workaround would be to select the object in question by hands and then copy it as "Bitmap" (under Windows). Then you can investigate this raster image directly. I also suspect that your real problem is just ill-posed and there may be a way to achieve what you want without such functionality. – Alexey Popkov Oct 30 '13 at 05:48
  • Copy as Bitmap can be done programmatically, and while it will destroy clipboard contents, this is actually not a bad, however crude it may be, solution. One would simply have to write the ridiculously complex selection routine that will select exact content you want to measure, then copy as MGF and work with image properties of that image, then empty the clipboard. Alternatively, it's probably possible to cache what was in clipboard before and then put it back, unless it's some really complex content. – Gregory Klopper Oct 30 '13 at 06:11
  • Yes, all these is possible. Another alternative would be to copy entire Cell somewhere in the same Notebook, then convert it to Bitmap and to assign the Bitmap to some variable for further investigation, then delete the duplicate Cell. But I think there should be only very rare cases when all of this is really necessary. If you are sure that you problem cannot be solved in different way, it is worth to create separate question (and it is good idea to express the real problem, because currently I cannot imagine what it may be...). – Alexey Popkov Oct 30 '13 at 06:28
  • The question has been raised on here more than once, and the bottom line is that Mathematica is good for a great number of things, but clean beautiful UI design is not one of them. If you use Overlay as a layering construct, you may eventually want more than just one layer interacted with (can't do that). If you are using Column/Row/Grid for spacing, you need to know how much space they took up so other elements can orient to them. – Gregory Klopper Oct 30 '13 at 13:11
  • Recent problem: a Grid was used as a primary visual element in a Panel, now I need a row of buttons underneath - 2 on the left, 1 on the right. Where's the right and where's the left? If I wrap the whole thing into a Grid, then I lose the ability to do Scaled in ItemSize. If I don't, I've no idea what width the Grid ended up being, so my buttons cannot line up with it no matter what I do. I tried Grid[{buttonsLeft,buttonsRight},ItemSize->{{Scaled[.5],Scaled[.5]}}] but no luck. Seems Scaled is computed at wrong times, so new size, set by main grid isn't seen. – Gregory Klopper Oct 30 '13 at 13:17
  • Scaled functionality is very gedanken in Mathematica. One reason for this is that there already too much automatic scalings and it is really difficult to coordinate all of it and even worse, there already are edge cases when user can specify automatic scaling relative to automatic scaling relative to ... original automatically determined scaled size! The only workaround is to implement scaling functionality by yourself for your particular task, I have given an example here. – Alexey Popkov Oct 30 '13 at 14:54
  • Noted. Thank you. I still stick to my opinion that WAY TOO MUCH work is required for fairly simple UI/UX tasks, which should be fast and intuitive in 2013 in a language as powerful as Mathematica. (...continued in next comment) – Gregory Klopper Oct 30 '13 at 15:31
  • School homework demos with Manipulate are great and all, but in the world of Flash, HTML5, D3, Tableau, Spotfire, Visual.ly, the fact that 90% of visuals produced in Mathematica look like they were made in 1999, lack animation/transitions, and there's no way to quickly measure an object to get its size, lay out elements EXACTLY where you want them, and create absolutely-positioned layers, instead of Overlay, all that is just a really loud warning to Wolfram developers that Mathematica may fall short in the world of big data visualization and rapid data-driven app development. – Gregory Klopper Oct 30 '13 at 15:32
  • Strictly speaking, absolutely-positioned layers are supported by Graphics and Graphics3D. I have not tried to inset Grid-like constructs but it is definitely possible. Overlay is a kludge for such task and its purpose probably is different (although I have not worked much with Overlay). Mathematica's FrontEnd has absolutely unique paradigm of data representation and visualization. But it is gedanken and develops very slowly. The reason is that there are very few people who develop it and these people also work for other projects in parallel. – Alexey Popkov Oct 30 '13 at 16:02
  • Here you can find an example of exactly positioned layers in Graphics which are made from Graphics3D (implementation of missing functionality of Export). I think this shows how correctly in really these things are implemented. There were many bugs those times, some of them are fixed now but most of them are still here. But despite them it is possible to get precise result! From the other side, you are right: it is necessary to love Mathematica very much and to have significant free time for going in the hell of corrupted functionality :(. – Alexey Popkov Oct 30 '13 at 17:27
  • Upper management doesn't seem to appreciate FrontEnd paradigms. :-) A new kid with R and D3 has put out interactive animated gorgeous set of visuals that put my non-trivial and rather laborsome advanced CDFs to shame. Granted that I ultimately have more capabilities and other/unique ones that D3 cannot do and R is not suitable for, but unless those are your core business, it boils down to rapid delivery of attractive interactive GUIs (beyond manipulates) which are as functional as they are pleasing to the eye and have shallow learning curve. "Medium is the message" - presentation matters. – Gregory Klopper Oct 30 '13 at 17:30
  • Nice to hear, I still have not tried R and even do not know what D3 is. It would be interesting to see what is possible to achieve with them! :-) – Alexey Popkov Oct 30 '13 at 17:37
  • FYI: D3 -- http://d3js.org/ – Gregory Klopper Oct 30 '13 at 17:42
0

It seems form the documentation that the right function for that is AbsoluteCurrentValue[]. Indeed the description: ?AbsoluteCurrentValue coincides pretty close with what is looked for. However,

pl = Plot[ Sin[t], {t, 0, 2 \[Pi]}, ImageSize -> 100];
AbsoluteCurrentValue[pl, ImageSize]

returns {350, 350} and also

pl = Plot[ Sin[t], {t, 0, 2 \[Pi]}, ImageSize -> 200];
AbsoluteCurrentValue[pl, ImageSize]

returns {350, 350}. ??

Alexei Boulbitch
  • 39,397
  • 2
  • 47
  • 96