Remove whitespace around exported (saved) figure via imwrite

108 ビュー (過去 30 日間)
John Cruce
John Cruce 2021 年 9 月 28 日
編集済み: DGM 2021 年 9 月 29 日
I'm trying to save a figure using getframe and imwrite, however, there's a lot of whitespace around the figure I'd like to remove. Basically I want the saved png tight around the title, figure, and colorbar. Any thoughts on how I might do this? My code is below.
% Open figure
set(gca,'xtick',[],'xticklabel',[],'ytick',[],'yticklabel',[],'color','w');
set(gcf,'units','pixel','position',[0,10,650,650],'color','w');
m_proj('Miller Cylindrical','lon',[-92.5 -87.5],'lat',[27.5 32]);
m_grid('xtick',[],'ytick',[],'linestyle','none','backgroundcolor',[0 0 0]);
ax=gca;
colormap(jet(50));
% Set the scale of the colormap for the contours
caxis([0, 50]);
hcb=colorbar('SouthOutside');
hcb.Label.String='Color Bar Label';
axPos = ax.Position;
colorbarpos=hcb.Position;
% Position for SouthOutside colorbar
colorbarpos(2)=0.032+colorbarpos(2);
colorbarpos(4)=0.5*colorbarpos(4);
hcb.Position = colorbarpos;
ax.Position = axPos;
set(hcb,'YTick',[0:1:50],'TickLength',colorbarpos(4)/colorbarpos(3));
set(hcb,'YTickLabel',{'';'1';'';'';'';'5';'';'';'';'';'10';'';'';'';'';'15';'';'';'';'';'20';'';'';'';'';'25';'';'';'';'';'30';'';'';'';'';'35';'';'';'';'';'40';'';'';'';'';'45';'';'';'';'';'50';});
t = title({['\fontsize{12}','Test Plot']},'FontWeight','Bold');
f=getframe(gcf);
imwrite(f.cdata,'test.png','png');

採用された回答

Dave B
Dave B 2021 年 9 月 29 日
編集済み: Dave B 2021 年 9 月 29 日
If/when you upgrade to R2020a+ consider trying exportgraphics(gca, ...) which trims images nice and tight and may be easier than working with imwrite.
In the mean time...you could crop f.cdata based on the rows/columns that are all white (because your figure background is white).
% Open figure
set(gca,'xtick',[],'xticklabel',[],'ytick',[],'yticklabel',[],'color','w');
set(gcf,'units','pixel','position',[0,10,650,650],'color','w');
imagesc(magic(10)) % I didn't have m_proj so I used image as a placeholder
ax=gca;
colormap(jet(50));
% Set the scale of the colormap for the contours
caxis([0, 50]);
hcb=colorbar('SouthOutside');
hcb.Label.String='Color Bar Label';
axPos = ax.Position;
colorbarpos=hcb.Position;
% Position for SouthOutside colorbar
colorbarpos(2)=0.032+colorbarpos(2);
colorbarpos(4)=0.5*colorbarpos(4);
hcb.Position = colorbarpos;
ax.Position = axPos;
set(hcb,'YTick',[0:1:50],'TickLength',colorbarpos(4)/colorbarpos(3));
set(hcb,'YTickLabel',{'';'1';'';'';'';'5';'';'';'';'';'10';'';'';'';'';'15';'';'';'';'';'20';'';'';'';'';'25';'';'';'';'';'30';'';'';'';'';'35';'';'';'';'';'40';'';'';'';'';'45';'';'';'';'';'50';});
t = title({['\fontsize{12}','Test Plot']},'FontWeight','Bold');
f=getframe(gcf);
iswhite=min(f.cdata,[],3)==255;
blankcols=all(iswhite,1);
col_ind = find(~blankcols,1,'first'):find(~blankcols,1,'last');
blankrows=all(iswhite,2);
row_ind = find(~blankrows,1,'first'):find(~blankrows,1,'last');
cropdata = f.cdata(row_ind,col_ind,:);
% demo of pre/post trim (for ML answers, can remove for export)
figure
tiledlayout(1,2,'Padding','none','TileSpacing','tight')
image(nexttile,f.cdata); axis image;xticks([]);yticks([])
image(nexttile,cropdata);axis image;xticks([]);yticks([])
% uncomment this to write the image
% imwrite(cropdata,'test.png','png');
Exported image

その他の回答 (1 件)

DGM
DGM 2021 年 9 月 29 日
編集済み: DGM 2021 年 9 月 29 日
Is there any reason you're not using print(), saveas(), or exportgraphics()?
Instead of
f=getframe(gcf);
imwrite(f.cdata,'test.png','png');
you could try
saveas(gcf,'testsaveas.png');
or maybe
print('testprint','-dpng');
or exportgraphics(), which I don't have (I guess you don't either).
If none of that changes the padding sufficiently, or if you need to process existing saved figures, you'll have to crop the images. You could use imcrop() if you could determine the correct rect parameter, but that's going to be a pain. MIMT has cropborder(), which has optional automatic cropping modes specifically for tasks like this:
% Open figure
set(gca,'xtick',[],'xticklabel',[],'ytick',[],'yticklabel',[],'color','w');
set(gcf,'units','pixel','position',[0,10,650,650],'color','w');
h = surf(3.2*peaks+23); h.EdgeAlpha = 0.1;
ax=gca;
colormap(jet(50));
% Set the scale of the colormap for the contours
caxis([0, 50]);
hcb=colorbar('SouthOutside');
hcb.Label.String='Color Bar Label';
axPos = ax.Position;
colorbarpos=hcb.Position;
% Position for SouthOutside colorbar
colorbarpos(2)=0.032+colorbarpos(2);
colorbarpos(4)=0.5*colorbarpos(4);
hcb.Position = colorbarpos;
ax.Position = axPos;
set(hcb,'YTick',[0:1:50],'TickLength',colorbarpos(4)/colorbarpos(3));
set(hcb,'YTickLabel',{'';'1';'';'';'';'5';'';'';'';'';'10';'';'';'';'';'15';'';'';'';'';'20';'';'';'';'';'25';'';'';'';'';'30';'';'';'';'';'35';'';'';'';'';'40';'';'';'';'';'45';'';'';'';'';'50';});
t = title({['\fontsize{12}','Test Plot']},'FontWeight','Bold');
f = getframe(gcf);
f = cropborder(f.cdata,[NaN NaN NaN NaN],'threshold',0.0001);
f = addborder(f,10,[1 0 0],'normalized'); % for web demo only!
imwrite(f,'test.png','png');
imshow(f)
In this example, I added a red border so that you can see where the image boundary is against the white website background. You obviously don't need to add a red border to anything.
As mentioned, cropborder() is from MIMT on the FEX:
Cropborder webdocs are here:

カテゴリ

Help Center および File ExchangeConvert Image Type についてさらに検索

製品


リリース

R2018a

Community Treasure Hunt

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

Start Hunting!

Translated by