Printing figure alters content details

2 Ansichten (letzte 30 Tage)
Yi-xiao Liu
Yi-xiao Liu am 14 Jul. 2022
Bearbeitet: Yi-xiao Liu am 4 Aug. 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 Kommentare
Jonas
Jonas am 14 Jul. 2022
increase dpi (resolution) to 1200 and try again maybe
Yi-xiao Liu
Yi-xiao Liu am 14 Jul. 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

Melden Sie sich an, um zu kommentieren.

Antworten (2)

Jonas
Jonas am 14 Jul. 2022
Bearbeitet: Jonas am 14 Jul. 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 Kommentar
Yi-xiao Liu
Yi-xiao Liu am 14 Jul. 2022
Bearbeitet: Yi-xiao Liu am 14 Jul. 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?

Melden Sie sich an, um zu kommentieren.


Yi-xiao Liu
Yi-xiao Liu am 4 Aug. 2022
Bearbeitet: Yi-xiao Liu am 4 Aug. 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.

Kategorien

Mehr zu Environment and Settings finden Sie in Help Center und File Exchange

Produkte


Version

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by