uifigure vector export size/resolution

16 views (last 30 days)
Suppose I want to export a uifigure to a vector file (*.pdf) at a specific size. The exportgraphics command has a resolution option, but that only works for bitmap files (*.png, etc.). Is there are way to explicitly control either the vector file size and/or resolution?
I'm trying to replicate what was once a useful feature of MATLAB figures. Traditional (Java based) figures use the print function, where the physical size of the figure could be replicated in that file. For example, I could make a 4"x6" figure on my screen that generated a 4"x6" PDF file. This process relied on the root ScreenPixelsPerInch setting, which stopped working in 2015b. For more information, see https://undocumentedmatlab.com/articles/graphic-sizing-in-matlab-r2015b.
Since (Javascropt) uifigures are sized purely on pixels, I was thinking that one could scale the window so that it appeared correctly on the screen. This usually requires a local calibration, e.g. adjusting a figure's width to match an 8.5" wide sheet of paper, and using that calibration to generate/control new uifigures. The problem is that those figures cannot be exported to the correct size in a vector format; bitmap files seem OK.
  2 Comments
Avni
Avni on 15 Dec 2023
Are you trying to implement something like this?
% Define desired physical size in inches and resolution in DPI
desired_width_in = 2; % Width in inches
desired_height_in = 3; % Height in inches
DPI = 300; % Desired dots per inch
% Calculate the size in pixels
width_px = desired_width_in * DPI;
height_px = desired_height_in * DPI;
% Create the uifigure with the calculated pixel dimensions
fig = uifigure('Position', [100, 100, width_px, height_px]);
% Add an axes component
ax = uiaxes('Parent', fig, 'Position', [0, 0, width_px, height_px]);
% Plot some data in the axes
x = linspace(0, 2*pi, 100);
y = sin(x);
plot(ax, x, y);
% Export the figure to a PDF file
% The size of the PDF will match the size of the uifigure
exportgraphics(ax, 'output_figure.pdf', 'ContentType', 'vector');
% Close the figure if no longer needed
close(fig);
Daniel Dolan
Daniel Dolan on 15 Dec 2023
@Avni: you describe one of the things I've tried. Since absolute sizing does not work, e.g. telling the figure to be 2" wide does not result in a 2" wide figure, one could scale those dimensions by a system-dependent DPI. For example, I can adjust a uifigure so that it's width matches an 8.5" piece of paper, query the figure's pixel width, and determine an effective DPI (about 128 on my Macbook with no external monitor). From that point on, any new figure can be scaled by that factor to achieve the correct physical size. Most graphics inside that figure are sized in a relative sense and can be rendered independently from that DPI. Text, which is usually specified in points, is an important exception where effective DPI scaling is needed. All this can be a pain, but it is possible to create a correctly sized uifigure (with text) on the screen.
When that figure is exported, however, the resulting graphic does not automatically match the screen size. For bitmap files, you wouldn't necessarily want to use the effective DPI in the previous step because lines/text would be blurred; 300-600 DPI would probably be acceptable, but now the physical size is wrong. Vector exports ignore the resolution argument, resulting in some entirely different size. I've tried several variations of this and it never quite works.
What I'm asking for is a MATLAB graphic that can be:
  • Explicitly sized to some physical specifications (e.g., 4").
  • Correctly displayed at the above dimensions with accurate font sizing (e.g., 10 points is 10/75" on the screen)
  • Precisely printed/exported to a file preserving the above dimensions. I should be able to lay a 100% representation of that file (either physicall printed or in digital form) precisely on top of the screen figure. Apart from bounding box differences (exterior white space might be trimmed in the file), all graphic sizes should exactly the same.
All of this was possible prior to R2015b and has been impossible since that time. Neither figures nor uifigures permit such rigorous control.

Sign in to comment.

Accepted Answer

Yair Altman
Yair Altman on 21 Dec 2023
Edited: Yair Altman on 21 Dec 2023
As already noted above, neither print nor the exportgraphics functions support setting the output page size, and ignore the figure's PaperSize property.
An alternative: use the export_fig utility with the 'preserve_size' parameter, to indicate that the figure's PaperSize should be used in the generated output (the exported contents will start from the bottom-left corner of the page). This should work well for both legacy (Java-based) figures and newer (web-based) uifigures:
export_fig(fig, 'figure.pdf', '-preserve_size');
Note that the PaperSize property works with the PaperUnits property to set the actual physical size. By default, a new figure's PaperSize is set to [8.5,11] and PaperUnits to 'inches', which corresponds to US letter size. These default values might be different based on your specific installation/setup, and can always be modified or set ad-hoc to a new value independently for each figure.
  1 Comment
Daniel Dolan
Daniel Dolan on 22 Dec 2023
I will have to give this a try. Was unaware that export_fig managed uifigures.

Sign in to comment.

More Answers (1)

Sujay
Sujay on 11 Dec 2023
Hi Daniel,
There is no direct way to export uifigure to a vector file (*.pdf) at a specific size using the exportgraphics command in MATLAB. The resolution option only works for bitmap files like PNGs. This creates a challenge for replicating the functionality of the print function used for traditional Java-based figures.
However, there are some workarounds you can try to achieve your desired outcome:
1) Manually set figure size: Use the uifigure.Position property to set the figure size in pixels. You can then export the figure using exportgraphics and use the Resolution option to ensure the exported image is of sufficient quality.
fig = uifigure('Position', [100 100 400 600]);
% Add your UI elements to the figure
exportgraphics(fig, 'figure.pdf', 'Resolution', 300);
2) Use the paperposition property: Set the fig.PaperPosition property to specify the desired size in units like centimeters or inches. This will determine the size of the exported PDF file.
fig = uifigure;
% Add your UI elements to the figure
fig.PaperUnits = 'centimeters';
fig.PaperPosition = [0 0 8.4 5];
exportgraphics(fig, 'figure.pdf');
3) Export to SVG and then to PDF:
  • Export the uifigure to an SVG file using the exportgraphics command.
  • Use a suitable vector graphics editor (Ex: Inkscape) to open the SVG file and resize it to your desired dimensions.
  • Save the file as a PDF.
The best approach will depend on your specific needs and preferences. Experiment with different methods and choose the one that best suits your workflow and desired output.
Regards,
Sujay
  1 Comment
Daniel Dolan
Daniel Dolan on 11 Dec 2023
None of these workarounds are acceptable.
  1. The resolution input is ignored for vector output, and there seems to be no obvious relationship between the number of pixels on the screen and physical size of the exported graphic. Font scaling is horrible, at least on my M1 Mac running R2023b.
  2. PaperPosition seems to have no discernable affect.
  3. The exportgraphics function does not support SVG.
In all three cases, there is severe disconnect between how the figure/uifigure looks on the screen and the printed/exported file.
It's been eight years since this problem came up, and we still don't have a fix!

Sign in to comment.

Categories

Find more on Develop uifigure-Based Apps in Help Center and File Exchange

Products


Release

R2023b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!