Azzera filtri
Azzera filtri

Printing figure alters content details

3 visualizzazioni (ultimi 30 giorni)
Yi-xiao Liu
Yi-xiao Liu il 14 Lug 2022
Modificato: Yi-xiao Liu il 4 Ago 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 Commenti
Jonas
Jonas il 14 Lug 2022
increase dpi (resolution) to 1200 and try again maybe
Yi-xiao Liu
Yi-xiao Liu il 14 Lug 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

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 Help Center e File Exchange

Prodotti


Release

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by