Printing figure alters content details

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 Commenti

did you try exportgraphics() instead of print(). then all axes etc are also preserved
Tried exportgraphics on MATLAB online, it produces the same type of artifacts as print.
increase dpi (resolution) to 1200 and try again maybe
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

Accedi per commentare.

Risposte (2)

Jonas
Jonas il 14 Lug 2022
Modificato: Jonas il 14 Lug 2022
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 Commento

Yi-xiao Liu
Yi-xiao Liu il 14 Lug 2022
Modificato: Yi-xiao Liu il 14 Lug 2022
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?

Accedi per commentare.

Yi-xiao Liu
Yi-xiao Liu il 4 Ago 2022
Modificato: Yi-xiao Liu il 4 Ago 2022
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.

Categorie

Scopri di più su Printing and Saving in Centro assistenza e File Exchange

Prodotti

Release

R2019b

Richiesto:

il 14 Lug 2022

Modificato:

il 4 Ago 2022

Community Treasure Hunt

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

Start Hunting!

Translated by