Printing figure alters content details

1 vue (au cours des 30 derniers jours)
Yi-xiao Liu
Yi-xiao Liu le 14 Juil 2022
Modifié(e) : Yi-xiao Liu le 4 Août 2022
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 commentaires
Jonas
Jonas le 14 Juil 2022
increase dpi (resolution) to 1200 and try again maybe
Yi-xiao Liu
Yi-xiao Liu le 14 Juil 2022
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

Connectez-vous pour commenter.

Réponses (2)

Jonas
Jonas le 14 Juil 2022
Modifié(e) : Jonas le 14 Juil 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 commentaire
Yi-xiao Liu
Yi-xiao Liu le 14 Juil 2022
Modifié(e) : Yi-xiao Liu le 14 Juil 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?

Connectez-vous pour commenter.


Yi-xiao Liu
Yi-xiao Liu le 4 Août 2022
Modifié(e) : Yi-xiao Liu le 4 Août 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.

Catégories

En savoir plus sur Printing and Saving dans Help Center et File Exchange

Produits


Version

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by