Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Save subplot images in axes in a GUI

283 views
Skip to first unread message

Rossella

unread,
Jan 26, 2011, 3:23:03 PM1/26/11
to
Hi,
I need to save an image plotted in a GUI.
Basically I have a GUI containing an axes in which I plotted three images using subplot. I have called the three subplot handles respectively:
handles.MainPlot
handles.IITPlot
handles.CPDPlot
The GUI axes handles is handles.axes_MainPlot.

If I want to save each image alone I have no problem:
f = getframe(handles.Mainplot); %Capture screen shot
[im,map] = frame2im(f);
imwrite(im,'Mainplot.jpg');

but if I try to save the entire figure (the axes composed of the three subplots) using the command:
f = getframe(handles.axes_MainPlot); %Capture screen shot

I got the following error:
??? Error using ==> capturescreen
Invalid object handle
Error in ==> getframe at 35
x=capturescreen(varargin{:});

On the other hand if I use saveas, it saves the entire GUI, while I'd like to save only the content of the axes handles.axes_MainPlot (that contains the three subplots).

Thank you in advance for any suggestion
Rossella

Paulo Silva

unread,
Jan 26, 2011, 5:03:03 PM1/26/11
to
> f = getframe(handles.axes_MainPlot); %Capture screen shot
>
> I got the following error:
> ??? Error using ==> capturescreen
> Invalid object handle
> Error in ==> getframe at 35
> x=capturescreen(varargin{:});
>
> On the other hand if I use saveas, it saves the entire GUI, while I'd like to save only the content of the axes handles.axes_MainPlot (that contains the three subplots).
>
> Thank you in advance for any suggestion
> Rossella

handles.axes_MainPlot isn't the handle for the axes, check it

Like this should work, gca is the current axes
f = getframe(gca);

Rossella

unread,
Jan 26, 2011, 5:30:06 PM1/26/11
to
Hi Paulo,

thank you for your suggestion. Unfortunately, that doesn't work neither as it selects only one of the three subplots (the current one). On the contrary, I would like to save the entire content of the axes handles.axes_MainPlot, that is the three subplots.

Thanks.
Rossella

"Paulo Silva" wrote in message <ihq5mn$rq9$1...@fred.mathworks.com>...

Think blue, count two.

unread,
Jan 26, 2011, 6:40:04 PM1/26/11
to

When you use subplot(), it deletes any axes that overlaps the place the
new axes will go. subplot() does not create "child" plots. There is no
axes that "contains" the three subplots: they are 3 different axes that
do not overlap. The complaint from Matlab is that the handle you are
using is not a valid handle anymore -- which would happen if it was in
the area that was to be written on by one of the subplots.

The saveas documentation says specifically:

"You can pass the handle of any Handle Graphics object to saveas, which
then saves the parent figure to the object you specified should h not be
a figure handle. This means that saveas cannot save a subplot without
also saving all subplots in its parent figure."

Therefore if only one subplot is being saved, then it is the only axes
that still exists in the figure.

Rossella

unread,
Jan 26, 2011, 7:07:03 PM1/26/11
to
Hi,
thanks for the explanation: it totally makes sense.
Still, I do not understand how I can come around this issue. I guess that the problem is that the three subplots are not in a figure, but rather in an axes in a GUI. How can I save the three subplots in one image format file? I tried with the command:
f = getframe(handles.uipanel_axes)
where handles.uipanel_axes is the handle of the panel containing the original axes where I later plot the three subplots, but, as expected I got the error:

??? Error using ==> capturescreen

A valid figure or axes handle must be specified


Error in ==> getframe at 35
x=capturescreen(varargin{:});

An alternative might be to define a specific area of the GUI and to save it as image, but I do not know if this is something possible.

Thanks
Rossella

"Think blue, count two." <robe...@hushmail.com> wrote in message <ph20p.40744$8_2...@newsfe17.iad>...

Matt Fig

unread,
Jan 26, 2011, 9:07:03 PM1/26/11
to
"Rossella" wrote in message <ihqcv7$5gn$1...@fred.mathworks.com>...

> Hi,
> thanks for the explanation: it totally makes sense.
> Still, I do not understand how I can come around this issue. I guess that the problem is that the three subplots are not in a figure, but rather in an axes in a GUI.

NO. You cannot have SUBPLOTs in an AXES object. It is not possible, AXES objects are never children of other AXES objects. Try this. Run this code with your figure open:

AX = findall(0,'type','axes');
set(AX,'units','pixels');
G = get(AX,'position');
G = cat(1,G{:})

And show us what is printed out on the screen.

Rossella

unread,
Jan 27, 2011, 12:30:24 PM1/27/11
to
This is the result:
AX =
242.0012
195.0012
30.0013 --> this is the 1st subplot
27.0013 --> this is the 3rd subplot (bottom left)
17.0015 --> this is 2nd subplot (bottom right)
228.0012 --> this is another axes in another area of the GUI
220.0012 --> this is another axes in another area of the GUI
G =
1.0e+03 *
0.6800 0.0040 0.3000 0.0910
1.0000 0.0050 0.2800 0.0900
0.0791 0.1408 0.4658 0.5272
0.0010 -0.0307 0.2896 0.1638
0.3438 -0.0163 0.2494 0.1410
0.0160 0.0100 0.0210 0.1440
0.0120 0.0120 0.0210 0.1440

I couldn't figure out what the first 2 axes (242.0012 and 195.0012) are: looking and the handles structure I couldn't find any field with that values. Also, the handle of the original axes created in the GUI (handles.axes_MainPlot = 17.0013) is not present in the axes list (that makes sense because I have "overwritten" it with the subplots).

This is how I did the subplots (maybe this will help understanding if I'm doing something wrong):
1) In the GUI (using GUIDE) I create a panel containing an axes that represents the area where later I will plot the three images (the three subplots). The tag of this axes is handles.axes_MainPlot.
2) In the opening function of the GUI I populate the axes with three subplots:
axes(handles.axes_MainPlot) % make handles.axes_MainPlot current axes
handles.IITPlot = subplot(4,2,8); % bottom left
p = get(handles.IITPlot, 'pos'); % [left, bottom, width, height]
p(2) = -0.024; p(3) = p(3)*1.24; p(4) = p(4)*1.24;
set(handles.IITPlot, 'pos', p);
imagesc(IITlogo);
axis image
axis off
handles.CPDPlot = subplot(4,2,7);
pc = get(handles.CPDPlot, 'pos'); % [left, bottom, width, height]
pc(1) = 0; pc(2) = -0.044; pc(3) = pc(3)*1.44; pc(4) = pc(4)*1.44;
set(handles.CPDPlot, 'pos', pc);
imagesc(CPDlogo);
axis image
axis off
handles.MainPlot = subplot(10,2,[1 18]);
axis off
% At this point the three subplots have taken the place of the original axes (handles.axes_MainPlot)
3) Later, based on the user selections in the GUI, I'll plot several images in handles.MainPlot (the central subplot) and I need to save the three subplots together into one image.

At the beginning I had created three different axes in the GUI, but then I didn't know how to save the three together into one image. That's why I thought that using subplot might have solved the issue.
If I plot the three subplots in a "normal" figure (not in a GUI) it works fine because I can pass the handle of the figure itself to save the entire image, but in the GUI the handle of the figure is the entire GUI fig and the handle of the axes where the subplots have been plotted doesn't exist anymore.

Maybe subplotting is not the right way to solve my issue (saving more subplots/plots into one image). Do you have any suggestion on how I might do it?

Thank you very much for your help.
Rossella

"Matt Fig" wrote in message <ihqk06$69l$1...@fred.mathworks.com>...

Matt Fig

unread,
Jan 27, 2011, 9:08:03 PM1/27/11
to
I think I see your problem now. You have made the subplots children of a UIPANEL. Thus when you call GETFRAME with the figure handle as the first argument and the rectangle second argument, you have to remember that the rectangle should be calculated from the lower left corner of the figure. In order to get the proper rectangle, I would convert the units of both the UIPANEL and AXES to pixels, then add to the starting position of the rectangle the position of the UIPANEL.

Rossella

unread,
Jan 27, 2011, 10:48:03 PM1/27/11
to
Hi Matt,

thanks so much! You solved my issue!
The problem was that I was trying to pass one handle containing the three subplots, but this handle actually doesn't exist or is not a figure or axes handles (and thus I got the error from getframe). So now I pass the handle of the entire GUI figure with the rectangle of the area of the panel containing the plots I want to save all together.
Just in case it might be useful for someone else in the future, here's the code:

% get the position of the panel containing the subplots I want to save together
rect_pos = get(handles.uipanel_axes,'position');
f = getframe(handles.MyGUI, rect_pos); %Capture screen shot area defined by rect_pos
[im,map] = frame2im(f);
imwrite(im,'MyImage.jpg');

Thanks again to both of you for your great help.
Rossella

"Matt Fig" wrote in message <iht8e3$mqk$1...@fred.mathworks.com>...

Oliver Woodford

unread,
Feb 2, 2011, 10:47:04 AM2/2/11
to

The function export_fig (on the file exchange) can now take a list of axes handles as input, and save only those axes. This could be useful to you, Rosella, if you want to save those subplots at a higher resolution, and/or anti-aliased.
Oliver

Rossella

unread,
Feb 2, 2011, 12:14:05 PM2/2/11
to
Hi Oliver,
thanks! That's great!
Though, I guess I'm doing something wrong because it didn't work. That's the command I'm using:

export_fig([handles.MainPlot handles.IITPlot handles.CPDPlot], 'FileName.jpg');

The result is a tiny white pixel. The same occurs if I try to save only one of the subplots.
I also got several warnings (six, but they are all the same):
Warning: Callback for uicontrol of style radiobutton will be overwritten when added to a UIBUTTONGROUP.
Use the SelectionChangeFcn property on the button group instead.
> In uitools.uibuttongroup.childAddedCbk at 12
In isolate_axes>copyfig at 94
In isolate_axes at 45
In export_fig at 160
In NearRepeatGUI>pushbutton_OkNearRepeat_Callback at 1061
In gui_mainfcn at 96
In NearRepeatGUI at 45
In @(hObject,eventdata)NearRepeatGUI('pushbutton_OkNearRepeat_Callback',hObject,eventdata,guidata(hObject))

Any hint on what I'm doing wrong?
Thanks in advance for your help.
Rossella

"Oliver Woodford" wrote in message <iibu9o$gio$1...@fred.mathworks.com>...

Oliver Woodford

unread,
Feb 2, 2011, 12:52:03 PM2/2/11
to
"Rossella" wrote:
> Hi Oliver,
> thanks! That's great!
> Though, I guess I'm doing something wrong because it didn't work. That's the command I'm using:
>
> export_fig([handles.MainPlot handles.IITPlot handles.CPDPlot], 'FileName.jpg');
>
> The result is a tiny white pixel. The same occurs if I try to save only one of the subplots.
> I also got several warnings (six, but they are all the same):
> Warning: Callback for uicontrol of style radiobutton will be overwritten when added to a UIBUTTONGROUP.
> Use the SelectionChangeFcn property on the button group instead.
> > In uitools.uibuttongroup.childAddedCbk at 12
> In isolate_axes>copyfig at 94
> In isolate_axes at 45
> In export_fig at 160
> In NearRepeatGUI>pushbutton_OkNearRepeat_Callback at 1061
> In gui_mainfcn at 96
> In NearRepeatGUI at 45
> In @(hObject,eventdata)NearRepeatGUI('pushbutton_OkNearRepeat_Callback',hObject,eventdata,guidata(hObject))
>
> Any hint on what I'm doing wrong?
> Thanks in advance for your help.
> Rossella

Rossella

If you email me a script (and data) to recreate the problem, then I'll take a look.

The following should definitely work:

figure; for a = 1:4, h(a) = subplot(2, 2, a); peaks; if (a == 1 || a == 4) colorbar; end; end
export_fig(h([1 4]), 'test.png');

Let me know if not.
Regards,
Oliver

Eric

unread,
Feb 8, 2011, 7:53:03 PM2/8/11
to
"Rossella" wrote in message <ihte9j$abh$1...@fred.mathworks.com>...

> Hi Matt,
>
> thanks so much! You solved my issue!
> The problem was that I was trying to pass one handle containing the three subplots, but this handle actually doesn't exist or is not a figure or axes handles (and thus I got the error from getframe). So now I pass the handle of the entire GUI figure with the rectangle of the area of the panel containing the plots I want to save all together.
> Just in case it might be useful for someone else in the future, here's the code:
>
> % get the position of the panel containing the subplots I want to save together
> rect_pos = get(handles.uipanel_axes,'position');
> f = getframe(handles.MyGUI, rect_pos); %Capture screen shot area defined by rect_pos
> [im,map] = frame2im(f);
> imwrite(im,'MyImage.jpg');
>
> Thanks again to both of you for your great help.
> Rossella

Rossella,

Thank you so much for posting your solution! It saved my day. However I should note that in my case, when the 'Units' property is set to default (normalized) for a panel within a GUI you have to first set the Units to pixels before the get Position statement and set them back to normalized after the get Position statement for your solution to work and integrate happily into the rest of the code. I'm sure there's got to be a workaround to just use the Units in normalized form, but I couldn't work it out.

If anyone out there knows how, please do tell.

~Eric

0 new messages