Make figure without white border
285 views (last 30 days)
Show older comments
I have a piece of code that plots a surface, and I feel it is ready for being included into the report. The only thing is that the figure has a quite large white border which substantially increases the size of it. I would like to have the unnecessary white space reduced to a minimum.
I did try
set(gca,'LooseInset',get(gca,'TightInset'))
But this cuts off my z-axis label. Is there an easy way to achieve this? With LaTeX, we can simply use the standalone documentclass with PGFplots/tikz, but I don't think there's a simple keyword or option to do this with matlab. I'm using R2016b.
0 Comments
Accepted Answer
Chad Greene
on 8 Feb 2017
export_fig removes the border by default.
1 Comment
Sim
on 5 Jan 2022
Edited: Sim
on 5 Jan 2022
Hi, I have used both the following functions to save a figure as a PDF file:
print (figure_name, '-dpdf','-opengl','-r600', [path, plot_name{:}] )
export_fig([path, plot_name{:}], '-pdf', '-opengl','-r600');
Result:
Even though the matlab built-in function print does not crop the white margins in a PDF figure (right?), it mantains a very good resolution/quality of the saved PDF figure. The file exchange export_fig crops instead the white space in a figure automatically, but it reduces a bit the quality of the saved PDF figure, resulting in slightly blurry contours (after zooming in).
This is just my experience, but if you know a reason for the loss of quality in a PDF figure by using export_fig, please let me know!
All the best
More Answers (6)
atilla Maia
on 19 Dec 2018
Edited: KSSV
on 1 Feb 2024
I have tried many suggestions. This one works for me:
f = figure;
F= getframe(f);
img = F.cdata;
imwrite(img, filename) ;
0 Comments
Gyaneshwar dubacharla
on 9 Aug 2020
Moved: Image Analyst
on 20 Aug 2023
Use this command from MATLAB - exportgraphics(gca,fname.emf,'BackgroundColor','none')
1 Comment
Hajra Afzal
on 26 Apr 2021
Moved: Image Analyst
on 20 Aug 2023
@Gyaneshwar dubacharla exportgraphics(gca,fname.emf,'BackgroundColor','none') worked for me. Thankyou for sharing. I faced quite a hassle before implementing this command.
0 Comments
Thomas
on 20 Aug 2023
Maybe this way?
fig_1 = figure(1);
clf();
n = 512;
m = 2 * n + 1;
j = ones(1, m);
i = (-n : n) / n;
i = i .* i;
ii = i' * j;
img = real(sqrt(1 - (ii' + ii)));
imshow(img);
hold on;
lw = .01 * m;
x = 4 * lw + (m - 8 * lw) * [.25 .25 .50 .75 .25 .75 .25 .75 .75];
y = 4 * lw + (m - 8 * lw) * [1.0 .50 .00 .50 .50 1.0 1.0 .50 1.0];
plot(x, y, LineWidth = lw, Color=[1 0 0]);
title("ball with santa's house");
hold off;
new_bordersize = 2; % must not be greater than the original border
img = remove_border(frame2im(getframe(fig_1)), new_bordersize);
imwrite(img, "ball_with_santas_house.tiff");
%%REMOVE_BORDER
function img = remove_border(img, new_bordersize)
%REMOVE_BORDER
% default value for new_bordersize is zero.
if ~exist("new_bordersize", "var")
new_bordersize = 0;
end
% get the border color
col = img(1, 1);
% get the image size
[h, w, ~] = size(img);
% search from left for the first column that not contains only the border-color
x0 = 0;
while x0 < w
x0 = x0 + 1;
if ~all(img(:, x0) == col)
break;
end
end
% search from rigth for the first column that not contains only the border-color
x1 = w + 1;
while 1 < x1
x1 = x1 - 1;
if ~all(img(:, x1) == col)
break;
end
end
% search from bottom for the first row that not contains only the border-color
y0 = 0;
while y0 < h
y0 = y0 + 1;
if ~all(img(y0, :) == col)
break;
end
end
% search from top for the first row that not contains only the border-color
y1 = h + 1;
while 1 < y1
y1 = y1 - 1;
if ~all(img(y1, :) == col)
break;
end
end
% calculate the sub image size to cut out
x0 = max(0, x0 - new_bordersize);
x1 = min(w, x1 + new_bordersize);
y0 = max(0, y0 - new_bordersize - 7);
y1 = min(h, y1 + new_bordersize);
% return the new image
img = img(y0 : y1, x0 : x1, :);
end
1 Comment
DGM
on 20 Aug 2023
Trimming after the fact is not ideal, but it is often the only option left.
That said, the whole trimming process can be simplified. In this example, I use an image with a non-white background for sake of demonstration. While I'm reading the image from a file for simplicity, the same applies to an image as captured using getframe()/frame2im().
The original padding is removed and new padding added. In this case, the result demonstrates that the new padding is not constrained by the original amount of padding.
% inputs
inpict = imread('stuffthings.png');
padwidth = [50 0]; % [y x]
% create a mask of non-BG pixels
mask = ~all(inpict == inpict(1,1,:),3);
% find ROI geometry
mkr = any(mask,2);
mkc = any(mask,1);
r1 = find(mkr,1,'first');
r2 = find(mkr,1,'last');
c1 = find(mkc,1,'first');
c2 = find(mkc,1,'last');
% crop original image to extents
roipict = inpict(r1:r2,c1:c2,:,:);
% re-pad as specified
% doing this with IPT or base tools is clumsy, but it's fine
% doing the padding this way instead of shifting subscripts
% allows the output padding to be unconstrained by the original image size
szo = size(roipict,1:2)+2*padwidth;
outpict = zeros(szo,class(roipict));
for c = 1:size(inpict,3)
outpict(:,:,c) = padarray(roipict(:,:,c),padwidth,inpict(1,1,c),'both');
end
imshow(inpict,'border','tight')
figure
imshow(outpict,'border','tight')
Of course, there are more convenient ways. If I were doing it with MIMT, this simplifies to:
% inputs
inpict = imread('stuffthings.png');
padwidth = [100 10]; % [y x]
% create a mask of non-BG pixels
bg = inpict(1,1,:);
mask = ~all(inpict == bg,3);
% crop original image to extents
[~,rr,cc] = crop2box(mask);
outpict = inpict(rr,cc,:,:);
% re-pad as specified
outpict = addborder(outpict,padwidth,ctflop(bg));
imshow(outpict,'border','tight')
... or more simply:
% inputs
inpict = imread('stuffthings.png');
padwidth = [100 10]; % [y x]
% crop uniform border vectors
outpict = cropborder(inpict,NaN(1,4));
% re-pad as specified
bg = inpict(1,1,:);
outpict = addborder(outpict,padwidth,ctflop(bg));
imshow(outpict,'border','tight')
Chris
on 16 Aug 2024
Edited: Chris
on 16 Aug 2024
This is by no means the most elegant solution, but in my case I was saving figures as *.png files and then cropping them down once I'd inserted them onto a PowerPoint slide. After about 60 of these I found this thread. Since I'm the only one doing this work and I'm always working on the same monitor, I developed the following workflow:
- create an image that is the size of my monitor,
- save the figure as a PNG file,
- load it back in using imread,
- crop the image matrix down to the height and width I want using the associated row/column ranges,
- save it out again overwriting the original PNG using imwrite.
The code looks like this:
test = rand(100,1);
f = figure('units','normalized');
plot(test,'LineWidth',3)
legend('Random Noise')
set(gca,'LineWidth',2,'YLim',[-0.1, 1.1],'FontSize',64)
set(f,'Position',[0,0.0333,1.0000,0.9132])
saveas(f,'test','png')
im = imread('test.png');
imwrite(im(100:2025,461:5000,:),'test.png')
The difference in the saved images goes from this:
->||<-
To this:
->||<-
I've been working on a large monitor and haven't noticed any negative impact on the image quality.
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!