Force saved figure to use a specific number of pixels
18 views (last 30 days)
Show older comments
I am saving different maps, I need to compare some specific pixels, but Matlab somehow adds a line at the bottom (3 pixels) for example when I save my image, which kills everything I try to do later. Is there any method to force exportgraphics to use X pixels horizontally and Y vertically (I mean height and width)? Or when I call my figure to be X and Y dimensions? Force it not to add this line. I tried exportgraphics/export_fig they both fail at it.
It is not random, as only some specific files get the line added and always even if I try to replot, I still did not figure out why this happens, my data have the same resolution/grid.
Edit: The issue is what Walter proposed. Sometimes, I have data on the edge of my map, and because in my example I make a plot (set a marker to the area), it can extend beyond the limits, and will require extra pixels from my figure to be displayed. Easy fix is increasing the limit of the map, using smaller markersize, or setting a NaN values to the border of the data. Other fix have still not been provided (imresize does not work as intended). It may be an issue with m_map package pushing the pixels when it needs to, but I have seen this exact same problem for videos, so I guess this is internal to some matlab functions. If someone can reproduce my plot and return the same width/heights with no distortion that would solve the issue.
8 Comments
DGM
on 12 Sep 2024 at 1:31
Yes. As far as I know, the dot marker is the only one that's handled like this. That at least makes the output geometry independent of marker locations.
I believe other posts have suggested using multiple overlaid axes for forcing clipping, but that doesn't really help us with capture.
I believe there are other ways to get the correct position information, particularly in newer versions (newer than what I have), but the above attached captureaxes() can be still be used to force clipping to the axes.
% the example
rng('default');
X = 12 + (16-12) * rand(1, 10000);
Y = 25 + (30-25) * rand(1, 10000);
figure('units','normalized','outerposition',[0 0 1 1]);
set(gcf,'color','w')
m_proj('equidistant','lon',[12 16],'lat',[25 30]);
hp = m_plot(X,Y,'.r','markerSize',30); % we need this handle
m_gshhs_h('patch',[0.5 0.5 0.5],'edgecolor','none');
m_grid('XLabel', [],'YLabel',[],'XTickLabel',[],'YTickLabel',[],...
'linestyle','none');
% use captureaxes to resize the figure to fit the plot box
% that way all markers and labels are clipped, regardless of style
maxw = 900; % temporary size needs to be able to fit on-screen (adjust as needed)
szo = round(maxw./hp.Parent.PlotBoxAspectRatio(1:2)) % on-screen geometry
onscreen = captureaxes(gca,szo); % resize figure (output can be discarded if undesired)
imwrite(onscreen,'screenshot.png'); % 900x639
% instead of using the on-screen render from captureaxes
% export_fig() can be used to render the resized figure
% at resolutions that won't fit on screen
% either using -r or -m options
export_fig('ex1.png', '-r150') % 1405x997 (taller than my screen)
While captureaxes() can work for images small enough to fit on screen, it can also just be used as a tool for setting up the figure for capture with export_fig().
Answers (2)
Image Analyst
on 30 Aug 2024
"I am saving different maps" <== What, like a road map, or an image with different colormaps?
"I save my image" ...with "... exportgraphics." <== If you have an image you should use imwrite, not exportgraphics. It will save exactly what is in the matrix and not add any extra lines or columns.
5 Comments
Image Analyst
on 31 Aug 2024
Not right on hand, but it sounds like you really want the screenshot rather than the image inside. So you can save the entire window using exportgraphics to a PNG format file (NOT JPG), then you can have a few lines of code to read it back in, determine the bounding box of non-background stuff, then crop it and resave it. Something like (untested)
rgbImage = imread(filename);
grayImage = rgb2gray(rgbImage);
% Find all pixels that are NOT background:
background = grayImage ~= 255; % Or whatever the background intensity is.
% Find row and column of bounding box.
[rows, columns] = find(background);
row1 = rows(1);
row2 = rows(end);
col1 = cols(1);
col2 = cols(end);
rgbImage = rgbImage(row1:row2, col1:col2, :) % Crop it.
imwrite(rgbImage, filename); % Resave it.
This will crop the image so that there is no background surrounding it. It will be a very tight bounding box with labels and titles (or tick marks if there are no axes labels) on the very outside edge of the image (first and last rows/columns).
Walter Roberson
on 31 Aug 2024
The problem with this approach is that, except under narrow conditions, the size of axes is not consistent even when max(data)-min(data) is consistent. You can capture, you can trim, you can resize for consistency... but the images so produced are going to be inconsistent in having features line up with the other images.
Walter Roberson
on 30 Aug 2024
Edited: Walter Roberson
on 30 Aug 2024
You can getframe() and imresize() to a fixed size
The results are not likely to be satisfactory. Yes, you would get out the same sized image each time -- but the images would not generally be aligned.
It turns out that the exact size the MATLAB choses to render an axes depends upon the tick labels. The right-most tick label might be shifted up to 2 pixels left or up to 3 pixels right in order to have the labels be positioned "nicely". This changes the axes size. And it depends on exactly how many pixels are needed to render the tick labels. Remember that tick labels are typically proportionate fonts, so it isn't enough to make sure that the labels are always the same number of characters. 11.75 needs a different number of pixels than 12.75 does, for example.
To ensure that the axes is a consistent size you would need to use constant x and y tick labels and constant x and y labels and constant x and y data span and constant titles.
1 Comment
DGM
on 30 Aug 2024
I never realized that the tick labels were part of the equation, but it makes sense that it would appear so unpredictable. I might have to dig into that.
See Also
Categories
Find more on Printing and Saving in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!