Printing figure alters content details

1 回表示 (過去 30 日間)
Yi-xiao Liu
Yi-xiao Liu 2022 年 7 月 14 日
編集済み: Yi-xiao Liu 2022 年 8 月 4 日
I am trying to print some figures generated by imagesc into png images for portability. However, I found the output to lose some details in the figure and original data
load data.mat
fig=figure("visible","off");
imagesc([X(1),X(end)],[Y(1),Y(end)],Z)
colorbar
caxis([0,1])
axis equal
axis tight
fig.CurrentAxes.YDir = 'normal';
fig.CurrentAxes.FontSize=16;
fig.PaperPositionMode = 'auto';
fig.PaperUnits = 'inches';
fig.PaperPosition = [0,0,6,6];
print(fig,"imagesc.png",'-dpng','-r600')
close(fig)
imwrite(Z+1,parula(2),"direct.png")
imshow("imagesc.png")
imshow("direct.png")
If you zoom into the output (also attached), you will find that printing alters figure content, the origianlly continuous line becomes broken:
while in the original figure or directly writing there is no such artifact:
However I still want the axes, colorbar, etc. to show up in the output images. Is there any way to get around this problem?
  4 件のコメント
Jonas
Jonas 2022 年 7 月 14 日
increase dpi (resolution) to 1200 and try again maybe
Yi-xiao Liu
Yi-xiao Liu 2022 年 7 月 14 日
I did that, it doesn't change anything.
I also tried resizing the figure to be larger by setting the Position property. No luck either

サインインしてコメントする。

回答 (2 件)

Jonas
Jonas 2022 年 7 月 14 日
編集済み: Jonas 2022 年 7 月 14 日
couldn't find a professional solution for this, but here is a ugly one by including the colormap as pixel values. imwrite should then lead to a correct result
%% your code
load('data.mat','X','Y','Z');
fig=figure("visible","on");
imagesc([X(1),X(end)],[Y(1),Y(end)],Z);
colorbar;
caxis([0,1])
axis equal
axis tight
% get max and min values and add the values to the right of your image
cm=linspace(max(Z,[],'all'),min(Z,[],'all'),size(Z,1))';
cm=repmat(cm,[1 round(0.1*size(Z,1))]);
% also add NaN values
newIm=[Z nan(size(cm)) cm];
% NaN values shall be seen as transparent ('as empty')
imAlpha=ones(size(newIm));
imAlpha(isnan(newIm))=0;
figure;
im=imagesc([X(1),X(end)*1.4],[Y(1),Y(end)],newIm,'AlphaData',imAlpha);
%colorbar();
%caxis([0,1])
axis equal
axis tight
% remove box and set xruler line to white to avoid visibility in the NaN
% gap
box off;
ax=gca;
ax.XRuler.Axle.ColorData = uint8([255,255,255,255])';
%% now we want also the ticks
ticks=0.1:0.1:0.9;
nrOfTicks=numel(ticks);
posX=size(newIm,2)*ones(nrOfTicks,1);
posY=round(size(Z,1)*ticks)';
posY=flip(posY);
colors=[repmat([1 1 1],[floor(nrOfTicks/2) 1]);repmat([0 0 0],[ceil(nrOfTicks/2) 1])]; % add color in black or white
% unfortunately this function changes newIm to an rgb image
newImWithTicks=insertText(newIm,[posX posY],ticks,'FontSize',130,'TextColor',colors,'BoxOpacity',0,'AnchorPoint','RightCenter');
newImWithTicks=rgb2gray(newImWithTicks);
figure; imagesc([X(1),X(end)*1.4],[Y(1),Y(end)],newImWithTicks,'AlphaData',imAlpha)
ax=gca;
ax.YAxis.TickLength = [0 0];
% imwrite .....
newImWithTicks=ind2rgb(uint8(mat2gray(newImWithTicks)*255),colormap());
imwrite(newImWithTicks,'exmpl.png','Alpha',imAlpha)
  1 件のコメント
Yi-xiao Liu
Yi-xiao Liu 2022 年 7 月 14 日
編集済み: Yi-xiao Liu 2022 年 7 月 14 日
Thanks Jonas.
I suppose I can scale imagesc.png and replace the plotting region with direct.png to make it look even more 'original.' But I was looking for something more elegant like messing with the renderer. Because what if I need to add datatips or another layer of line plots on top?

サインインしてコメントする。


Yi-xiao Liu
Yi-xiao Liu 2022 年 8 月 4 日
編集済み: Yi-xiao Liu 2022 年 8 月 4 日
I have brought this to MATLAB support, they concluded that this is an visual artifact produced by the renderer when the on-screen size does not match the size of the data. The problem is that generally the figure size cannot be larger than your real screen. They proposed a workaround that invloves a undocumented property and exportgraphics() to print out-of-screen contents. However unfortunately they wish this undocumented handle not to be published.
However, I have come up with my own workaround, inspired by @Jonas. Essentially it scales the with-artifact image and replace the axis region with Original data. There needs to be some trial-and-error in adjusting the offsets if you want to be pixel-prefect.
fig=figure("visible","off");
imagesc([X(1),X(end)],[Y(1),Y(end)],Z)
colorbar
caxis([0,1])
axis equal
axis tight
fig.CurrentAxes.TickDir = 'both';
fig.CurrentAxes.YDir = 'normal';
fig.CurrentAxes.FontSize=16;
scaleratio=5.5;
margins=[50,50,100,50];
% left,bottom,right,top
fig.Position = [0,0,margins(1)+margins(3)+size(Z,2)/scaleratio,margins(2)+margins(4)+size(Z,1)/scaleratio];
fig.CurrentAxes.Units = 'pixels';
fig.CurrentAxes.Position = [margins(1),margins(2),size(Z,2)/scaleratio,size(Z,1)/scaleratio];
%https://github.com/altmany/export_fig
%export_fig makes it easier to make faithful reproduction of on-screen
%looks
fig.Color = 'w';
figframe=export_fig(fig,'-nocrop',"-m"+scaleratio);
close(fig)
img=ind2rgb8(Z+1,parula(2));
Axesoffsets=[5,-5];%adjust as needed, roughly the width of axes in pixels
insertpos=margins(1:2).*scaleratio+Axesoffsets;
insertpos=[insertpos,insertpos+size(img,[1,2])-1];
figframe(insertpos(1):insertpos(3),insertpos(2):insertpos(4),:)=img;
imwrite(figframe,"imagesc.png")
Open in new tab to zoom in
It uses a third pary library export_fig(). In pricinple you can do without because it's just a convenient wrapper of print(). But it makes things a lot easier.

カテゴリ

Help Center および File ExchangePrinting and Saving についてさらに検索

タグ

製品


リリース

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by