Saving tiledlayout with imagesc exactly as shown

74 ビュー (過去 30 日間)
Felix Müller
Felix Müller 2021 年 10 月 28 日
回答済み: Felix Müller 2021 年 11 月 1 日
I am producing images of matrices with imagesc() and want to save them exactly as they are on the screen. Each pixel in my data is assigned a certain number which corresponds to a color from the colormap. In my MWE the data is random so it is easier to provide.
Because I want to compare two consecutive timesteps I am using a tiled layout to have the two timesteps next to each other in one picture. I create the tiled layout, call imagesc() on the two tiles and want to save the whole thing.
Now the problem: I do not find a way to save that actually preserves each pixel. No matter the resolution (I already tried 2000dpi) or the method, there is always a difference between the produced png and the data that is shown on screen. I have verified that the display from imagesc in the figure corresponds to the data matrix, so the difference comes up in the saving process.
I have tried multiple functions for saving (print, save, saveas, exportgraphics, imwrite), but of course maybe I have missed some critical option when using them.
Any ideas how to preserve each pixel exactly?
PS:
  1. I do not require the outut to be pictures (png, jpg, ...), but would prefer it.
  2. I do not need the plot to be shown on screen, I would be fine if it is saved directly.
MWE:
% create data (dim1 and dim2 are in the range of 10^2 to 10^4)
dim1 = 400;
dim2 = 700;
data1 = randi(3, dim1, dim2);
colors1 = [[1 0 0]; [0 1 0]; [0 0 1]];
data2 = randi(4, dim1, dim2);
colors2 = [[1 0 0]; [0 1 0]; [0 0 1]; [1 1 0]];
% data1 and data2 would typically have ~10-15 different interger entries and corresponding colormaps
% create figure and tiled layout
fig = figure();
t = tiledlayout(2, 1); % create tiled layout
t.TileSpacing = 'compact';
t.Padding = 'compact';
title(t, 'Big Title')
% first plot
nexttile(1)
imagesc(data1)
colormap(colors1)
title('First small plot')
axis image;
% second plot
nexttile(2)
imagesc(data2)
colormap(colors2)
title('Second small plot')
axis image;
% save it
print(fig, 'saved_with_print', '-dpng', '-r300'); % save as png with 300dpi
print(fig, 'saved_with_print_and_painters', '-dpdf', '-painters', '-fillpage') % print as pdf
% also tried: imwrite, exportgraphics, saveas

採用された回答

Felix Müller
Felix Müller 2021 年 11 月 1 日
I have given up for now.
The best I could get was to save the pictures individually using imwrite, ind2rgb and uint8:
imwrite(ind2rgb(uint8(data1), colors1), 'pic1.png')
For this to work I had to add another color at the beginning of my colormap because the count for ind2rgb starts at 0 (and my data started at 1).
When reloading the pictures and trying to assemble them in a tiledlayout the same problems as before came up (as was expected).

その他の回答 (2 件)

Dave B
Dave B 2021 年 10 月 28 日
You mentioned that you tried imwrite, did you use a strategy that combined getframe/imwrite? Something like:
im = getframe(fig);
imwrite(im.cdata, 'myfile.png')
If that doesn't produce images that match what you're seeing on screen, I wonder if you could identify whether the difference you're seeing is between what's shown on screen and what's in im.cdata or what's in im.cdata and what's in the file...I'd be surprised about either but it might be a good debugging step.
  1 件のコメント
Felix Müller
Felix Müller 2021 年 11 月 1 日
The difference is between the figure shown on screen and im.cdata already. The dimensions of im.cdata already are downsized to 420 by 560 pixels (where I originally have 400 and 700 in each plot so in total there is more than double that in the whole figure).
So im.cdata and the png are the same, but getframe already reduces the resolution. I suspect that depends on the resolution of my screen where the figure is shown. Is it possible in Matlab to work without this graphic display? I don't want to see the figure on my screen, I just want the file exactly as plotted.

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


yanqi liu
yanqi liu 2021 年 10 月 29 日
clc; clear all; close all;
% create data (dim1 and dim2 are in the range of 10^2 to 10^4)
dim1 = 400;
dim2 = 700;
data1 = randi(3, dim1, dim2);
colors1 = [[1 0 0]; [0 1 0]; [0 0 1]];
data2 = randi(4, dim1, dim2);
colors2 = [[1 0 0]; [0 1 0]; [0 0 1]; [1 1 0]];
% data1 and data2 would typically have ~10-15 different interger entries and corresponding colormaps
% create figure and tiled layout
fig = figure('Visible', 'off');
t = tiledlayout(2, 1); % create tiled layout
t.TileSpacing = 'compact';
t.Padding = 'compact';
title(t, 'Big Title')
% first plot
nexttile(1)
imagesc(data1)
colormap(colors1)
title('First small plot')
axis image; axis off;
f = getframe(gca);
imwrite(mat2gray(frame2im(f)), 'First.png');
% second plot
nexttile(2)
imagesc(data2)
colormap(colors2)
title('Second small plot')
axis image; axis off;
f = getframe(gca);
imwrite(mat2gray(frame2im(f)), 'Second.png');
% save it
% print(fig, 'saved_with_print', '-dpng', '-r300'); % save as png with 300dpi
% print(fig, 'saved_with_print_and_painters', '-dpdf', '-painters', '-fillpage') % print as pdf
% also tried: imwrite, exportgraphics, saveas
  1 件のコメント
Felix Müller
Felix Müller 2021 年 11 月 1 日
Thanks for the reply. This will not work since 1. getframe does not capture the exact image but reads it from the screen (see other answer and comments) and 2. I want the result to include both pictures and not save all of them individually.

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

カテゴリ

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

製品


リリース

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by