source: issm/trunk-jpl/externalpackages/export_fig/export_fig.m@ 21671

Last change on this file since 21671 was 21671, checked in by Mathieu Morlighem, 8 years ago

CHG: updated export_fig

File size: 61.8 KB
Line 
1function [imageData, alpha] = export_fig(varargin)
2%EXPORT_FIG Exports figures in a publication-quality format
3%
4% Examples:
5% imageData = export_fig
6% [imageData, alpha] = export_fig
7% export_fig filename
8% export_fig filename -format1 -format2
9% export_fig ... -nocrop
10% export_fig ... -c[<val>,<val>,<val>,<val>]
11% export_fig ... -transparent
12% export_fig ... -native
13% export_fig ... -m<val>
14% export_fig ... -r<val>
15% export_fig ... -a<val>
16% export_fig ... -q<val>
17% export_fig ... -p<val>
18% export_fig ... -d<gs_option>
19% export_fig ... -depsc
20% export_fig ... -<renderer>
21% export_fig ... -<colorspace>
22% export_fig ... -append
23% export_fig ... -bookmark
24% export_fig ... -clipboard
25% export_fig ... -update
26% export_fig ... -nofontswap
27% export_fig ... -linecaps
28% export_fig(..., handle)
29%
30% This function saves a figure or single axes to one or more vector and/or
31% bitmap file formats, and/or outputs a rasterized version to the workspace,
32% with the following properties:
33% - Figure/axes reproduced as it appears on screen
34% - Cropped borders (optional)
35% - Embedded fonts (vector formats)
36% - Improved line and grid line styles
37% - Anti-aliased graphics (bitmap formats)
38% - Render images at native resolution (optional for bitmap formats)
39% - Transparent background supported (pdf, eps, png, tif)
40% - Semi-transparent patch objects supported (png & tif only)
41% - RGB, CMYK or grayscale output (CMYK only with pdf, eps, tiff)
42% - Variable image compression, including lossless (pdf, eps, jpg)
43% - Optionally append to file (pdf, tiff)
44% - Vector formats: pdf, eps
45% - Bitmap formats: png, tiff, jpg, bmp, export to workspace
46% - Rounded line-caps (optional; pdf & eps only)
47%
48% This function is especially suited to exporting figures for use in
49% publications and presentations, because of the high quality and
50% portability of media produced.
51%
52% Note that the background color and figure dimensions are reproduced
53% (the latter approximately, and ignoring cropping & magnification) in the
54% output file. For transparent background (and semi-transparent patch
55% objects), use the -transparent option or set the figure 'Color' property
56% to 'none'. To make axes transparent set the axes 'Color' property to
57% 'none'. PDF, EPS, TIF & PNG are the only formats that support a transparent
58% background; only TIF & PNG formats support transparency of patch objects.
59%
60% The choice of renderer (opengl, zbuffer or painters) has a large impact
61% on the quality of output. The default value (opengl for bitmaps, painters
62% for vector formats) generally gives good results, but if you aren't
63% satisfied then try another renderer. Notes: 1) For vector formats (EPS,
64% PDF), only painters generates vector graphics. 2) For bitmaps, only
65% opengl can render transparent patch objects correctly. 3) For bitmaps,
66% only painters will correctly scale line dash and dot lengths when
67% magnifying or anti-aliasing. 4) Fonts may be substitued with Courier when
68% using painters.
69%
70% When exporting to vector format (PDF & EPS) and bitmap format using the
71% painters renderer, this function requires that ghostscript is installed
72% on your system. You can download this from:
73% http://www.ghostscript.com
74% When exporting to eps it additionally requires pdftops, from the Xpdf
75% suite of functions. You can download this from:
76% http://www.foolabs.com/xpdf
77%
78% Inputs:
79% filename - string containing the name (optionally including full or
80% relative path) of the file the figure is to be saved as. If
81% a path is not specified, the figure is saved in the current
82% directory. If no name and no output arguments are specified,
83% the default name, 'export_fig_out', is used. If neither a
84% file extension nor a format are specified, a ".png" is added
85% and the figure saved in that format.
86% -format1, -format2, etc. - strings containing the extensions of the
87% file formats the figure is to be saved as.
88% Valid options are: '-pdf', '-eps', '-png',
89% '-tif', '-jpg' and '-bmp'. All combinations
90% of formats are valid.
91% -nocrop - option indicating that the borders of the output are not to
92% be cropped.
93% -c[<val>,<val>,<val>,<val>] - option indicating crop amounts. Must be
94% a 4-element vector of numeric values: [top,right,bottom,left]
95% where NaN/Inf indicate auto-cropping, 0 means no cropping,
96% and any other value mean cropping in pixel amounts.
97% -transparent - option indicating that the figure background is to be
98% made transparent (png, pdf, tif and eps output only).
99% -m<val> - option where val indicates the factor to magnify the
100% on-screen figure pixel dimensions by when generating bitmap
101% outputs (does not affect vector formats). Default: '-m1'.
102% -r<val> - option val indicates the resolution (in pixels per inch) to
103% export bitmap and vector outputs at, keeping the dimensions
104% of the on-screen figure. Default: '-r864' (for vector output
105% only). Note that the -m option overides the -r option for
106% bitmap outputs only.
107% -native - option indicating that the output resolution (when outputting
108% a bitmap format) should be such that the vertical resolution
109% of the first suitable image found in the figure is at the
110% native resolution of that image. To specify a particular
111% image to use, give it the tag 'export_fig_native'. Notes:
112% This overrides any value set with the -m and -r options. It
113% also assumes that the image is displayed front-to-parallel
114% with the screen. The output resolution is approximate and
115% should not be relied upon. Anti-aliasing can have adverse
116% effects on image quality (disable with the -a1 option).
117% -a1, -a2, -a3, -a4 - option indicating the amount of anti-aliasing to
118% use for bitmap outputs. '-a1' means no anti-
119% aliasing; '-a4' is the maximum amount (default).
120% -<renderer> - option to force a particular renderer (painters, opengl or
121% zbuffer). Default value: opengl for bitmap formats or
122% figures with patches and/or transparent annotations;
123% painters for vector formats without patches/transparencies.
124% -<colorspace> - option indicating which colorspace color figures should
125% be saved in: RGB (default), CMYK or gray. CMYK is only
126% supported in pdf, eps and tiff output.
127% -q<val> - option to vary bitmap image quality (in pdf, eps and jpg
128% files only). Larger val, in the range 0-100, gives higher
129% quality/lower compression. val > 100 gives lossless
130% compression. Default: '-q95' for jpg, ghostscript prepress
131% default for pdf & eps. Note: lossless compression can
132% sometimes give a smaller file size than the default lossy
133% compression, depending on the type of images.
134% -p<val> - option to pad a border of width val to exported files, where
135% val is either a relative size with respect to cropped image
136% size (i.e. p=0.01 adds a 1% border). For EPS & PDF formats,
137% val can also be integer in units of 1/72" points (abs(val)>1).
138% val can be positive (padding) or negative (extra cropping).
139% If used, the -nocrop flag will be ignored, i.e. the image will
140% always be cropped and then padded. Default: 0 (i.e. no padding).
141% -append - option indicating that if the file (pdfs only) already
142% exists, the figure is to be appended as a new page, instead
143% of being overwritten (default).
144% -bookmark - option to indicate that a bookmark with the name of the
145% figure is to be created in the output file (pdf only).
146% -clipboard - option to save output as an image on the system clipboard.
147% Note: background transparency is not preserved in clipboard
148% -d<gs_option> - option to indicate a ghostscript setting. For example,
149% -dMaxBitmap=0 or -dNoOutputFonts (Ghostscript 9.15+).
150% -depsc - option to use EPS level-3 rather than the default level-2 print
151% device. This solves some bugs with Matlab's default -depsc2 device
152% such as discolored subplot lines on images (vector formats only).
153% -update - option to download and install the latest version of export_fig
154% -nofontswap - option to avoid font swapping. Font swapping is automatically
155% done in vector formats (only): 11 standard Matlab fonts are
156% replaced by the original figure fonts. This option prevents this.
157% -linecaps - option to create rounded line-caps (vector formats only).
158% handle - The handle of the figure, axes or uipanels (can be an array of
159% handles, but the objects must be in the same figure) to be
160% saved. Default: gcf.
161%
162% Outputs:
163% imageData - MxNxC uint8 image array of the exported image.
164% alpha - MxN single array of alphamatte values in the range [0,1],
165% for the case when the background is transparent.
166%
167% Some helpful examples and tips can be found at:
168% https://github.com/altmany/export_fig
169%
170% See also PRINT, SAVEAS, ScreenCapture (on the Matlab File Exchange)
171
172%{
173% Copyright (C) Oliver Woodford 2008-2014, Yair Altman 2015-
174
175% The idea of using ghostscript is inspired by Peder Axensten's SAVEFIG
176% (fex id: 10889) which is itself inspired by EPS2PDF (fex id: 5782).
177% The idea for using pdftops came from the MATLAB newsgroup (id: 168171).
178% The idea of editing the EPS file to change line styles comes from Jiro
179% Doke's FIXPSLINESTYLE (fex id: 17928).
180% The idea of changing dash length with line width came from comments on
181% fex id: 5743, but the implementation is mine :)
182% The idea of anti-aliasing bitmaps came from Anders Brun's MYAA (fex id:
183% 20979).
184% The idea of appending figures in pdfs came from Matt C in comments on the
185% FEX (id: 23629)
186
187% Thanks to Roland Martin for pointing out the colour MATLAB
188% bug/feature with colorbar axes and transparent backgrounds.
189% Thanks also to Andrew Matthews for describing a bug to do with the figure
190% size changing in -nodisplay mode. I couldn't reproduce it, but included a
191% fix anyway.
192% Thanks to Tammy Threadgill for reporting a bug where an axes is not
193% isolated from gui objects.
194%}
195%{
196% 23/02/12: Ensure that axes limits don't change during printing
197% 14/03/12: Fix bug in fixing the axes limits (thanks to Tobias Lamour for reporting it).
198% 02/05/12: Incorporate patch of Petr Nechaev (many thanks), enabling bookmarking of figures in pdf files.
199% 09/05/12: Incorporate patch of Arcelia Arrieta (many thanks), to keep tick marks fixed.
200% 12/12/12: Add support for isolating uipanels. Thanks to michael for suggesting it.
201% 25/09/13: Add support for changing resolution in vector formats. Thanks to Jan Jaap Meijer for suggesting it.
202% 07/05/14: Add support for '~' at start of path. Thanks to Sally Warner for suggesting it.
203% 24/02/15: Fix Matlab R2014b bug (issue #34): plot markers are not displayed when ZLimMode='manual'
204% 25/02/15: Fix issue #4 (using HG2 on R2014a and earlier)
205% 25/02/15: Fix issue #21 (bold TeX axes labels/titles in R2014b)
206% 26/02/15: If temp dir is not writable, use the user-specified folder for temporary EPS/PDF files (Javier Paredes)
207% 27/02/15: Modified repository URL from github.com/ojwoodford to /altmany
208% Indented main function
209% Added top-level try-catch block to display useful workarounds
210% 28/02/15: Enable users to specify optional ghostscript options (issue #36)
211% 06/03/15: Improved image padding & cropping thanks to Oscar Hartogensis
212% 26/03/15: Fixed issue #49 (bug with transparent grayscale images); fixed out-of-memory issue
213% 26/03/15: Fixed issue #42: non-normalized annotations on HG1
214% 26/03/15: Fixed issue #46: Ghostscript crash if figure units <> pixels
215% 27/03/15: Fixed issue #39: bad export of transparent annotations/patches
216% 28/03/15: Fixed issue #50: error on some Matlab versions with the fix for issue #42
217% 29/03/15: Fixed issue #33: bugs in Matlab's print() function with -cmyk
218% 29/03/15: Improved processing of input args (accept space between param name & value, related to issue #51)
219% 30/03/15: When exporting *.fig files, then saveas *.fig if figure is open, otherwise export the specified fig file
220% 30/03/15: Fixed edge case bug introduced yesterday (commit #ae1755bd2e11dc4e99b95a7681f6e211b3fa9358)
221% 09/04/15: Consolidated header comment sections; initialize output vars only if requested (nargout>0)
222% 14/04/15: Workaround for issue #45: lines in image subplots are exported in invalid color
223% 15/04/15: Fixed edge-case in parsing input parameters; fixed help section to show the -depsc option (issue #45)
224% 21/04/15: Bug fix: Ghostscript croaks on % chars in output PDF file (reported by Sven on FEX page, 15-Jul-2014)
225% 22/04/15: Bug fix: Pdftops croaks on relative paths (reported by Tintin Milou on FEX page, 19-Jan-2015)
226% 04/05/15: Merged fix #63 (Kevin Mattheus Moerman): prevent tick-label changes during export
227% 07/05/15: Partial fix for issue #65: PDF export used painters rather than opengl renderer (thanks Nguyenr)
228% 08/05/15: Fixed issue #65: bad PDF append since commit #e9f3cdf 21/04/15 (thanks Robert Nguyen)
229% 12/05/15: Fixed issue #67: exponent labels cropped in export, since fix #63 (04/05/15)
230% 28/05/15: Fixed issue #69: set non-bold label font only if the string contains symbols (\beta etc.), followup to issue #21
231% 29/05/15: Added informative error message in case user requested SVG output (issue #72)
232% 09/06/15: Fixed issue #58: -transparent removed anti-aliasing when exporting to PNG
233% 19/06/15: Added -update option to download and install the latest version of export_fig
234% 07/07/15: Added -nofontswap option to avoid font-swapping in EPS/PDF
235% 16/07/15: Fixed problem with anti-aliasing on old Matlab releases
236% 11/09/15: Fixed issue #103: magnification must never become negative; also fixed reported error msg in parsing input params
237% 26/09/15: Alert if trying to export transparent patches/areas to non-PNG outputs (issue #108)
238% 04/10/15: Do not suggest workarounds for certain errors that have already been handled previously
239% 01/11/15: Fixed issue #112: use same renderer in print2eps as export_fig (thanks to Jesús Pestana Puerta)
240% 10/11/15: Custom GS installation webpage for MacOS. Thanks to Andy Hueni via FEX
241% 19/11/15: Fixed clipboard export in R2015b (thanks to Dan K via FEX)
242% 21/02/16: Added -c option for indicating specific crop amounts (idea by Cedric Noordam on FEX)
243% 08/05/16: Added message about possible error reason when groot.Units~=pixels (issue #149)
244% 17/05/16: Fixed case of image YData containing more than 2 elements (issue #151)
245% 08/08/16: Enabled exporting transparency to TIF, in addition to PNG/PDF (issue #168)
246% 11/12/16: Added alert in case of error creating output PDF/EPS file (issue #179)
247% 13/12/16: Minor fix to the commit for issue #179 from 2 days ago
248% 22/03/17: Fixed issue #187: only set manual ticks when no exponent is present
249% 09/04/17: Added -linecaps option (idea by Baron Finer, issue #192)
250%}
251
252 if nargout
253 [imageData, alpha] = deal([]);
254 end
255 hadError = false;
256 displaySuggestedWorkarounds = true;
257
258 % Ensure the figure is rendered correctly _now_ so that properties like axes limits are up-to-date
259 drawnow;
260 pause(0.05); % this solves timing issues with Java Swing's EDT (http://undocumentedmatlab.com/blog/solving-a-matlab-hang-problem)
261
262 % Parse the input arguments
263 fig = get(0, 'CurrentFigure');
264 [fig, options] = parse_args(nargout, fig, varargin{:});
265
266 % Ensure that we have a figure handle
267 if isequal(fig,-1)
268 return; % silent bail-out
269 elseif isempty(fig)
270 error('No figure found');
271 end
272
273 % Isolate the subplot, if it is one
274 cls = all(ismember(get(fig, 'Type'), {'axes', 'uipanel'}));
275 if cls
276 % Given handles of one or more axes, so isolate them from the rest
277 fig = isolate_axes(fig);
278 else
279 % Check we have a figure
280 if ~isequal(get(fig, 'Type'), 'figure')
281 error('Handle must be that of a figure, axes or uipanel');
282 end
283 % Get the old InvertHardcopy mode
284 old_mode = get(fig, 'InvertHardcopy');
285 end
286
287 % Hack the font units where necessary (due to a font rendering bug in print?).
288 % This may not work perfectly in all cases.
289 % Also it can change the figure layout if reverted, so use a copy.
290 magnify = options.magnify * options.aa_factor;
291 if isbitmap(options) && magnify ~= 1
292 fontu = findall(fig, 'FontUnits', 'normalized');
293 if ~isempty(fontu)
294 % Some normalized font units found
295 if ~cls
296 fig = copyfig(fig);
297 set(fig, 'Visible', 'off');
298 fontu = findall(fig, 'FontUnits', 'normalized');
299 cls = true;
300 end
301 set(fontu, 'FontUnits', 'points');
302 end
303 end
304
305 try
306 % MATLAB "feature": axes limits and tick marks can change when printing
307 Hlims = findall(fig, 'Type', 'axes');
308 if ~cls
309 % Record the old axes limit and tick modes
310 Xlims = make_cell(get(Hlims, 'XLimMode'));
311 Ylims = make_cell(get(Hlims, 'YLimMode'));
312 Zlims = make_cell(get(Hlims, 'ZLimMode'));
313 Xtick = make_cell(get(Hlims, 'XTickMode'));
314 Ytick = make_cell(get(Hlims, 'YTickMode'));
315 Ztick = make_cell(get(Hlims, 'ZTickMode'));
316 Xlabel = make_cell(get(Hlims, 'XTickLabelMode'));
317 Ylabel = make_cell(get(Hlims, 'YTickLabelMode'));
318 Zlabel = make_cell(get(Hlims, 'ZTickLabelMode'));
319 end
320
321 % Set all axes limit and tick modes to manual, so the limits and ticks can't change
322 % Fix Matlab R2014b bug (issue #34): plot markers are not displayed when ZLimMode='manual'
323 set(Hlims, 'XLimMode', 'manual', 'YLimMode', 'manual');
324 set_tick_mode(Hlims, 'X');
325 set_tick_mode(Hlims, 'Y');
326 if ~using_hg2(fig)
327 set(Hlims,'ZLimMode', 'manual');
328 set_tick_mode(Hlims, 'Z');
329 end
330 catch
331 % ignore - fix issue #4 (using HG2 on R2014a and earlier)
332 end
333
334 % Fix issue #21 (bold TeX axes labels/titles in R2014b when exporting to EPS/PDF)
335 try
336 if using_hg2(fig) && isvector(options)
337 % Set the FontWeight of axes labels/titles to 'normal'
338 % Fix issue #69: set non-bold font only if the string contains symbols (\beta etc.)
339 texLabels = findall(fig, 'type','text', 'FontWeight','bold');
340 symbolIdx = ~cellfun('isempty',strfind({texLabels.String},'\'));
341 set(texLabels(symbolIdx), 'FontWeight','normal');
342 end
343 catch
344 % ignore
345 end
346
347 % Fix issue #42: non-normalized annotations on HG1 (internal Matlab bug)
348 annotationHandles = [];
349 try
350 if ~using_hg2(fig)
351 annotationHandles = findall(fig,'Type','hggroup','-and','-property','Units','-and','-not','Units','norm');
352 try % suggested by Jesús Pestana Puerta (jespestana) 30/9/2015
353 originalUnits = get(annotationHandles,'Units');
354 set(annotationHandles,'Units','norm');
355 catch
356 end
357 end
358 catch
359 % should never happen, but ignore in any case - issue #50
360 end
361
362 % Fix issue #46: Ghostscript crash if figure units <> pixels
363 oldFigUnits = get(fig,'Units');
364 set(fig,'Units','pixels');
365
366 % Set to print exactly what is there
367 set(fig, 'InvertHardcopy', 'off');
368 % Set the renderer
369 switch options.renderer
370 case 1
371 renderer = '-opengl';
372 case 2
373 renderer = '-zbuffer';
374 case 3
375 renderer = '-painters';
376 otherwise
377 renderer = '-opengl'; % Default for bitmaps
378 end
379
380 % Handle transparent patches
381 hasTransparency = ~isempty(findall(fig,'-property','FaceAlpha','-and','-not','FaceAlpha',1));
382 hasPatches = ~isempty(findall(fig,'type','patch'));
383 if hasTransparency
384 % Alert if trying to export transparent patches/areas to non-supported outputs (issue #108)
385 % http://www.mathworks.com/matlabcentral/answers/265265-can-export_fig-or-else-draw-vector-graphics-with-transparent-surfaces
386 % TODO - use transparency when exporting to PDF by not passing via print2eps
387 msg = 'export_fig currently supports transparent patches/areas only in PNG output. ';
388 if options.pdf
389 warning('export_fig:transparency', '%s\nTo export transparent patches/areas to PDF, use the print command:\n print(gcf, ''-dpdf'', ''%s.pdf'');', msg, options.name);
390 elseif ~options.png && ~options.tif % issue #168
391 warning('export_fig:transparency', '%s\nTo export the transparency correctly, try using the ScreenCapture utility on the Matlab File Exchange: http://bit.ly/1QFrBip', msg);
392 end
393 end
394
395 try
396 % Do the bitmap formats first
397 if isbitmap(options)
398 if abs(options.bb_padding) > 1
399 displaySuggestedWorkarounds = false;
400 error('For bitmap output (png,jpg,tif,bmp) the padding value (-p) must be between -1<p<1')
401 end
402 % Get the background colour
403 if options.transparent && (options.png || options.alpha)
404 % Get out an alpha channel
405 % MATLAB "feature": black colorbar axes can change to white and vice versa!
406 hCB = findall(fig, 'Type','axes', 'Tag','Colorbar');
407 if isempty(hCB)
408 yCol = [];
409 xCol = [];
410 else
411 yCol = get(hCB, 'YColor');
412 xCol = get(hCB, 'XColor');
413 if iscell(yCol)
414 yCol = cell2mat(yCol);
415 xCol = cell2mat(xCol);
416 end
417 yCol = sum(yCol, 2);
418 xCol = sum(xCol, 2);
419 end
420 % MATLAB "feature": apparently figure size can change when changing
421 % colour in -nodisplay mode
422 pos = get(fig, 'Position');
423 % Set the background colour to black, and set size in case it was
424 % changed internally
425 tcol = get(fig, 'Color');
426 set(fig, 'Color', 'k', 'Position', pos);
427 % Correct the colorbar axes colours
428 set(hCB(yCol==0), 'YColor', [0 0 0]);
429 set(hCB(xCol==0), 'XColor', [0 0 0]);
430
431 % The following code might cause out-of-memory errors
432 try
433 % Print large version to array
434 B = print2array(fig, magnify, renderer);
435 % Downscale the image
436 B = downsize(single(B), options.aa_factor);
437 catch
438 % This is more conservative in memory, but kills transparency (issue #58)
439 B = single(print2array(fig, magnify/options.aa_factor, renderer));
440 end
441
442 % Set background to white (and set size)
443 set(fig, 'Color', 'w', 'Position', pos);
444 % Correct the colorbar axes colours
445 set(hCB(yCol==3), 'YColor', [1 1 1]);
446 set(hCB(xCol==3), 'XColor', [1 1 1]);
447
448 % The following code might cause out-of-memory errors
449 try
450 % Print large version to array
451 A = print2array(fig, magnify, renderer);
452 % Downscale the image
453 A = downsize(single(A), options.aa_factor);
454 catch
455 % This is more conservative in memory, but kills transparency (issue #58)
456 A = single(print2array(fig, magnify/options.aa_factor, renderer));
457 end
458
459 % Set the background colour (and size) back to normal
460 set(fig, 'Color', tcol, 'Position', pos);
461 % Compute the alpha map
462 alpha = round(sum(B - A, 3)) / (255 * 3) + 1;
463 A = alpha;
464 A(A==0) = 1;
465 A = B ./ A(:,:,[1 1 1]);
466 clear B
467 % Convert to greyscale
468 if options.colourspace == 2
469 A = rgb2grey(A);
470 end
471 A = uint8(A);
472 % Crop the background
473 if options.crop
474 %[alpha, v] = crop_borders(alpha, 0, 1, options.crop_amounts);
475 %A = A(v(1):v(2),v(3):v(4),:);
476 [alpha, vA, vB] = crop_borders(alpha, 0, options.bb_padding, options.crop_amounts);
477 if ~any(isnan(vB)) % positive padding
478 B = repmat(uint8(zeros(1,1,size(A,3))),size(alpha));
479 B(vB(1):vB(2), vB(3):vB(4), :) = A(vA(1):vA(2), vA(3):vA(4), :); % ADDED BY OH
480 A = B;
481 else % negative padding
482 A = A(vA(1):vA(2), vA(3):vA(4), :);
483 end
484 end
485 if options.png
486 % Compute the resolution
487 res = options.magnify * get(0, 'ScreenPixelsPerInch') / 25.4e-3;
488 % Save the png
489 imwrite(A, [options.name '.png'], 'Alpha', double(alpha), 'ResolutionUnit', 'meter', 'XResolution', res, 'YResolution', res);
490 % Clear the png bit
491 options.png = false;
492 end
493 % Return only one channel for greyscale
494 if isbitmap(options)
495 A = check_greyscale(A);
496 end
497 if options.alpha
498 % Store the image
499 imageData = A;
500 % Clear the alpha bit
501 options.alpha = false;
502 end
503 % Get the non-alpha image
504 if isbitmap(options)
505 alph = alpha(:,:,ones(1, size(A, 3)));
506 A = uint8(single(A) .* alph + 255 * (1 - alph));
507 clear alph
508 end
509 if options.im
510 % Store the new image
511 imageData = A;
512 end
513 else
514 % Print large version to array
515 if options.transparent
516 % MATLAB "feature": apparently figure size can change when changing
517 % colour in -nodisplay mode
518 pos = get(fig, 'Position');
519 tcol = get(fig, 'Color');
520 set(fig, 'Color', 'w', 'Position', pos);
521 A = print2array(fig, magnify, renderer);
522 set(fig, 'Color', tcol, 'Position', pos);
523 tcol = 255;
524 else
525 [A, tcol] = print2array(fig, magnify, renderer);
526 end
527 % Crop the background
528 if options.crop
529 A = crop_borders(A, tcol, options.bb_padding, options.crop_amounts);
530 end
531 % Downscale the image
532 A = downsize(A, options.aa_factor);
533 if options.colourspace == 2
534 % Convert to greyscale
535 A = rgb2grey(A);
536 else
537 % Return only one channel for greyscale
538 A = check_greyscale(A);
539 end
540 % Outputs
541 if options.im
542 imageData = A;
543 end
544 if options.alpha
545 imageData = A;
546 alpha = zeros(size(A, 1), size(A, 2), 'single');
547 end
548 end
549 % Save the images
550 if options.png
551 res = options.magnify * get(0, 'ScreenPixelsPerInch') / 25.4e-3;
552 imwrite(A, [options.name '.png'], 'ResolutionUnit', 'meter', 'XResolution', res, 'YResolution', res);
553 end
554 if options.bmp
555 imwrite(A, [options.name '.bmp']);
556 end
557 % Save jpeg with given quality
558 if options.jpg
559 quality = options.quality;
560 if isempty(quality)
561 quality = 95;
562 end
563 if quality > 100
564 imwrite(A, [options.name '.jpg'], 'Mode', 'lossless');
565 else
566 imwrite(A, [options.name '.jpg'], 'Quality', quality);
567 end
568 end
569 % Save tif images in cmyk if wanted (and possible)
570 if options.tif
571 if options.colourspace == 1 && size(A, 3) == 3
572 A = double(255 - A);
573 K = min(A, [], 3);
574 K_ = 255 ./ max(255 - K, 1);
575 C = (A(:,:,1) - K) .* K_;
576 M = (A(:,:,2) - K) .* K_;
577 Y = (A(:,:,3) - K) .* K_;
578 A = uint8(cat(3, C, M, Y, K));
579 clear C M Y K K_
580 end
581 append_mode = {'overwrite', 'append'};
582 imwrite(A, [options.name '.tif'], 'Resolution', options.magnify*get(0, 'ScreenPixelsPerInch'), 'WriteMode', append_mode{options.append+1});
583 end
584 end
585
586 % Now do the vector formats
587 if isvector(options)
588 % Set the default renderer to painters
589 if ~options.renderer
590 if hasTransparency || hasPatches
591 % This is *MUCH* slower, but more accurate for patches and transparent annotations (issue #39)
592 renderer = '-painters'; %ISSM fix
593 else
594 renderer = '-painters';
595 end
596 end
597 options.rendererStr = renderer; % fix for issue #112
598 % Generate some filenames
599 tmp_nam = [tempname '.eps'];
600 try
601 % Ensure that the temp dir is writable (Javier Paredes 30/1/15)
602 fid = fopen(tmp_nam,'w');
603 fwrite(fid,1);
604 fclose(fid);
605 delete(tmp_nam);
606 isTempDirOk = true;
607 catch
608 % Temp dir is not writable, so use the user-specified folder
609 [dummy,fname,fext] = fileparts(tmp_nam); %#ok<ASGLU>
610 fpath = fileparts(options.name);
611 tmp_nam = fullfile(fpath,[fname fext]);
612 isTempDirOk = false;
613 end
614 if isTempDirOk
615 pdf_nam_tmp = [tempname '.pdf'];
616 else
617 pdf_nam_tmp = fullfile(fpath,[fname '.pdf']);
618 end
619 if options.pdf
620 pdf_nam = [options.name '.pdf'];
621 try copyfile(pdf_nam, pdf_nam_tmp, 'f'); catch, end % fix for issue #65
622 else
623 pdf_nam = pdf_nam_tmp;
624 end
625 % Generate the options for print
626 p2eArgs = {renderer, sprintf('-r%d', options.resolution)};
627 if options.colourspace == 1 % CMYK
628 % Issue #33: due to internal bugs in Matlab's print() function, we can't use its -cmyk option
629 %p2eArgs{end+1} = '-cmyk';
630 end
631 if ~options.crop
632 % Issue #56: due to internal bugs in Matlab's print() function, we can't use its internal cropping mechanism,
633 % therefore we always use '-loose' (in print2eps.m) and do our own cropping (in crop_borders)
634 %p2eArgs{end+1} = '-loose';
635 end
636 if any(strcmpi(varargin,'-depsc'))
637 % Issue #45: lines in image subplots are exported in invalid color.
638 % The workaround is to use the -depsc parameter instead of the default -depsc2
639 p2eArgs{end+1} = '-depsc';
640 end
641 try
642 % Generate an eps
643 print2eps(tmp_nam, fig, options, p2eArgs{:});
644 % Remove the background, if desired
645 if options.transparent && ~isequal(get(fig, 'Color'), 'none')
646 eps_remove_background(tmp_nam, 1 + using_hg2(fig));
647 end
648 % Fix colorspace to CMYK, if requested (workaround for issue #33)
649 if options.colourspace == 1 % CMYK
650 % Issue #33: due to internal bugs in Matlab's print() function, we can't use its -cmyk option
651 change_rgb_to_cmyk(tmp_nam);
652 end
653 % Add a bookmark to the PDF if desired
654 if options.bookmark
655 fig_nam = get(fig, 'Name');
656 if isempty(fig_nam)
657 warning('export_fig:EmptyBookmark', 'Bookmark requested for figure with no name. Bookmark will be empty.');
658 end
659 add_bookmark(tmp_nam, fig_nam);
660 end
661 % Generate a pdf
662 eps2pdf(tmp_nam, pdf_nam_tmp, 1, options.append, options.colourspace==2, options.quality, options.gs_options);
663 % Ghostscript croaks on % chars in the output PDF file, so use tempname and then rename the file
664 try
665 % Rename the file (except if it is already the same)
666 % Abbie K's comment on the commit for issue #179 (#commitcomment-20173476)
667 if ~isequal(pdf_nam_tmp, pdf_nam)
668 movefile(pdf_nam_tmp, pdf_nam, 'f');
669 end
670 catch
671 % Alert in case of error creating output PDF/EPS file (issue #179)
672 if exist(pdf_nam_tmp, 'file')
673 error(['Could not create ' pdf_nam ' - perhaps the folder does not exist, or you do not have write permissions']);
674 else
675 error('Could not generate the intermediary EPS file.');
676 end
677 end
678 catch ex
679 % Delete the eps
680 delete(tmp_nam);
681 rethrow(ex);
682 end
683 % Delete the eps
684 delete(tmp_nam);
685 if options.eps || options.linecaps
686 try
687 % Generate an eps from the pdf
688 % since pdftops can't handle relative paths (e.g., '..\'), use a temp file
689 eps_nam_tmp = strrep(pdf_nam_tmp,'.pdf','.eps');
690 pdf2eps(pdf_nam, eps_nam_tmp);
691
692 % Issue #192: enable rounded line-caps
693 if options.linecaps
694 fstrm = read_write_entire_textfile(eps_nam_tmp);
695 fstrm = regexprep(fstrm, '[02] J', '1 J');
696 read_write_entire_textfile(eps_nam_tmp, fstrm);
697 if options.pdf
698 eps2pdf(eps_nam_tmp, pdf_nam, 1, options.append, options.colourspace==2, options.quality, options.gs_options);
699 end
700 end
701
702 if options.eps
703 movefile(eps_nam_tmp, [options.name '.eps'], 'f');
704 else % if options.pdf
705 try delete(eps_nam_tmp); catch, end
706 end
707 catch ex
708 if ~options.pdf
709 % Delete the pdf
710 delete(pdf_nam);
711 end
712 try delete(eps_nam_tmp); catch, end
713 rethrow(ex);
714 end
715 if ~options.pdf
716 % Delete the pdf
717 delete(pdf_nam);
718 end
719 end
720 end
721
722 % Revert the figure or close it (if requested)
723 if cls || options.closeFig
724 % Close the created figure
725 close(fig);
726 else
727 % Reset the hardcopy mode
728 set(fig, 'InvertHardcopy', old_mode);
729 % Reset the axes limit and tick modes
730 for a = 1:numel(Hlims)
731 try
732 set(Hlims(a), 'XLimMode', Xlims{a}, 'YLimMode', Ylims{a}, 'ZLimMode', Zlims{a},...
733 'XTickMode', Xtick{a}, 'YTickMode', Ytick{a}, 'ZTickMode', Ztick{a},...
734 'XTickLabelMode', Xlabel{a}, 'YTickLabelMode', Ylabel{a}, 'ZTickLabelMode', Zlabel{a});
735 catch
736 % ignore - fix issue #4 (using HG2 on R2014a and earlier)
737 end
738 end
739 % Revert the tex-labels font weights
740 try set(texLabels, 'FontWeight','bold'); catch, end
741 % Revert annotation units
742 for handleIdx = 1 : numel(annotationHandles)
743 try
744 oldUnits = originalUnits{handleIdx};
745 catch
746 oldUnits = originalUnits;
747 end
748 try set(annotationHandles(handleIdx),'Units',oldUnits); catch, end
749 end
750 % Revert figure units
751 set(fig,'Units',oldFigUnits);
752 end
753
754 % Output to clipboard (if requested)
755 if options.clipboard
756 % Delete the output file if unchanged from the default name ('export_fig_out.png')
757 if strcmpi(options.name,'export_fig_out')
758 try
759 fileInfo = dir('export_fig_out.png');
760 if ~isempty(fileInfo)
761 timediff = now - fileInfo.datenum;
762 ONE_SEC = 1/24/60/60;
763 if timediff < ONE_SEC
764 delete('export_fig_out.png');
765 end
766 end
767 catch
768 % never mind...
769 end
770 end
771
772 % Save the image in the system clipboard
773 % credit: Jiro Doke's IMCLIPBOARD: http://www.mathworks.com/matlabcentral/fileexchange/28708-imclipboard
774 try
775 error(javachk('awt', 'export_fig -clipboard output'));
776 catch
777 warning('export_fig -clipboard output failed: requires Java to work');
778 return;
779 end
780 try
781 % Import necessary Java classes
782 import java.awt.Toolkit
783 import java.awt.image.BufferedImage
784 import java.awt.datatransfer.DataFlavor
785
786 % Get System Clipboard object (java.awt.Toolkit)
787 cb = Toolkit.getDefaultToolkit.getSystemClipboard();
788
789 % Add java class (ImageSelection) to the path
790 if ~exist('ImageSelection', 'class')
791 javaaddpath(fileparts(which(mfilename)), '-end');
792 end
793
794 % Get image size
795 ht = size(imageData, 1);
796 wd = size(imageData, 2);
797
798 % Convert to Blue-Green-Red format
799 try
800 imageData2 = imageData(:, :, [3 2 1]);
801 catch
802 % Probably gray-scaled image (2D, without the 3rd [RGB] dimension)
803 imageData2 = imageData(:, :, [1 1 1]);
804 end
805
806 % Convert to 3xWxH format
807 imageData2 = permute(imageData2, [3, 2, 1]);
808
809 % Append Alpha data (unused - transparency is not supported in clipboard copy)
810 alphaData2 = uint8(permute(255*alpha,[3,2,1])); %=255*ones(1,wd,ht,'uint8')
811 imageData2 = cat(1, imageData2, alphaData2);
812
813 % Create image buffer
814 imBuffer = BufferedImage(wd, ht, BufferedImage.TYPE_INT_RGB);
815 imBuffer.setRGB(0, 0, wd, ht, typecast(imageData2(:), 'int32'), 0, wd);
816
817 % Create ImageSelection object from the image buffer
818 imSelection = ImageSelection(imBuffer);
819
820 % Set clipboard content to the image
821 cb.setContents(imSelection, []);
822 catch
823 warning('export_fig -clipboard output failed: %s', lasterr); %#ok<LERR>
824 end
825 end
826
827 % Don't output the data to console unless requested
828 if ~nargout
829 clear imageData alpha
830 end
831 catch err
832 % Display possible workarounds before the error message
833 if displaySuggestedWorkarounds && ~strcmpi(err.message,'export_fig error')
834 if ~hadError, fprintf(2, 'export_fig error. '); end
835 fprintf(2, 'Please ensure:\n');
836 fprintf(2, ' that you are using the <a href="https://github.com/altmany/export_fig/archive/master.zip">latest version</a> of export_fig\n');
837 if ismac
838 fprintf(2, ' and that you have <a href="http://pages.uoregon.edu/koch">Ghostscript</a> installed\n');
839 else
840 fprintf(2, ' and that you have <a href="http://www.ghostscript.com">Ghostscript</a> installed\n');
841 end
842 try
843 if options.eps
844 fprintf(2, ' and that you have <a href="http://www.foolabs.com/xpdf">pdftops</a> installed\n');
845 end
846 catch
847 % ignore - probably an error in parse_args
848 end
849 fprintf(2, ' and that you do not have <a href="matlab:which export_fig -all">multiple versions</a> of export_fig installed by mistake\n');
850 fprintf(2, ' and that you did not made a mistake in the <a href="matlab:help export_fig">expected input arguments</a>\n');
851 try
852 % Alert per issue #149
853 if ~strncmpi(get(0,'Units'),'pixel',5)
854 fprintf(2, ' or try to set groot''s Units property back to its default value of ''pixels'' (<a href="matlab:web(''https://github.com/altmany/export_fig/issues/149'',''-browser'');">details</a>)\n');
855 end
856 catch
857 % ignore - maybe an old MAtlab release
858 end
859 fprintf(2, '\nIf the problem persists, then please <a href="https://github.com/altmany/export_fig/issues">report a new issue</a>.\n\n');
860 end
861 rethrow(err)
862 end
863end
864
865function options = default_options()
866 % Default options used by export_fig
867 options = struct(...
868 'name', 'export_fig_out', ...
869 'crop', true, ...
870 'crop_amounts', nan(1,4), ... % auto-crop all 4 image sides
871 'transparent', false, ...
872 'renderer', 0, ... % 0: default, 1: OpenGL, 2: ZBuffer, 3: Painters
873 'pdf', false, ...
874 'eps', false, ...
875 'png', false, ...
876 'tif', false, ...
877 'jpg', false, ...
878 'bmp', false, ...
879 'clipboard', false, ...
880 'colourspace', 0, ... % 0: RGB/gray, 1: CMYK, 2: gray
881 'append', false, ...
882 'im', false, ...
883 'alpha', false, ...
884 'aa_factor', 0, ...
885 'bb_padding', 0, ...
886 'magnify', [], ...
887 'resolution', [], ...
888 'bookmark', false, ...
889 'closeFig', false, ...
890 'quality', [], ...
891 'update', false, ...
892 'fontswap', true, ...
893 'linecaps', false, ...
894 'gs_options', {{}});
895end
896
897function [fig, options] = parse_args(nout, fig, varargin)
898 % Parse the input arguments
899
900 % Set the defaults
901 native = false; % Set resolution to native of an image
902 options = default_options();
903 options.im = (nout == 1); % user requested imageData output
904 options.alpha = (nout == 2); % user requested alpha output
905
906 % Go through the other arguments
907 skipNext = false;
908 for a = 1:nargin-2
909 if skipNext
910 skipNext = false;
911 continue;
912 end
913 if all(ishandle(varargin{a}))
914 fig = varargin{a};
915 elseif ischar(varargin{a}) && ~isempty(varargin{a})
916 if varargin{a}(1) == '-'
917 switch lower(varargin{a}(2:end))
918 case 'nocrop'
919 options.crop = false;
920 options.crop_amounts = [0,0,0,0];
921 case {'trans', 'transparent'}
922 options.transparent = true;
923 case 'opengl'
924 options.renderer = 1;
925 case 'zbuffer'
926 options.renderer = 2;
927 case 'painters'
928 options.renderer = 3;
929 case 'pdf'
930 options.pdf = true;
931 case 'eps'
932 options.eps = true;
933 case 'png'
934 options.png = true;
935 case {'tif', 'tiff'}
936 options.tif = true;
937 case {'jpg', 'jpeg'}
938 options.jpg = true;
939 case 'bmp'
940 options.bmp = true;
941 case 'rgb'
942 options.colourspace = 0;
943 case 'cmyk'
944 options.colourspace = 1;
945 case {'gray', 'grey'}
946 options.colourspace = 2;
947 case {'a1', 'a2', 'a3', 'a4'}
948 options.aa_factor = str2double(varargin{a}(3));
949 case 'append'
950 options.append = true;
951 case 'bookmark'
952 options.bookmark = true;
953 case 'native'
954 native = true;
955 case 'clipboard'
956 options.clipboard = true;
957 options.im = true;
958 options.alpha = true;
959 case 'svg'
960 msg = ['SVG output is not supported by export_fig. Use one of the following alternatives:\n' ...
961 ' 1. saveas(gcf,''filename.svg'')\n' ...
962 ' 2. plot2svg utility: http://github.com/jschwizer99/plot2svg\n' ...
963 ' 3. export_fig to EPS/PDF, then convert to SVG using generic (non-Matlab) tools\n'];
964 error(sprintf(msg)); %#ok<SPERR>
965 case 'update'
966 % Download the latest version of export_fig into the export_fig folder
967 try
968 zipFileName = 'https://github.com/altmany/export_fig/archive/master.zip';
969 folderName = fileparts(which(mfilename('fullpath')));
970 targetFileName = fullfile(folderName, datestr(now,'yyyy-mm-dd.zip'));
971 urlwrite(zipFileName,targetFileName);
972 catch
973 error('Could not download %s into %s\n',zipFileName,targetFileName);
974 end
975
976 % Unzip the downloaded zip file in the export_fig folder
977 try
978 unzip(targetFileName,folderName);
979 catch
980 error('Could not unzip %s\n',targetFileName);
981 end
982 case 'nofontswap'
983 options.fontswap = false;
984 case 'linecaps'
985 options.linecaps = true;
986 otherwise
987 try
988 wasError = false;
989 if strcmpi(varargin{a}(1:2),'-d')
990 varargin{a}(2) = 'd'; % ensure lowercase 'd'
991 options.gs_options{end+1} = varargin{a};
992 elseif strcmpi(varargin{a}(1:2),'-c')
993 if numel(varargin{a})==2
994 skipNext = true;
995 vals = str2num(varargin{a+1}); %#ok<ST2NM>
996 else
997 vals = str2num(varargin{a}(3:end)); %#ok<ST2NM>
998 end
999 if numel(vals)~=4
1000 wasError = true;
1001 error('option -c cannot be parsed: must be a 4-element numeric vector');
1002 end
1003 options.crop_amounts = vals;
1004 options.crop = true;
1005 else % scalar parameter value
1006 val = str2double(regexp(varargin{a}, '(?<=-(m|M|r|R|q|Q|p|P))-?\d*.?\d+', 'match'));
1007 if isempty(val) || isnan(val)
1008 % Issue #51: improved processing of input args (accept space between param name & value)
1009 val = str2double(varargin{a+1});
1010 if isscalar(val) && ~isnan(val)
1011 skipNext = true;
1012 end
1013 end
1014 if ~isscalar(val) || isnan(val)
1015 wasError = true;
1016 error('option %s is not recognised or cannot be parsed', varargin{a});
1017 end
1018 switch lower(varargin{a}(2))
1019 case 'm'
1020 % Magnification may never be negative
1021 if val <= 0
1022 wasError = true;
1023 error('Bad magnification value: %g (must be positive)', val);
1024 end
1025 options.magnify = val;
1026 case 'r'
1027 options.resolution = val;
1028 case 'q'
1029 options.quality = max(val, 0);
1030 case 'p'
1031 options.bb_padding = val;
1032 end
1033 end
1034 catch err
1035 % We might have reached here by raising an intentional error
1036 if wasError % intentional raise
1037 rethrow(err)
1038 else % unintentional
1039 error(['Unrecognized export_fig input option: ''' varargin{a} '''']);
1040 end
1041 end
1042 end
1043 else
1044 [p, options.name, ext] = fileparts(varargin{a});
1045 if ~isempty(p)
1046 options.name = [p filesep options.name];
1047 end
1048 switch lower(ext)
1049 case {'.tif', '.tiff'}
1050 options.tif = true;
1051 case {'.jpg', '.jpeg'}
1052 options.jpg = true;
1053 case '.png'
1054 options.png = true;
1055 case '.bmp'
1056 options.bmp = true;
1057 case '.eps'
1058 options.eps = true;
1059 case '.pdf'
1060 options.pdf = true;
1061 case '.fig'
1062 % If no open figure, then load the specified .fig file and continue
1063 if isempty(fig)
1064 fig = openfig(varargin{a},'invisible');
1065 varargin{a} = fig;
1066 options.closeFig = true;
1067 else
1068 % save the current figure as the specified .fig file and exit
1069 saveas(fig(1),varargin{a});
1070 fig = -1;
1071 return
1072 end
1073 case '.svg'
1074 msg = ['SVG output is not supported by export_fig. Use one of the following alternatives:\n' ...
1075 ' 1. saveas(gcf,''filename.svg'')\n' ...
1076 ' 2. plot2svg utility: http://github.com/jschwizer99/plot2svg\n' ...
1077 ' 3. export_fig to EPS/PDF, then convert to SVG using generic (non-Matlab) tools\n'];
1078 error(sprintf(msg)); %#ok<SPERR>
1079 otherwise
1080 options.name = varargin{a};
1081 end
1082 end
1083 end
1084 end
1085
1086 % Quick bail-out if no figure found
1087 if isempty(fig), return; end
1088
1089 % Do border padding with repsect to a cropped image
1090 if options.bb_padding
1091 options.crop = true;
1092 end
1093
1094 % Set default anti-aliasing now we know the renderer
1095 if options.aa_factor == 0
1096 try isAA = strcmp(get(ancestor(fig, 'figure'), 'GraphicsSmoothing'), 'on'); catch, isAA = false; end
1097 options.aa_factor = 1 + 2 * (~(using_hg2(fig) && isAA) | (options.renderer == 3));
1098 end
1099
1100 % Convert user dir '~' to full path
1101 if numel(options.name) > 2 && options.name(1) == '~' && (options.name(2) == '/' || options.name(2) == '\')
1102 options.name = fullfile(char(java.lang.System.getProperty('user.home')), options.name(2:end));
1103 end
1104
1105 % Compute the magnification and resolution
1106 if isempty(options.magnify)
1107 if isempty(options.resolution)
1108 options.magnify = 1;
1109 options.resolution = 864;
1110 else
1111 options.magnify = options.resolution ./ get(0, 'ScreenPixelsPerInch');
1112 end
1113 elseif isempty(options.resolution)
1114 options.resolution = 864;
1115 end
1116
1117 % Set the default format
1118 if ~isvector(options) && ~isbitmap(options)
1119 options.png = true;
1120 end
1121
1122 % Check whether transparent background is wanted (old way)
1123 if isequal(get(ancestor(fig(1), 'figure'), 'Color'), 'none')
1124 options.transparent = true;
1125 end
1126
1127 % If requested, set the resolution to the native vertical resolution of the
1128 % first suitable image found
1129 if native && isbitmap(options)
1130 % Find a suitable image
1131 list = findall(fig, 'Type','image', 'Tag','export_fig_native');
1132 if isempty(list)
1133 list = findall(fig, 'Type','image', 'Visible','on');
1134 end
1135 for hIm = list(:)'
1136 % Check height is >= 2
1137 height = size(get(hIm, 'CData'), 1);
1138 if height < 2
1139 continue
1140 end
1141 % Account for the image filling only part of the axes, or vice versa
1142 yl = get(hIm, 'YData');
1143 if isscalar(yl)
1144 yl = [yl(1)-0.5 yl(1)+height+0.5];
1145 else
1146 yl = [min(yl), max(yl)]; % fix issue #151 (case of yl containing more than 2 elements)
1147 if ~diff(yl)
1148 continue
1149 end
1150 yl = yl + [-0.5 0.5] * (diff(yl) / (height - 1));
1151 end
1152 hAx = get(hIm, 'Parent');
1153 yl2 = get(hAx, 'YLim');
1154 % Find the pixel height of the axes
1155 oldUnits = get(hAx, 'Units');
1156 set(hAx, 'Units', 'pixels');
1157 pos = get(hAx, 'Position');
1158 set(hAx, 'Units', oldUnits);
1159 if ~pos(4)
1160 continue
1161 end
1162 % Found a suitable image
1163 % Account for stretch-to-fill being disabled
1164 pbar = get(hAx, 'PlotBoxAspectRatio');
1165 pos = min(pos(4), pbar(2)*pos(3)/pbar(1));
1166 % Set the magnification to give native resolution
1167 options.magnify = abs((height * diff(yl2)) / (pos * diff(yl))); % magnification must never be negative: issue #103
1168 break
1169 end
1170 end
1171end
1172
1173function A = downsize(A, factor)
1174 % Downsample an image
1175 if factor == 1
1176 % Nothing to do
1177 return
1178 end
1179 try
1180 % Faster, but requires image processing toolbox
1181 A = imresize(A, 1/factor, 'bilinear');
1182 catch
1183 % No image processing toolbox - resize manually
1184 % Lowpass filter - use Gaussian as is separable, so faster
1185 % Compute the 1d Gaussian filter
1186 filt = (-factor-1:factor+1) / (factor * 0.6);
1187 filt = exp(-filt .* filt);
1188 % Normalize the filter
1189 filt = single(filt / sum(filt));
1190 % Filter the image
1191 padding = floor(numel(filt) / 2);
1192 for a = 1:size(A, 3)
1193 A(:,:,a) = conv2(filt, filt', single(A([ones(1, padding) 1:end repmat(end, 1, padding)],[ones(1, padding) 1:end repmat(end, 1, padding)],a)), 'valid');
1194 end
1195 % Subsample
1196 A = A(1+floor(mod(end-1, factor)/2):factor:end,1+floor(mod(end-1, factor)/2):factor:end,:);
1197 end
1198end
1199
1200function A = rgb2grey(A)
1201 A = cast(reshape(reshape(single(A), [], 3) * single([0.299; 0.587; 0.114]), size(A, 1), size(A, 2)), class(A)); % #ok<ZEROLIKE>
1202end
1203
1204function A = check_greyscale(A)
1205 % Check if the image is greyscale
1206 if size(A, 3) == 3 && ...
1207 all(reshape(A(:,:,1) == A(:,:,2), [], 1)) && ...
1208 all(reshape(A(:,:,2) == A(:,:,3), [], 1))
1209 A = A(:,:,1); % Save only one channel for 8-bit output
1210 end
1211end
1212
1213function eps_remove_background(fname, count)
1214 % Remove the background of an eps file
1215 % Open the file
1216 fh = fopen(fname, 'r+');
1217 if fh == -1
1218 error('Not able to open file %s.', fname);
1219 end
1220 % Read the file line by line
1221 while count
1222 % Get the next line
1223 l = fgets(fh);
1224 if isequal(l, -1)
1225 break; % Quit, no rectangle found
1226 end
1227 % Check if the line contains the background rectangle
1228 if isequal(regexp(l, ' *0 +0 +\d+ +\d+ +r[fe] *[\n\r]+', 'start'), 1)
1229 % Set the line to whitespace and quit
1230 l(1:regexp(l, '[\n\r]', 'start', 'once')-1) = ' ';
1231 fseek(fh, -numel(l), 0);
1232 fprintf(fh, l);
1233 % Reduce the count
1234 count = count - 1;
1235 end
1236 end
1237 % Close the file
1238 fclose(fh);
1239end
1240
1241function b = isvector(options)
1242 b = options.pdf || options.eps;
1243end
1244
1245function b = isbitmap(options)
1246 b = options.png || options.tif || options.jpg || options.bmp || options.im || options.alpha;
1247end
1248
1249% Helper function
1250function A = make_cell(A)
1251 if ~iscell(A)
1252 A = {A};
1253 end
1254end
1255
1256function add_bookmark(fname, bookmark_text)
1257 % Adds a bookmark to the temporary EPS file after %%EndPageSetup
1258 % Read in the file
1259 fh = fopen(fname, 'r');
1260 if fh == -1
1261 error('File %s not found.', fname);
1262 end
1263 try
1264 fstrm = fread(fh, '*char')';
1265 catch ex
1266 fclose(fh);
1267 rethrow(ex);
1268 end
1269 fclose(fh);
1270
1271 % Include standard pdfmark prolog to maximize compatibility
1272 fstrm = strrep(fstrm, '%%BeginProlog', sprintf('%%%%BeginProlog\n/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse'));
1273 % Add page bookmark
1274 fstrm = strrep(fstrm, '%%EndPageSetup', sprintf('%%%%EndPageSetup\n[ /Title (%s) /OUT pdfmark',bookmark_text));
1275
1276 % Write out the updated file
1277 fh = fopen(fname, 'w');
1278 if fh == -1
1279 error('Unable to open %s for writing.', fname);
1280 end
1281 try
1282 fwrite(fh, fstrm, 'char*1');
1283 catch ex
1284 fclose(fh);
1285 rethrow(ex);
1286 end
1287 fclose(fh);
1288end
1289
1290function set_tick_mode(Hlims, ax)
1291 % Set the tick mode of linear axes to manual
1292 % Leave log axes alone as these are tricky
1293 M = get(Hlims, [ax 'Scale']);
1294 if ~iscell(M)
1295 M = {M};
1296 end
1297 %idx = cellfun(@(c) strcmp(c, 'linear'), M);
1298 idx = find(strcmp(M,'linear'));
1299 %set(Hlims(idx), [ax 'TickMode'], 'manual'); % issue #187
1300 %set(Hlims(idx), [ax 'TickLabelMode'], 'manual'); % this hides exponent label in HG2!
1301 for idx2 = 1 : numel(idx)
1302 try
1303 % Fix for issue #187 - only set manual ticks when no exponent is present
1304 hAxes = Hlims(idx(idx2));
1305 props = {[ax 'TickMode'],'manual', [ax 'TickLabelMode'],'manual'};
1306 if isempty(strtrim(hAxes.([ax 'Ruler']).SecondaryLabel.String))
1307 set(hAxes, props{:}); % no exponent, so update moth ticks and tick labels to manual
1308 end
1309 catch % probably HG1
1310 set(hAxes, props{:}); % revert back to old behavior
1311 end
1312 end
1313end
1314
1315function change_rgb_to_cmyk(fname) % convert RGB => CMYK within an EPS file
1316 % Do post-processing on the eps file
1317 try
1318 % Read the EPS file into memory
1319 fstrm = read_write_entire_textfile(fname);
1320
1321 % Replace all gray-scale colors
1322 fstrm = regexprep(fstrm, '\n([\d.]+) +GC\n', '\n0 0 0 ${num2str(1-str2num($1))} CC\n');
1323
1324 % Replace all RGB colors
1325 fstrm = regexprep(fstrm, '\n[0.]+ +[0.]+ +[0.]+ +RC\n', '\n0 0 0 1 CC\n'); % pure black
1326 fstrm = regexprep(fstrm, '\n([\d.]+) +([\d.]+) +([\d.]+) +RC\n', '\n${sprintf(''%.4g '',[1-[str2num($1),str2num($2),str2num($3)]/max([str2num($1),str2num($2),str2num($3)]),1-max([str2num($1),str2num($2),str2num($3)])])} CC\n');
1327
1328 % Overwrite the file with the modified contents
1329 read_write_entire_textfile(fname, fstrm);
1330 catch
1331 % never mind - leave as is...
1332 end
1333end
Note: See TracBrowser for help on using the repository browser.