在做gui界面的时候遇到一个这样的问题:我fig里有2个axes,一个用于显示原始图像,一个用来显示每个步骤处理结果。想通过一个菜单或者按键来实现保存处理结果的功能,也就是说只要用户点击保存的时候。系统会读取axes2里的图像数据,然后写成文件。因为保存路径和文件名可供用户选择,所以很自然想到uiputfile和saveas(看过很多人写的程序都是这样的)。由于保存程序和处理程序不在一个callback里所以牵扯到数据的传递问题,此问题困扰我好久了,今天总算给解决了。拿来分享一下,同时又发现了新问题,高手们来帮忙哈。
因为在多个axes情况下,显示不同的图像实现的代码记得是eight兄给的:
axes(handles.axes1);
这以后的绘图或者显示函数都是针对axes1的
axes(handles.axes2);
这以后的绘图或者显示函数都是针对axes2的
.......................................
更多的一次类推.....
那么如果向保存axes2的图像该怎么实现呢?受上边的启发我用了下边的代码:
[sFileName sFilePath]=uiputfile({'*.jpg','JPEG-Files (*.jpg)'; ...
'*.*','All Files (*.*)'},'保存图像文件','untitled.jpg');
if ~isequal([sFileName,sFilePath],[0,0])
sFileFullName=[sFilePath sFileName];
axes(handles.axes2);
saveas(gca,sFileFullName,'jpg');
else
msgbox('你按了取消键!','保存失败');
end
程序运行正常,可惜结果不对。保存的图像是整个fig的左下角的一部分,而不是axes2里显示的图像。
猜测可能是数据传递有问题,结果把我搜集的参数传递方式试了一个遍:
handles.Timg=imshow(J);%某论坛一个版主给的方法
handles.Timg=J;%常用的保存方法
事实证明这2种方法传递的句柄保存的结果都不太正常,而且和我上边使用的方法结果完全相同!
无奈之下,想到高手常用的另一种传递方法setappdata和getappdata
setappdata(gcf,'Timg',J);
保存里callback里:
data=getappdata(gcf,'Timg');
saveas(Timg,sFileFullName,'jpg');
结果程序出错:
??? Error using ==> saveas
Invalid handle.
Error in ==> preprocess>saveas_Callback at 206
saveas(data,sFileFullName,'jpg');
Error in ==> gui_mainfcn at 75
feval(varargin{:});
Error in ==> preprocess at 42
gui_mainfcn(gui_State, varargin{:});
??? Error while evaluating uimenu Callback.
无效的句柄,查看saveas的help文档,发现saveas保存的都是句柄对象。getappdata获得是图像数据,原来是因为saveas不支持保存图像数据,所以想到了imwrite
data=getappdata(gcf,'Timg');
imwrite(gca,sFileFullName,'jpg');
嘿嘿程序完全正常了,经常见到uiputfile和saveas一起用。和imwrite一起用的倒是没见过,可能是我见识太少了。后来发现当使用imwrite保存的时候,在处理的callback里可以用handles.Timg=J替换 setappdata(gcf,'Timg',J);
虽然达到了保存的目的但是,问题仍在:如何用saveas得到正确的结果?3种不同的句柄出传递方法得到相同不正确的结果,说明问题不在句柄保存本身上,那么到底是在哪儿呢?还往高手们多讨论一下,把多axes的图像的可选路径保存问题弄个一目了然!
附图是用imwrite和saveas的保存结果,以后整个figure的图像。
下面的小程序是用来测试imwrite和saveas保存图像的区别:
==================================================================================
I=imread('lena.bmp');
data=imadjust(I);
imshow(data);
pause;
%%下面是只有单个绘图窗口的情形
[sFileName sFilePath]=uiputfile({'*.jpg','JPEG-Files (*.jpg)'; ...
'*.*','All Files (*.*)'},'保存图像文件','untitled.jpg');
if ~isequal([sFileName,sFilePath],[0,0])
sFileFullName=[sFilePath sFileName];
imwrite(data,sFileFullName,'jpg');
end
pause;
[sFileName sFilePath]=uiputfile({'*.jpg','JPEG-Files (*.jpg)'; ...
'*.*','All Files (*.*)'},'保存图像文件','untitled.jpg');
if ~isequal([sFileName,sFilePath],[0,0])
sFileFullName=[sFilePath sFileName];
saveas(gca,sFileFullName,'jpg');
end
pause;
%下面是多个绘图窗口的情形(以2个为例)
subplot(121),Ta=imshow(data);title('原图')
[counts,x] = imhist(data);
subplot(122),Tb=plot(x,counts);title('直方图')
saveas(Tb,'直方图.jpg');
%这里的保存结果是整个fig,需要的是子图2里的直方图。
==================================================================================
直观上看有2点不同
(1)saveas保存的图像是整个fig,图像以外的部分全部用白像素代替了。
(2)图像的大小不一样:
saveas: 1201*900*24b jpeg 72.3k
imwrite:256*256*256 jpeg 12.6k
(我的lena.bmp是重新在网上下载的,系统里的没了。所以具体的数据会有差别,在此只是为了说明2者保存同种类型图像时的区别)
最后归纳一下待解决的问题:
(1)如何在gui里用saveas正确的保存不同axes里的图像?
(2)在多窗口绘图里(使用subplot的情形),如果正确保存子图里的图像?
screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='点击在新窗口查看全图/nCTRL+鼠标滚轮
放大或缩小';}" border=0>