Trouble saving sub-figure within a Custom UIComponent

24 views (last 30 days)
Christian
Christian on 19 Nov 2024 at 1:28
Commented: Walter Roberson on 19 Nov 2024 at 2:17
Hello there,
I have a custom Canvas UIComponent that I have close to working called canvas_mre. This component is suposed to have a working canvas that I can manually draw, save and load a picture. It is also supposed to rescale the image to a specified size as a form of compression. (Side note: if anyone is aware of a good canvas app that's already made, I would be tremendously grateful)
The app works as a standalone app (meaning if I just run canvas_mre by itself). The image capture works nicely and the loaded image is a low-res version of the picture I drew. Perfect.
When I use it as part of a larger app that has a UIGridLayout, I end up with inconsistent behavior and I am having trouble understanding why it happens. When I have a single Canvas within the larger grid system, the relative Y position (how many rows down) affects how much the of the figure is captured (compare the different one_component*.mlapp files). Additionally, having two components causes them both to be (mostly) captured, with a slight shift.
I set up the image via
function set_clean_image(comp)
Layout = matlab.ui.layout.GridLayoutOptions('Row',[1 5],'Column',2);
comp.ax = axes(comp.GridLayout, ...
'Box','on', ...
'XLim',[0, comp.dimensions(2) ], ...
'YLim',[0, comp.dimensions(1) ], ...
'XTick',[], ...
'YTick',[], ...
'Visible', 'off'...
,'Layout',Layout ...
);
comp.ax.Visible = 'on';
comp.ax.DataAspectRatio = [1 1 1];
if isempty(comp.dimensions)
comp.dimensions = [32 32];
end
if ndims(comp.dimensions) == 3
comp.bitmap = comp.dimensions;
else
comp.bitmap = repmat(reshape([ 255 255 255],1,1,3), comp.dimensions(1), comp.dimensions(2), 1);
end
comp.ax.Interactions = [];
set(comp.ax, 'YDir', 'reverse'); % Ensure Y-axis direction is normal
try %#ok<TRYNC>
comp.ax.Toolbar.Visible = 'off';
end
end
and I capture the cdata of the image/axis is via
function cdata = extract_cdata(comp)
% Capture the frame of the entire figure and save the image
frame = getframe(comp.ax);
img = frame.cdata; % Save the image to a file
cdata = imresize(img, [comp.dimensions(1) , comp.dimensions(2) ]);
end
  1. Why does the secondary grid affect the image capture?
  2. Why does the positioning within the second grid affect the screen capture?
  3. What is the appropriate way to capture the image with respect to the local axis/reference grid?
Edit:
I've also considered obtaining the cdata via this alternative implementation but prefer it less because it loses focus from the original window and leaves it focused on the main MATLAB window for some reason.
function cdata = extract_cdata(comp)
% Create temporary invisible figure for clean capture
temp_fig = figure('Visible', 'off');
temp_ax = copyobj(comp.ax, temp_fig);
% Reset position and remove borders/spacing
temp_ax.Position = [0 0 1 1];
temp_ax.Box = 'off';
temp_ax.XTick = [];
temp_ax.YTick = [];
% Ensure axes limits match image dimensions exactly
temp_ax.XLim = [0, comp.dimensions(2)];
temp_ax.YLim = [0, comp.dimensions(1)];
% Force drawing update
drawnow;
% Capture frame without borders
frame = getframe(temp_ax);
% Clean up temporary objects
close(temp_fig);
% Resize to exact dimensions
cdata = imresize(frame.cdata, [comp.dimensions(1), comp.dimensions(2)]);
end
  1 Comment
Walter Roberson
Walter Roberson on 19 Nov 2024 at 2:17
if isempty(comp.dimensions)
If comp.dimensions were empty, then you would not be able to
comp.ax = axes(comp.GridLayout, ...
'Box','on', ...
'XLim',[0, comp.dimensions(2) ], ...
'YLim',[0, comp.dimensions(1) ], ...
'XTick',[], ...
'YTick',[], ...
'Visible', 'off'...
,'Layout',Layout ...
);
as that requires comp.dimensions(2)

Sign in to comment.

Answers (0)

Products


Release

R2024b

Community Treasure Hunt

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

Start Hunting!