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.
7 % EXPORTFIG(...,PARAM1,VAL1,PARAM2,VAL2,...) specifies
8 % parameters that control various characteristics of the output
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.
19 % 'Preview' one of the strings 'none', 'tiff'
20 % specifies a preview for EPS files. Defaults to 'none'.
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
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.
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.
46 % The default color setting is 'bw'.
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
55 % 'FontEncoding' one of the strings 'latin1', 'adobe'
56 % specifies the character encoding of the font
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.
65 % The default 'FontMode' setting is 'scaled'.
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
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
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.
93 error('Too few input arguments');
96 % exportfig(H, filename, ...)
98 if ~ishandle(H) | ~strcmp(
get(H,
'type'),
'figure')
99 error('First argument must be a handle to a figure.');
101 filename = varargin{2};
103 error('Second argument must be a
string.');
105 paramPairs = varargin(3:end);
107 % Do some validity checking on param-value pairs
108 if (rem(length(paramPairs),2) ~= 0)
109 error(['Invalid input syntax. Optional parameters and values' ...
110 ' must be in pairs.']);
122 fontencoding = 'latin1';
126 % Process param-value pairs
128 for k = 1:2:length(paramPairs)
129 param = lower(paramPairs{k});
131 error(
'Optional parameter names must be strings');
133 value = paramPairs{k+1};
138 if (~strcmp(format,{
'eps',
'eps2',
'jpeg',
'png',
'preview'}))
139 error([
'Format must be ''eps'', ''eps2'', ''jpeg'', ''png'' or' ...
144 if (~strcmp(preview,{
'none',
'tiff'}))
145 error(
'Preview must be ''none'' or ''tiff''.');
148 width = LocalToNum(value);
149 if(~LocalIsPositiveScalar(width))
150 error(
'Width must be a numeric scalar > 0');
153 height = LocalToNum(value);
154 if(~LocalIsPositiveScalar(height))
155 error(
'Height must be a numeric scalar > 0');
158 color = lower(value);
159 if (~strcmp(color,{
'bw',
'gray',
'cmyk'}))
160 error(
'Color must be ''bw'', ''gray'' or ''cmyk''.');
163 fontmode = lower(value);
164 if (~strcmp(fontmode,{
'scaled',
'fixed'}))
165 error(
'FontMode must be ''scaled'' or ''fixed''.');
168 fontsize = LocalToNum(value);
169 if(~LocalIsPositiveScalar(fontsize))
170 error(
'FontSize must be a numeric scalar > 0');
173 fontencoding = lower(value);
174 if (~strcmp(fontencoding,{
'latin1',
'adobe'}))
175 error(
'FontEncoding must be ''latin1'' or ''adobe''.');
178 linemode = lower(value);
179 if (~strcmp(linemode,{
'scaled',
'fixed'}))
180 error(
'LineMode must be ''scaled'' or ''fixed''.');
183 linewidth = LocalToNum(value);
184 if(~LocalIsPositiveScalar(linewidth))
185 error(
'LineWidth must be a numeric scalar > 0');
188 renderer = lower(value);
189 if (~strcmp(renderer,{
'painters',
'zbuffer',
'opengl'}))
190 error(
'Renderer must be ''painters'', ''zbuffer'' or ''opengl''.');
193 resolution = LocalToNum(value);
194 if ~(isnumeric(value) & (prod(size(value)) == 1) & (value >= 0));
195 error(
'Resolution must be a numeric scalar >= 0');
198 error([
'Unrecognized option ' param
'.']);
202 allLines = findall(H,
'type',
'line');
203 allText = findall(H,
'type',
'text');
204 allAxes = findall(H,
'type',
'axes');
205 allImages = findall(H,
'type',
'image');
206 allLights = findall(H,
'type',
'light');
207 allPatch = findall(H,
'type',
'patch');
208 allSurf = findall(H,
'type',
'surface');
209 allRect = findall(H,
'type',
'rectangle');
210 allFont = [allText; allAxes];
211 allColor = [allLines; allText; allAxes; allLights];
212 allMarker = [allLines; allPatch; allSurf];
213 allEdge = [allPatch; allSurf];
214 allCData = [allImages; allPatch; allSurf];
220 % Process format and preview parameter
221 showPreview = strcmp(format,
'preview');
224 filename = [tempName
'.png'];
226 if strncmp(format,
'eps',3) & ~strcmp(preview,
'none')
227 args = {args{:}, [
'-' preview]};
232 % Process size parameters
233 paperPos =
get(H,
'PaperPosition');
234 old = LocalPushOldData(old, H,
'PaperPosition', paperPos);
235 figureUnits =
get(H,
'Units');
236 set(H,
'Units',
get(H,
'PaperUnits'));
237 figurePos =
get(H,
'Position');
238 aspectRatio = figurePos(3)/figurePos(4);
239 set(H,
'Units', figureUnits);
240 if (width == -1) & (height == -1)
242 height = paperPos(4);
244 width = height * aspectRatio;
245 elseif (height == -1)
246 height = width / aspectRatio;
248 set(H, 'PaperPosition', [0 0 width height]);
249 paperPosMode = get(H, 'PaperPositionMode');
250 old = LocalPushOldData(old, H, 'PaperPositionMode', paperPosMode);
251 set(H, 'PaperPositionMode', 'manual');
253 % Process rendering parameters
256 if ~strcmp(color,
'bw') & strncmp(format,
'eps',3)
257 format = [format 'c'];
259 args = {args{:}, [
'-d' format]};
261 %compute and
set gray colormap
262 oldcmap =
get(H,
'Colormap');
263 newgrays = 0.30*oldcmap(:,1) + 0.59*oldcmap(:,2) + 0.11*oldcmap(:,3);
264 newcmap = [newgrays newgrays newgrays];
265 old = LocalPushOldData(old, H,
'Colormap', oldcmap);
266 set(H,
'Colormap', newcmap);
268 %compute and
set ColorSpec and CData properties
269 old = LocalUpdateColors(allColor,
'color', old);
270 old = LocalUpdateColors(allAxes,
'xcolor', old);
271 old = LocalUpdateColors(allAxes,
'ycolor', old);
272 old = LocalUpdateColors(allAxes,
'zcolor', old);
273 old = LocalUpdateColors(allMarker,
'MarkerEdgeColor', old);
274 old = LocalUpdateColors(allMarker,
'MarkerFaceColor', old);
275 old = LocalUpdateColors(allEdge,
'EdgeColor', old);
276 old = LocalUpdateColors(allEdge,
'FaceColor', old);
277 old = LocalUpdateColors(allCData,
'CData', old);
280 if strncmp(format,
'eps',3)
281 format = [format 'c'];
282 args = {args{:}, [
'-d' format],
'-cmyk'};
284 args = {args{:}, [
'-d' format]};
287 error(
'Invalid Color parameter');
289 if (~isempty(renderer))
290 args = {args{:}, [
'-' renderer]};
292 if (~isempty(resolution)) | ~strncmp(format,
'eps',3)
293 if isempty(resolution)
296 args = {args{:}, [
'-r' int2str(resolution)]};
299 % Process font parameters
300 if (~isempty(fontmode))
301 oldfonts = LocalGetAsCell(allFont,
'FontSize');
304 oldfontunits = LocalGetAsCell(allFont,
'FontUnits');
305 old = LocalPushOldData(old, allFont, {
'FontUnits'}, oldfontunits);
306 set(allFont,
'FontUnits',
'points');
308 set(allFont,
'FontSize',7);
310 set(allFont,
'FontSize',fontsize);
314 wscale = width/figurePos(3);
315 hscale = height/figurePos(4);
316 scale = min(wscale, hscale);
320 newfonts = LocalScale(oldfonts,scale,5);
321 set(allFont,{
'FontSize'},newfonts);
323 error(
'Invalid FontMode parameter');
325 % make sure we push the size after the units
326 old = LocalPushOldData(old, allFont, {
'FontSize'}, oldfonts);
328 if strcmp(fontencoding,
'adobe') & strncmp(format,
'eps',3)
329 args = {args{:},
'-adobecset'};
332 % Process linewidth parameters
333 if (~isempty(linemode))
334 oldlines = LocalGetAsCell(allMarker,
'LineWidth');
335 old = LocalPushOldData(old, allMarker, {
'LineWidth'}, oldlines);
339 set(allMarker,
'LineWidth',1);
341 set(allMarker,
'LineWidth',linewidth);
345 wscale = width/figurePos(3);
346 hscale = height/figurePos(4);
347 scale = min(wscale, hscale);
351 newlines = LocalScale(oldlines, scale, 0.5);
352 set(allMarker,{
'LineWidth'},newlines);
354 error(
'Invalid LineMode parameter');
359 print(H, filename, args{:});
360 fixPSlinestyle(filename);
365 % Restore figure settings
366 for n=1:length(old.objs)
367 set(old.objs{n}, old.prop{n}, old.values{n});
371 error(deblank(lasterr));
374 % Show preview
if requested
376 X = imread(filename,
'png');
378 f = figure(
'Name',
'Preview', ...
379 'Menubar',
'none', ...
380 'NumberTitle',
'off', ...
384 ax = findobj(f,
'type',
'axes');
385 set(ax,
'Units',
get(H,
'PaperUnits'), ...
386 'Position', [0 0 width height], ...
388 set(ax,
'Units',
'pixels');
389 axesPos =
get(ax,
'Position');
390 figPos =
get(f,
'Position');
391 rootSize =
get(0,
'ScreenSize');
392 figPos(3:4) = axesPos(3:4);
393 if figPos(1) + figPos(3) > rootSize(3)
394 figPos(1) = rootSize(3) - figPos(3) - 50;
396 if figPos(2) + figPos(4) > rootSize(4)
397 figPos(2) = rootSize(4) - figPos(4) - 50;
399 set(f, 'Position',figPos, ...
407 function outData = LocalPushOldData(inData, objs, prop, values)
408 outData.objs = {inData.objs{:}, objs};
409 outData.prop = {inData.prop{:}, prop};
410 outData.values = {inData.values{:}, values};
412 function cellArray = LocalGetAsCell(fig,prop);
413 cellArray =
get(fig,prop);
414 if (~isempty(cellArray)) & (~iscell(cellArray))
415 cellArray = {cellArray};
418 function newArray = LocalScale(inArray, scale, minValue)
420 newArray = cell(n,1);
422 newArray{k} = max(minValue,scale*inArray{k}(1));
425 function newArray = LocalMapToGray(inArray);
427 newArray = cell(n,1);
454 color = 0.30*color(1) + 0.59*color(2) + 0.11*color(3);
457 if isempty(color) | ischar(color)
460 newArray{k} = [color color color];
464 function newArray = LocalMapCData(inArray);
466 newArray = cell(n,1);
469 if (ndims(color) == 3) & isa(color,
'double')
470 gray = 0.30*color(:,:,1) + 0.59*color(:,:,2) + 0.11*color(:,:,3);
478 function outData = LocalUpdateColors(inArray, prop, inData)
479 value = LocalGetAsCell(inArray,prop);
480 outData.objs = {inData.objs{:}, inArray};
481 outData.prop = {inData.prop{:}, {prop}};
482 outData.values = {inData.values{:}, value};
484 if strcmp(prop,
'CData')
485 value = LocalMapCData(value);
487 value = LocalMapToGray(value);
489 set(inArray,{prop},value);
492 function bool = LocalIsPositiveScalar(value)
493 bool = isnumeric(value) & ...
494 prod(size(value)) == 1 & ...
497 function value = LocalToNum(value)
499 value = str2num(value);