PageRenderTime 27ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/image_analysisII/bookcode/visionbook/matlab_code/misc/exportfig.m

http://uppsala-university.googlecode.com/
MATLAB | 501 lines | 364 code | 31 blank | 106 comment | 75 complexity | 7c3c7564192a685c38d603ee06a84829 MD5 | raw file
Possible License(s): BSD-2-Clause
  1. function exportfig(varargin)
  2. %EXPORTFIG Export a figure to Encapsulated Postscript.
  3. % EXPORTFIG(H, FILENAME) writes the figure H to FILENAME. H is
  4. % a figure handle and FILENAME is a string that specifies the
  5. % name of the output file.
  6. %
  7. % EXPORTFIG(...,PARAM1,VAL1,PARAM2,VAL2,...) specifies
  8. % parameters that control various characteristics of the output
  9. % file.
  10. %
  11. % Format Paramter:
  12. % 'Format' one of the strings 'eps','eps2','jpeg','png','preview'
  13. % specifies the output format. Defaults to 'eps'.
  14. % The output format 'preview' does not generate an output
  15. % file but instead creates a new figure window with a
  16. % preview of the exported figure. In this case the
  17. % FILENAME parameter is ignored.
  18. %
  19. % 'Preview' one of the strings 'none', 'tiff'
  20. % specifies a preview for EPS files. Defaults to 'none'.
  21. %
  22. % Size Parameters:
  23. % 'Width' a positive scalar
  24. % specifies the width in the figure's PaperUnits
  25. % 'Height' a positive scalar
  26. % specifies the height in the figure's PaperUnits
  27. %
  28. % Specifying only one dimension sets the other dimension
  29. % so that the exported aspect ratio is the same as the
  30. % figure's current aspect ratio.
  31. % If neither dimension is specified the size defaults to
  32. % the width and height from the figure's PaperPosition.
  33. %
  34. % Rendering Parameters:
  35. % 'Color' one of the strings 'bw', 'gray', 'cmyk'
  36. % 'bw' specifies that lines and text are exported in
  37. % black and all other objects in grayscale
  38. % 'gray' specifies that all objects are exported in grayscale
  39. % 'cmyk' specifies that all objects are exported in color
  40. % using the CMYK color space
  41. % 'Renderer' one of the strings 'painters', 'zbuffer', 'opengl'
  42. % specifies the renderer to use
  43. % 'Resolution' a positive scalar
  44. % specifies the resolution in dots-per-inch.
  45. %
  46. % The default color setting is 'bw'.
  47. %
  48. % Font Parameters:
  49. % 'FontMode' one of the strings 'scaled', 'fixed'
  50. % 'FontSize' a positive scalar
  51. % in 'scaled' mode multiplies with the font size of each
  52. % text object to obtain the exported font size
  53. % in 'fixed' mode specifies the font size of all text
  54. % objects in points
  55. % 'FontEncoding' one of the strings 'latin1', 'adobe'
  56. % specifies the character encoding of the font
  57. %
  58. % If FontMode is 'scaled' but FontSize is not specified then a
  59. % scaling factor is computed from the ratio of the size of the
  60. % exported figure to the size of the actual figure. The minimum
  61. % font size allowed after scaling is 5 points.
  62. % If FontMode is 'fixed' but FontSize is not specified then the
  63. % exported font sizes of all text objects is 7 points.
  64. %
  65. % The default 'FontMode' setting is 'scaled'.
  66. %
  67. % Line Width Parameters:
  68. % 'LineMode' one of the strings 'scaled', 'fixed'
  69. % 'LineWidth' a positive scalar
  70. % the semantics of LineMode and LineWidth are exactly the
  71. % same as FontMode and FontSize, except that they apply
  72. % to line widths instead of font sizes. The minumum line
  73. % width allowed after scaling is 0.5 points.
  74. % If LineMode is 'fixed' but LineWidth is not specified
  75. % then the exported line width of all line objects is 1
  76. % point.
  77. %
  78. % Examples:
  79. % exportfig(gcf,'fig1.eps','height',3);
  80. % Exports the current figure to the file named 'fig1.eps' with
  81. % a height of 3 inches (assuming the figure's PaperUnits is
  82. % inches) and an aspect ratio the same as the figure's aspect
  83. % ratio on screen.
  84. %
  85. % exportfig(gcf, 'fig2.eps', 'FontMode', 'fixed',...
  86. % 'FontSize', 10, 'color', 'cmyk' );
  87. % Exports the current figure to 'fig2.eps' in color with all
  88. % text in 10 point fonts. The size of the exported figure is
  89. % the figure's PaperPostion width and height.
  90. if (nargin < 2)
  91. error('Too few input arguments');
  92. end
  93. % exportfig(H, filename, ...)
  94. H = varargin{1};
  95. if ~ishandle(H) | ~strcmp(get(H,'type'), 'figure')
  96. error('First argument must be a handle to a figure.');
  97. end
  98. filename = varargin{2};
  99. if ~ischar(filename)
  100. error('Second argument must be a string.');
  101. end
  102. paramPairs = varargin(3:end);
  103. % Do some validity checking on param-value pairs
  104. if (rem(length(paramPairs),2) ~= 0)
  105. error(['Invalid input syntax. Optional parameters and values' ...
  106. ' must be in pairs.']);
  107. end
  108. format = 'eps';
  109. preview = 'none';
  110. width = -1;
  111. height = -1;
  112. %color = 'bw';
  113. color = 'cmyk';
  114. fontsize = -1;
  115. fontmode='scaled';
  116. linewidth = -1;
  117. linemode=[];
  118. fontencoding = 'latin1';
  119. renderer = [];
  120. resolution = [];
  121. % Process param-value pairs
  122. args = {};
  123. for k = 1:2:length(paramPairs)
  124. param = lower(paramPairs{k});
  125. if (~ischar(param))
  126. error('Optional parameter names must be strings');
  127. end
  128. value = paramPairs{k+1};
  129. switch (param)
  130. case 'format'
  131. format = value;
  132. if (~strcmp(format,{'eps','eps2','jpeg','png','preview'}))
  133. error(['Format must be ''eps'', ''eps2'', ''jpeg'', ''png'' or' ...
  134. ' ''preview''.']);
  135. end
  136. case 'preview'
  137. preview = value;
  138. if (~strcmp(preview,{'none','tiff'}))
  139. error('Preview must be ''none'' or ''tiff''.');
  140. end
  141. case 'width'
  142. width = LocalToNum(value);
  143. if(~LocalIsPositiveScalar(width))
  144. error('Width must be a numeric scalar > 0');
  145. end
  146. case 'height'
  147. height = LocalToNum(value);
  148. if(~LocalIsPositiveScalar(height))
  149. error('Height must be a numeric scalar > 0');
  150. end
  151. case 'color'
  152. color = lower(value);
  153. if (~strcmp(color,{'bw','gray','cmyk'}))
  154. error('Color must be ''bw'', ''gray'' or ''cmyk''.');
  155. end
  156. case 'fontmode'
  157. fontmode = lower(value);
  158. if (~strcmp(fontmode,{'scaled','fixed'}))
  159. error('FontMode must be ''scaled'' or ''fixed''.');
  160. end
  161. case 'fontsize'
  162. fontsize = LocalToNum(value);
  163. if(~LocalIsPositiveScalar(fontsize))
  164. error('FontSize must be a numeric scalar > 0');
  165. end
  166. case 'fontencoding'
  167. fontencoding = lower(value);
  168. if (~strcmp(fontencoding,{'latin1','adobe'}))
  169. error('FontEncoding must be ''latin1'' or ''adobe''.');
  170. end
  171. case 'linemode'
  172. linemode = lower(value);
  173. if (~strcmp(linemode,{'scaled','fixed'}))
  174. error('LineMode must be ''scaled'' or ''fixed''.');
  175. end
  176. case 'linewidth'
  177. linewidth = LocalToNum(value);
  178. if(~LocalIsPositiveScalar(linewidth))
  179. error('LineWidth must be a numeric scalar > 0');
  180. end
  181. case 'renderer'
  182. renderer = lower(value);
  183. if (~strcmp(renderer,{'painters','zbuffer','opengl'}))
  184. error('Renderer must be ''painters'', ''zbuffer'' or ''opengl''.');
  185. end
  186. case 'resolution'
  187. resolution = LocalToNum(value);
  188. if ~(isnumeric(value) & (prod(size(value)) == 1) & (value >= 0));
  189. error('Resolution must be a numeric scalar >= 0');
  190. end
  191. otherwise
  192. error(['Unrecognized option ' param '.']);
  193. end
  194. end
  195. allLines = findall(H, 'type', 'line');
  196. allText = findall(H, 'type', 'text');
  197. allAxes = findall(H, 'type', 'axes');
  198. allImages = findall(H, 'type', 'image');
  199. allLights = findall(H, 'type', 'light');
  200. allPatch = findall(H, 'type', 'patch');
  201. allSurf = findall(H, 'type', 'surface');
  202. allRect = findall(H, 'type', 'rectangle');
  203. allFont = [allText; allAxes];
  204. allColor = [allLines; allText; allAxes; allLights];
  205. allMarker = [allLines; allPatch; allSurf];
  206. allEdge = [allPatch; allSurf];
  207. allCData = [allImages; allPatch; allSurf];
  208. old.objs = {};
  209. old.prop = {};
  210. old.values = {};
  211. % Process format and preview parameter
  212. showPreview = strcmp(format,'preview');
  213. if showPreview
  214. format = 'png';
  215. filename = [tempName '.png'];
  216. end
  217. if strncmp(format,'eps',3) & ~strcmp(preview,'none')
  218. args = {args{:}, ['-' preview]};
  219. end
  220. hadError = 0;
  221. try
  222. % Process size parameters
  223. paperPos = get(H, 'PaperPosition');
  224. old = LocalPushOldData(old, H, 'PaperPosition', paperPos);
  225. figureUnits = get(H, 'Units');
  226. set(H, 'Units', get(H,'PaperUnits'));
  227. figurePos = get(H, 'Position');
  228. aspectRatio = figurePos(3)/figurePos(4);
  229. set(H, 'Units', figureUnits);
  230. if (width == -1) & (height == -1)
  231. width = paperPos(3);
  232. height = paperPos(4);
  233. elseif (width == -1)
  234. width = height * aspectRatio;
  235. elseif (height == -1)
  236. height = width / aspectRatio;
  237. end
  238. set(H, 'PaperPosition', [0 0 width height]);
  239. paperPosMode = get(H, 'PaperPositionMode');
  240. old = LocalPushOldData(old, H, 'PaperPositionMode', paperPosMode);
  241. set(H, 'PaperPositionMode', 'manual');
  242. % Process rendering parameters
  243. switch (color)
  244. case {'bw', 'gray'}
  245. if ~strcmp(color,'bw') & strncmp(format,'eps',3)
  246. format = [format 'c'];
  247. end
  248. args = {args{:}, ['-d' format]};
  249. %compute and set gray colormap
  250. oldcmap = get(H,'Colormap');
  251. newgrays = 0.30*oldcmap(:,1) + 0.59*oldcmap(:,2) + 0.11*oldcmap(:,3);
  252. newcmap = [newgrays newgrays newgrays];
  253. old = LocalPushOldData(old, H, 'Colormap', oldcmap);
  254. set(H, 'Colormap', newcmap);
  255. %compute and set ColorSpec and CData properties
  256. old = LocalUpdateColors(allColor, 'color', old);
  257. old = LocalUpdateColors(allAxes, 'xcolor', old);
  258. old = LocalUpdateColors(allAxes, 'ycolor', old);
  259. old = LocalUpdateColors(allAxes, 'zcolor', old);
  260. old = LocalUpdateColors(allMarker, 'MarkerEdgeColor', old);
  261. old = LocalUpdateColors(allMarker, 'MarkerFaceColor', old);
  262. old = LocalUpdateColors(allEdge, 'EdgeColor', old);
  263. old = LocalUpdateColors(allEdge, 'FaceColor', old);
  264. old = LocalUpdateColors(allCData, 'CData', old);
  265. case 'cmyk'
  266. if strncmp(format,'eps',3)
  267. format = [format 'c'];
  268. args = {args{:}, ['-d' format], '-cmyk'};
  269. else
  270. args = {args{:}, ['-d' format]};
  271. end
  272. otherwise
  273. error('Invalid Color parameter');
  274. end
  275. if (~isempty(renderer))
  276. args = {args{:}, ['-' renderer]};
  277. end
  278. if (~isempty(resolution)) | ~strncmp(format,'eps',3)
  279. if isempty(resolution)
  280. resolution = 0;
  281. end
  282. args = {args{:}, ['-r' int2str(resolution)]};
  283. end
  284. % Process font parameters
  285. if (~isempty(fontmode))
  286. oldfonts = LocalGetAsCell(allFont,'FontSize');
  287. switch (fontmode)
  288. case 'fixed'
  289. oldfontunits = LocalGetAsCell(allFont,'FontUnits');
  290. old = LocalPushOldData(old, allFont, {'FontUnits'}, oldfontunits);
  291. set(allFont,'FontUnits','points');
  292. if (fontsize == -1)
  293. set(allFont,'FontSize',7);
  294. else
  295. set(allFont,'FontSize',fontsize);
  296. end
  297. case 'scaled'
  298. if (fontsize == -1)
  299. wscale = width/figurePos(3);
  300. hscale = height/figurePos(4);
  301. scale = min(wscale, hscale);
  302. else
  303. scale = fontsize;
  304. end
  305. newfonts = LocalScale(oldfonts,scale,5);
  306. set(allFont,{'FontSize'},newfonts);
  307. otherwise
  308. error('Invalid FontMode parameter');
  309. end
  310. % make sure we push the size after the units
  311. old = LocalPushOldData(old, allFont, {'FontSize'}, oldfonts);
  312. end
  313. if strcmp(fontencoding,'adobe') & strncmp(format,'eps',3)
  314. args = {args{:}, '-adobecset'};
  315. end
  316. % Process linewidth parameters
  317. if (~isempty(linemode))
  318. oldlines = LocalGetAsCell(allMarker,'LineWidth');
  319. old = LocalPushOldData(old, allMarker, {'LineWidth'}, oldlines);
  320. switch (linemode)
  321. case 'fixed'
  322. if (linewidth == -1)
  323. set(allMarker,'LineWidth',1);
  324. else
  325. set(allMarker,'LineWidth',linewidth);
  326. end
  327. case 'scaled'
  328. if (linewidth == -1)
  329. wscale = width/figurePos(3);
  330. hscale = height/figurePos(4);
  331. scale = min(wscale, hscale);
  332. else
  333. scale = linewidth;
  334. end
  335. newlines = LocalScale(oldlines, scale, 0.5);
  336. set(allMarker,{'LineWidth'},newlines);
  337. otherwise
  338. error('Invalid LineMode parameter');
  339. end
  340. end
  341. % Export
  342. print(H, filename, args{:});
  343. catch
  344. hadError = 1;
  345. end
  346. % Restore figure settings
  347. for n=1:length(old.objs)
  348. set(old.objs{n}, old.prop{n}, old.values{n});
  349. end
  350. if hadError
  351. error(deblank(lasterr));
  352. end
  353. % Show preview if requested
  354. if showPreview
  355. X = imread(filename,'png');
  356. delete(filename);
  357. f = figure( 'Name', 'Preview', ...
  358. 'Menubar', 'none', ...
  359. 'NumberTitle', 'off', ...
  360. 'Visible', 'off');
  361. image(X);
  362. axis image;
  363. ax = findobj(f, 'type', 'axes');
  364. set(ax, 'Units', get(H,'PaperUnits'), ...
  365. 'Position', [0 0 width height], ...
  366. 'Visible', 'off');
  367. set(ax, 'Units', 'pixels');
  368. axesPos = get(ax,'Position');
  369. figPos = get(f,'Position');
  370. rootSize = get(0,'ScreenSize');
  371. figPos(3:4) = axesPos(3:4);
  372. if figPos(1) + figPos(3) > rootSize(3)
  373. figPos(1) = rootSize(3) - figPos(3) - 50;
  374. end
  375. if figPos(2) + figPos(4) > rootSize(4)
  376. figPos(2) = rootSize(4) - figPos(4) - 50;
  377. end
  378. set(f, 'Position',figPos, ...
  379. 'Visible', 'on');
  380. end
  381. %
  382. % Local Functions
  383. %
  384. function outData = LocalPushOldData(inData, objs, prop, values)
  385. outData.objs = {inData.objs{:}, objs};
  386. outData.prop = {inData.prop{:}, prop};
  387. outData.values = {inData.values{:}, values};
  388. function cellArray = LocalGetAsCell(fig,prop);
  389. cellArray = get(fig,prop);
  390. if (~isempty(cellArray)) & (~iscell(cellArray))
  391. cellArray = {cellArray};
  392. end
  393. function newArray = LocalScale(inArray, scale, minValue)
  394. n = length(inArray);
  395. newArray = cell(n,1);
  396. for k=1:n
  397. newArray{k} = max(minValue,scale*inArray{k}(1));
  398. end
  399. function newArray = LocalMapToGray(inArray);
  400. n = length(inArray);
  401. newArray = cell(n,1);
  402. for k=1:n
  403. color = inArray{k};
  404. if (~isempty(color))
  405. if ischar(color)
  406. switch color(1)
  407. case 'y'
  408. color = [1 1 0];
  409. case 'm'
  410. color = [1 0 1];
  411. case 'c'
  412. color = [0 1 1];
  413. case 'r'
  414. color = [1 0 0];
  415. case 'g'
  416. color = [0 1 0];
  417. case 'b'
  418. color = [0 0 1];
  419. case 'w'
  420. color = [1 1 1];
  421. case 'k'
  422. color = [0 0 0];
  423. otherwise
  424. newArray{k} = color;
  425. end
  426. end
  427. if ~ischar(color)
  428. color = 0.30*color(1) + 0.59*color(2) + 0.11*color(3);
  429. end
  430. end
  431. if isempty(color) | ischar(color)
  432. newArray{k} = color;
  433. else
  434. newArray{k} = [color color color];
  435. end
  436. end
  437. function newArray = LocalMapCData(inArray);
  438. n = length(inArray);
  439. newArray = cell(n,1);
  440. for k=1:n
  441. color = inArray{k};
  442. if (ndims(color) == 3) & isa(color,'double')
  443. gray = 0.30*color(:,:,1) + 0.59*color(:,:,2) + 0.11*color(:,:,3);
  444. color(:,:,1) = gray;
  445. color(:,:,2) = gray;
  446. color(:,:,3) = gray;
  447. end
  448. newArray{k} = color;
  449. end
  450. function outData = LocalUpdateColors(inArray, prop, inData)
  451. value = LocalGetAsCell(inArray,prop);
  452. outData.objs = {inData.objs{:}, inArray};
  453. outData.prop = {inData.prop{:}, {prop}};
  454. outData.values = {inData.values{:}, value};
  455. if (~isempty(value))
  456. if strcmp(prop,'CData')
  457. value = LocalMapCData(value);
  458. else
  459. value = LocalMapToGray(value);
  460. end
  461. set(inArray,{prop},value);
  462. end
  463. function bool = LocalIsPositiveScalar(value)
  464. bool = isnumeric(value) & ...
  465. prod(size(value)) == 1 & ...
  466. value > 0;
  467. function value = LocalToNum(value)
  468. if ischar(value)
  469. value = str2num(value);
  470. end