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

Last change on this file since 18904 was 18904, checked in by Mathieu Morlighem, 10 years ago

CHG: upgrading export_fig for hg2 support and matlab R2014b

File size: 29.8 KB
Line 
1%EXPORT_FIG Exports figures suitable for publication
2%
3% Examples:
4% im = export_fig
5% [im alpha] = export_fig
6% export_fig filename
7% export_fig filename -format1 -format2
8% export_fig ... -nocrop
9% export_fig ... -transparent
10% export_fig ... -native
11% export_fig ... -m<val>
12% export_fig ... -r<val>
13% export_fig ... -a<val>
14% export_fig ... -q<val>
15% export_fig ... -p<val>
16% export_fig ... -<renderer>
17% export_fig ... -<colorspace>
18% export_fig ... -append
19% export_fig ... -bookmark
20% export_fig(..., handle)
21%
22% This function saves a figure or single axes to one or more vector and/or
23% bitmap file formats, and/or outputs a rasterized version to the
24% workspace, with the following properties:
25% - Figure/axes reproduced as it appears on screen
26% - Cropped borders (optional)
27% - Embedded fonts (vector formats)
28% - Improved line and grid line styles
29% - Anti-aliased graphics (bitmap formats)
30% - Render images at native resolution (optional for bitmap formats)
31% - Transparent background supported (pdf, eps, png)
32% - Semi-transparent patch objects supported (png only)
33% - RGB, CMYK or grayscale output (CMYK only with pdf, eps, tiff)
34% - Variable image compression, including lossless (pdf, eps, jpg)
35% - Optionally append to file (pdf, tiff)
36% - Vector formats: pdf, eps
37% - Bitmap formats: png, tiff, jpg, bmp, export to workspace
38%
39% This function is especially suited to exporting figures for use in
40% publications and presentations, because of the high quality and
41% portability of media produced.
42%
43% Note that the background color and figure dimensions are reproduced
44% (the latter approximately, and ignoring cropping & magnification) in the
45% output file. For transparent background (and semi-transparent patch
46% objects), use the -transparent option or set the figure 'Color' property
47% to 'none'. To make axes transparent set the axes 'Color' property to
48% 'none'. Pdf, eps and png are the only file formats to support a
49% transparent background, whilst the png format alone supports transparency
50% of patch objects.
51%
52% The choice of renderer (opengl, zbuffer or painters) has a large impact
53% on the quality of output. Whilst the default value (opengl for bitmaps,
54% painters for vector formats) generally gives good results, if you aren't
55% satisfied then try another renderer. Notes: 1) For vector formats (eps,
56% pdf), only painters generates vector graphics. 2) For bitmaps, only
57% opengl can render transparent patch objects correctly. 3) For bitmaps,
58% only painters will correctly scale line dash and dot lengths when
59% magnifying or anti-aliasing. 4) Fonts may be substitued with Courier when
60% using painters.
61%
62% When exporting to vector format (pdf & eps) and bitmap format using the
63% painters renderer, this function requires that ghostscript is installed
64% on your system. You can download this from:
65% http://www.ghostscript.com
66% When exporting to eps it additionally requires pdftops, from the Xpdf
67% suite of functions. You can download this from:
68% http://www.foolabs.com/xpdf
69%
70%IN:
71% filename - string containing the name (optionally including full or
72% relative path) of the file the figure is to be saved as. If
73% a path is not specified, the figure is saved in the current
74% directory. If no name and no output arguments are specified,
75% the default name, 'export_fig_out', is used. If neither a
76% file extension nor a format are specified, a ".png" is added
77% and the figure saved in that format.
78% -format1, -format2, etc. - strings containing the extensions of the
79% file formats the figure is to be saved as.
80% Valid options are: '-pdf', '-eps', '-png',
81% '-tif', '-jpg' and '-bmp'. All combinations
82% of formats are valid.
83% -nocrop - option indicating that the borders of the output are not to
84% be cropped.
85% -transparent - option indicating that the figure background is to be
86% made transparent (png, pdf and eps output only).
87% -m<val> - option where val indicates the factor to magnify the
88% on-screen figure pixel dimensions by when generating bitmap
89% outputs. Default: '-m1'.
90% -r<val> - option val indicates the resolution (in pixels per inch) to
91% export bitmap and vector outputs at, keeping the dimensions
92% of the on-screen figure. Default: '-r864' (for vector output
93% only). Note that the -m option overides the -r option for
94% bitmap outputs only.
95% -native - option indicating that the output resolution (when outputting
96% a bitmap format) should be such that the vertical resolution
97% of the first suitable image found in the figure is at the
98% native resolution of that image. To specify a particular
99% image to use, give it the tag 'export_fig_native'. Notes:
100% This overrides any value set with the -m and -r options. It
101% also assumes that the image is displayed front-to-parallel
102% with the screen. The output resolution is approximate and
103% should not be relied upon. Anti-aliasing can have adverse
104% effects on image quality (disable with the -a1 option).
105% -a1, -a2, -a3, -a4 - option indicating the amount of anti-aliasing to
106% use for bitmap outputs. '-a1' means no anti-
107% aliasing; '-a4' is the maximum amount (default).
108% -<renderer> - option to force a particular renderer (painters, opengl
109% or zbuffer) to be used over the default: opengl for
110% bitmaps; painters for vector formats.
111% -<colorspace> - option indicating which colorspace color figures should
112% be saved in: RGB (default), CMYK or gray. CMYK is only
113% supported in pdf, eps and tiff output.
114% -q<val> - option to vary bitmap image quality (in pdf, eps and jpg
115% files only). Larger val, in the range 0-100, gives higher
116% quality/lower compression. val > 100 gives lossless
117% compression. Default: '-q95' for jpg, ghostscript prepress
118% default for pdf & eps. Note: lossless compression can
119% sometimes give a smaller file size than the default lossy
120% compression, depending on the type of images.
121% -p<val> - option to add a border of width val to eps and pdf files,
122% where val is in units of the intermediate eps file. Default:
123% 0 (i.e. no padding).
124% -append - option indicating that if the file (pdfs only) already
125% exists, the figure is to be appended as a new page, instead
126% of being overwritten (default).
127% -bookmark - option to indicate that a bookmark with the name of the
128% figure is to be created in the output file (pdf only).
129% handle - The handle of the figure, axes or uipanels (can be an array of
130% handles, but the objects must be in the same figure) to be
131% saved. Default: gcf.
132%
133%OUT:
134% im - MxNxC uint8 image array of the figure.
135% alpha - MxN single array of alphamatte values in range [0,1], for the
136% case when the background is transparent.
137%
138% Some helpful examples and tips can be found at:
139% https://github.com/ojwoodford/export_fig
140%
141% See also PRINT, SAVEAS.
142
143% Copyright (C) Oliver Woodford 2008-2014
144
145% The idea of using ghostscript is inspired by Peder Axensten's SAVEFIG
146% (fex id: 10889) which is itself inspired by EPS2PDF (fex id: 5782).
147% The idea for using pdftops came from the MATLAB newsgroup (id: 168171).
148% The idea of editing the EPS file to change line styles comes from Jiro
149% Doke's FIXPSLINESTYLE (fex id: 17928).
150% The idea of changing dash length with line width came from comments on
151% fex id: 5743, but the implementation is mine :)
152% The idea of anti-aliasing bitmaps came from Anders Brun's MYAA (fex id:
153% 20979).
154% The idea of appending figures in pdfs came from Matt C in comments on the
155% FEX (id: 23629)
156
157% Thanks to Roland Martin for pointing out the colour MATLAB
158% bug/feature with colorbar axes and transparent backgrounds.
159% Thanks also to Andrew Matthews for describing a bug to do with the figure
160% size changing in -nodisplay mode. I couldn't reproduce it, but included a
161% fix anyway.
162% Thanks to Tammy Threadgill for reporting a bug where an axes is not
163% isolated from gui objects.
164
165% 23/02/12: Ensure that axes limits don't change during printing
166% 14/03/12: Fix bug in fixing the axes limits (thanks to Tobias Lamour for
167% reporting it).
168% 02/05/12: Incorporate patch of Petr Nechaev (many thanks), enabling
169% bookmarking of figures in pdf files.
170% 09/05/12: Incorporate patch of Arcelia Arrieta (many thanks), to keep
171% tick marks fixed.
172% 12/12/12: Add support for isolating uipanels. Thanks to michael for
173% suggesting it.
174% 25/09/13: Add support for changing resolution in vector formats. Thanks
175% to Jan Jaap Meijer for suggesting it.
176% 07/05/14: Add support for '~' at start of path. Thanks to Sally Warner
177% for suggesting it.
178
179function [im, alpha] = export_fig(varargin)
180% Make sure the figure is rendered correctly _now_ so that properties like
181% axes limits are up-to-date.
182drawnow;
183% Parse the input arguments
184[fig, options] = parse_args(nargout, varargin{:});
185% Isolate the subplot, if it is one
186cls = all(ismember(get(fig, 'Type'), {'axes', 'uipanel'}));
187if cls
188 % Given handles of one or more axes, so isolate them from the rest
189 fig = isolate_axes(fig);
190else
191 % Check we have a figure
192 if ~isequal(get(fig, 'Type'), 'figure');
193 error('Handle must be that of a figure, axes or uipanel');
194 end
195 % Get the old InvertHardcopy mode
196 old_mode = get(fig, 'InvertHardcopy');
197end
198% Hack the font units where necessary (due to a font rendering bug in
199% print?). This may not work perfectly in all cases. Also it can change the
200% figure layout if reverted, so use a copy.
201magnify = options.magnify * options.aa_factor;
202if isbitmap(options) && magnify ~= 1
203 fontu = findobj(fig, 'FontUnits', 'normalized');
204 if ~isempty(fontu)
205 % Some normalized font units found
206 if ~cls
207 fig = copyfig(fig);
208 set(fig, 'Visible', 'off');
209 fontu = findobj(fig, 'FontUnits', 'normalized');
210 cls = true;
211 end
212 set(fontu, 'FontUnits', 'points');
213 end
214end
215% MATLAB "feature": axes limits and tick marks can change when printing
216Hlims = findall(fig, 'Type', 'axes');
217if ~cls
218 % Record the old axes limit and tick modes
219 Xlims = make_cell(get(Hlims, 'XLimMode'));
220 Ylims = make_cell(get(Hlims, 'YLimMode'));
221 Zlims = make_cell(get(Hlims, 'ZLimMode'));
222 Xtick = make_cell(get(Hlims, 'XTickMode'));
223 Ytick = make_cell(get(Hlims, 'YTickMode'));
224 Ztick = make_cell(get(Hlims, 'ZTickMode'));
225end
226% Set all axes limit and tick modes to manual, so the limits and ticks can't change
227set(Hlims, 'XLimMode', 'manual', 'YLimMode', 'manual', 'ZLimMode', 'manual');
228set_tick_mode(Hlims, 'X');
229set_tick_mode(Hlims, 'Y');
230set_tick_mode(Hlims, 'Z');
231% Set to print exactly what is there
232set(fig, 'InvertHardcopy', 'off');
233% Set the renderer
234switch options.renderer
235 case 1
236 renderer = '-opengl';
237 case 2
238 renderer = '-zbuffer';
239 case 3
240 renderer = '-painters';
241 otherwise
242 renderer = '-opengl'; % Default for bitmaps
243end
244% Do the bitmap formats first
245if isbitmap(options)
246 % Get the background colour
247 if options.transparent && (options.png || options.alpha)
248 % Get out an alpha channel
249 % MATLAB "feature": black colorbar axes can change to white and vice versa!
250 hCB = findobj(fig, 'Type', 'axes', 'Tag', 'Colorbar');
251 if isempty(hCB)
252 yCol = [];
253 xCol = [];
254 else
255 yCol = get(hCB, 'YColor');
256 xCol = get(hCB, 'XColor');
257 if iscell(yCol)
258 yCol = cell2mat(yCol);
259 xCol = cell2mat(xCol);
260 end
261 yCol = sum(yCol, 2);
262 xCol = sum(xCol, 2);
263 end
264 % MATLAB "feature": apparently figure size can change when changing
265 % colour in -nodisplay mode
266 pos = get(fig, 'Position');
267 % Set the background colour to black, and set size in case it was
268 % changed internally
269 tcol = get(fig, 'Color');
270 set(fig, 'Color', 'k', 'Position', pos);
271 % Correct the colorbar axes colours
272 set(hCB(yCol==0), 'YColor', [0 0 0]);
273 set(hCB(xCol==0), 'XColor', [0 0 0]);
274 % Print large version to array
275 B = print2array(fig, magnify, renderer);
276 % Downscale the image
277 B = downsize(single(B), options.aa_factor);
278 % Set background to white (and set size)
279 set(fig, 'Color', 'w', 'Position', pos);
280 % Correct the colorbar axes colours
281 set(hCB(yCol==3), 'YColor', [1 1 1]);
282 set(hCB(xCol==3), 'XColor', [1 1 1]);
283 % Print large version to array
284 A = print2array(fig, magnify, renderer);
285 % Downscale the image
286 A = downsize(single(A), options.aa_factor);
287 % Set the background colour (and size) back to normal
288 set(fig, 'Color', tcol, 'Position', pos);
289 % Compute the alpha map
290 alpha = round(sum(B - A, 3)) / (255 * 3) + 1;
291 A = alpha;
292 A(A==0) = 1;
293 A = B ./ A(:,:,[1 1 1]);
294 clear B
295 % Convert to greyscale
296 if options.colourspace == 2
297 A = rgb2grey(A);
298 end
299 A = uint8(A);
300 % Crop the background
301 if options.crop
302 [alpha, v] = crop_borders(alpha, 0, 1);
303 A = A(v(1):v(2),v(3):v(4),:);
304 end
305 if options.png
306 % Compute the resolution
307 res = options.magnify * get(0, 'ScreenPixelsPerInch') / 25.4e-3;
308 % Save the png
309 imwrite(A, [options.name '.png'], 'Alpha', double(alpha), 'ResolutionUnit', 'meter', 'XResolution', res, 'YResolution', res);
310 % Clear the png bit
311 options.png = false;
312 end
313 % Return only one channel for greyscale
314 if isbitmap(options)
315 A = check_greyscale(A);
316 end
317 if options.alpha
318 % Store the image
319 im = A;
320 % Clear the alpha bit
321 options.alpha = false;
322 end
323 % Get the non-alpha image
324 if isbitmap(options)
325 alph = alpha(:,:,ones(1, size(A, 3)));
326 A = uint8(single(A) .* alph + 255 * (1 - alph));
327 clear alph
328 end
329 if options.im
330 % Store the new image
331 im = A;
332 end
333 else
334 % Print large version to array
335 if options.transparent
336 % MATLAB "feature": apparently figure size can change when changing
337 % colour in -nodisplay mode
338 pos = get(fig, 'Position');
339 tcol = get(fig, 'Color');
340 set(fig, 'Color', 'w', 'Position', pos);
341 A = print2array(fig, magnify, renderer);
342 set(fig, 'Color', tcol, 'Position', pos);
343 tcol = 255;
344 else
345 [A, tcol] = print2array(fig, magnify, renderer);
346 end
347 % Crop the background
348 if options.crop
349 A = crop_borders(A, tcol, 1);
350 end
351 % Downscale the image
352 A = downsize(A, options.aa_factor);
353 if options.colourspace == 2
354 % Convert to greyscale
355 A = rgb2grey(A);
356 else
357 % Return only one channel for greyscale
358 A = check_greyscale(A);
359 end
360 % Outputs
361 if options.im
362 im = A;
363 end
364 if options.alpha
365 im = A;
366 alpha = zeros(size(A, 1), size(A, 2), 'single');
367 end
368 end
369 % Save the images
370 if options.png
371 res = options.magnify * get(0, 'ScreenPixelsPerInch') / 25.4e-3;
372 imwrite(A, [options.name '.png'], 'ResolutionUnit', 'meter', 'XResolution', res, 'YResolution', res);
373 end
374 if options.bmp
375 imwrite(A, [options.name '.bmp']);
376 end
377 % Save jpeg with given quality
378 if options.jpg
379 quality = options.quality;
380 if isempty(quality)
381 quality = 95;
382 end
383 if quality > 100
384 imwrite(A, [options.name '.jpg'], 'Mode', 'lossless');
385 else
386 imwrite(A, [options.name '.jpg'], 'Quality', quality);
387 end
388 end
389 % Save tif images in cmyk if wanted (and possible)
390 if options.tif
391 if options.colourspace == 1 && size(A, 3) == 3
392 A = double(255 - A);
393 K = min(A, [], 3);
394 K_ = 255 ./ max(255 - K, 1);
395 C = (A(:,:,1) - K) .* K_;
396 M = (A(:,:,2) - K) .* K_;
397 Y = (A(:,:,3) - K) .* K_;
398 A = uint8(cat(3, C, M, Y, K));
399 clear C M Y K K_
400 end
401 append_mode = {'overwrite', 'append'};
402 imwrite(A, [options.name '.tif'], 'Resolution', options.magnify*get(0, 'ScreenPixelsPerInch'), 'WriteMode', append_mode{options.append+1});
403 end
404end
405% Now do the vector formats
406if isvector(options)
407 % Set the default renderer to painters
408 if ~options.renderer
409 renderer = '-painters';
410 end
411 % Generate some filenames
412 tmp_nam = [tempname '.eps'];
413 if options.pdf
414 pdf_nam = [options.name '.pdf'];
415 else
416 pdf_nam = [tempname '.pdf'];
417 end
418 % Generate the options for print
419 p2eArgs = {renderer, sprintf('-r%d', options.resolution)};
420 if options.colourspace == 1
421 p2eArgs = [p2eArgs {'-cmyk'}];
422 end
423 if ~options.crop
424 p2eArgs = [p2eArgs {'-loose'}];
425 end
426 try
427 % Generate an eps
428 print2eps(tmp_nam, fig, options.bb_padding, p2eArgs{:});
429 % Remove the background, if desired
430 if options.transparent && ~isequal(get(fig, 'Color'), 'none')
431 eps_remove_background(tmp_nam, 1 + using_hg2(fig));
432 end
433 % Add a bookmark to the PDF if desired
434 if options.bookmark
435 fig_nam = get(fig, 'Name');
436 if isempty(fig_nam)
437 warning('export_fig:EmptyBookmark', 'Bookmark requested for figure with no name. Bookmark will be empty.');
438 end
439 add_bookmark(tmp_nam, fig_nam);
440 end
441 % Generate a pdf
442 eps2pdf(tmp_nam, pdf_nam, 1, options.append, options.colourspace==2, options.quality);
443 catch ex
444 % Delete the eps
445 delete(tmp_nam);
446 rethrow(ex);
447 end
448 % Delete the eps
449 delete(tmp_nam);
450 if options.eps
451 try
452 % Generate an eps from the pdf
453 pdf2eps(pdf_nam, [options.name '.eps']);
454 catch ex
455 if ~options.pdf
456 % Delete the pdf
457 delete(pdf_nam);
458 end
459 rethrow(ex);
460 end
461 if ~options.pdf
462 % Delete the pdf
463 delete(pdf_nam);
464 end
465 end
466end
467if cls
468 % Close the created figure
469 close(fig);
470else
471 % Reset the hardcopy mode
472 set(fig, 'InvertHardcopy', old_mode);
473 % Reset the axes limit and tick modes
474 for a = 1:numel(Hlims)
475 set(Hlims(a), 'XLimMode', Xlims{a}, 'YLimMode', Ylims{a}, 'ZLimMode', Zlims{a}, 'XTickMode', Xtick{a}, 'YTickMode', Ytick{a}, 'ZTickMode', Ztick{a});
476 end
477end
478end
479
480function [fig, options] = parse_args(nout, varargin)
481% Parse the input arguments
482% Set the defaults
483fig = get(0, 'CurrentFigure');
484options = struct('name', 'export_fig_out', ...
485 'crop', true, ...
486 'transparent', false, ...
487 'renderer', 0, ... % 0: default, 1: OpenGL, 2: ZBuffer, 3: Painters
488 'pdf', false, ...
489 'eps', false, ...
490 'png', false, ...
491 'tif', false, ...
492 'jpg', false, ...
493 'bmp', false, ...
494 'colourspace', 0, ... % 0: RGB/gray, 1: CMYK, 2: gray
495 'append', false, ...
496 'im', nout == 1, ...
497 'alpha', nout == 2, ...
498 'aa_factor', 0, ...
499 'bb_padding', 0, ...
500 'magnify', [], ...
501 'resolution', [], ...
502 'bookmark', false, ...
503 'quality', []);
504native = false; % Set resolution to native of an image
505
506% Go through the other arguments
507for a = 1:nargin-1
508 if all(ishandle(varargin{a}))
509 fig = varargin{a};
510 elseif ischar(varargin{a}) && ~isempty(varargin{a})
511 if varargin{a}(1) == '-'
512 switch lower(varargin{a}(2:end))
513 case 'nocrop'
514 options.crop = false;
515 case {'trans', 'transparent'}
516 options.transparent = true;
517 case 'opengl'
518 options.renderer = 1;
519 case 'zbuffer'
520 options.renderer = 2;
521 case 'painters'
522 options.renderer = 3;
523 case 'pdf'
524 options.pdf = true;
525 case 'eps'
526 options.eps = true;
527 case 'png'
528 options.png = true;
529 case {'tif', 'tiff'}
530 options.tif = true;
531 case {'jpg', 'jpeg'}
532 options.jpg = true;
533 case 'bmp'
534 options.bmp = true;
535 case 'rgb'
536 options.colourspace = 0;
537 case 'cmyk'
538 options.colourspace = 1;
539 case {'gray', 'grey'}
540 options.colourspace = 2;
541 case {'a1', 'a2', 'a3', 'a4'}
542 options.aa_factor = str2double(varargin{a}(3));
543 case 'append'
544 options.append = true;
545 case 'bookmark'
546 options.bookmark = true;
547 case 'native'
548 native = true;
549 otherwise
550 val = str2double(regexp(varargin{a}, '(?<=-(m|M|r|R|q|Q|p|P))-?\d*.?\d+', 'match'));
551 if ~isscalar(val)
552 error('option %s not recognised', varargin{a});
553 end
554 switch lower(varargin{a}(2))
555 case 'm'
556 options.magnify = val;
557 case 'r'
558 options.resolution = val;
559 case 'q'
560 options.quality = max(val, 0);
561 case 'p'
562 options.bb_padding = val;
563 end
564 end
565 else
566 [p, options.name, ext] = fileparts(varargin{a});
567 if ~isempty(p)
568 options.name = [p filesep options.name];
569 end
570 switch lower(ext)
571 case {'.tif', '.tiff'}
572 options.tif = true;
573 case {'.jpg', '.jpeg'}
574 options.jpg = true;
575 case '.png'
576 options.png = true;
577 case '.bmp'
578 options.bmp = true;
579 case '.eps'
580 options.eps = true;
581 case '.pdf'
582 options.pdf = true;
583 otherwise
584 options.name = varargin{a};
585 end
586 end
587 end
588end
589
590% Set default anti-aliasing now we know the renderer
591if options.aa_factor == 0
592 options.aa_factor = 1 + 2 * (~(using_hg2(fig) && strcmp(get(ancestor(fig, 'figure'), 'GraphicsSmoothing'), 'on')) | (options.renderer == 3));
593end
594
595% Convert user dir '~' to full path
596if numel(options.name) > 2 && options.name(1) == '~' && (options.name(2) == '/' || options.name(2) == '\')
597 options.name = fullfile(char(java.lang.System.getProperty('user.home')), options.name(2:end));
598end
599
600% Compute the magnification and resolution
601if isempty(options.magnify)
602 if isempty(options.resolution)
603 options.magnify = 1;
604 options.resolution = 864;
605 else
606 options.magnify = options.resolution ./ get(0, 'ScreenPixelsPerInch');
607 end
608elseif isempty(options.resolution)
609 options.resolution = 864;
610end
611
612% Check we have a figure handle
613if isempty(fig)
614 error('No figure found');
615end
616
617% Set the default format
618if ~isvector(options) && ~isbitmap(options)
619 options.png = true;
620end
621
622% Check whether transparent background is wanted (old way)
623if isequal(get(ancestor(fig(1), 'figure'), 'Color'), 'none')
624 options.transparent = true;
625end
626
627% If requested, set the resolution to the native vertical resolution of the
628% first suitable image found
629if native && isbitmap(options)
630 % Find a suitable image
631 list = findobj(fig, 'Type', 'image', 'Tag', 'export_fig_native');
632 if isempty(list)
633 list = findobj(fig, 'Type', 'image', 'Visible', 'on');
634 end
635 for hIm = list(:)'
636 % Check height is >= 2
637 height = size(get(hIm, 'CData'), 1);
638 if height < 2
639 continue
640 end
641 % Account for the image filling only part of the axes, or vice
642 % versa
643 yl = get(hIm, 'YData');
644 if isscalar(yl)
645 yl = [yl(1)-0.5 yl(1)+height+0.5];
646 else
647 if ~diff(yl)
648 continue
649 end
650 yl = yl + [-0.5 0.5] * (diff(yl) / (height - 1));
651 end
652 hAx = get(hIm, 'Parent');
653 yl2 = get(hAx, 'YLim');
654 % Find the pixel height of the axes
655 oldUnits = get(hAx, 'Units');
656 set(hAx, 'Units', 'pixels');
657 pos = get(hAx, 'Position');
658 set(hAx, 'Units', oldUnits);
659 if ~pos(4)
660 continue
661 end
662 % Found a suitable image
663 % Account for stretch-to-fill being disabled
664 pbar = get(hAx, 'PlotBoxAspectRatio');
665 pos = min(pos(4), pbar(2)*pos(3)/pbar(1));
666 % Set the magnification to give native resolution
667 options.magnify = (height * diff(yl2)) / (pos * diff(yl));
668 break
669 end
670end
671end
672
673function A = downsize(A, factor)
674% Downsample an image
675if factor == 1
676 % Nothing to do
677 return
678end
679try
680 % Faster, but requires image processing toolbox
681 A = imresize(A, 1/factor, 'bilinear');
682catch
683 % No image processing toolbox - resize manually
684 % Lowpass filter - use Gaussian as is separable, so faster
685 % Compute the 1d Gaussian filter
686 filt = (-factor-1:factor+1) / (factor * 0.6);
687 filt = exp(-filt .* filt);
688 % Normalize the filter
689 filt = single(filt / sum(filt));
690 % Filter the image
691 padding = floor(numel(filt) / 2);
692 for a = 1:size(A, 3)
693 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');
694 end
695 % Subsample
696 A = A(1+floor(mod(end-1, factor)/2):factor:end,1+floor(mod(end-1, factor)/2):factor:end,:);
697end
698end
699
700function A = rgb2grey(A)
701A = cast(reshape(reshape(single(A), [], 3) * single([0.299; 0.587; 0.114]), size(A, 1), size(A, 2)), class(A));
702end
703
704function A = check_greyscale(A)
705% Check if the image is greyscale
706if size(A, 3) == 3 && ...
707 all(reshape(A(:,:,1) == A(:,:,2), [], 1)) && ...
708 all(reshape(A(:,:,2) == A(:,:,3), [], 1))
709 A = A(:,:,1); % Save only one channel for 8-bit output
710end
711end
712
713function eps_remove_background(fname, count)
714% Remove the background of an eps file
715% Open the file
716fh = fopen(fname, 'r+');
717if fh == -1
718 error('Not able to open file %s.', fname);
719end
720% Read the file line by line
721while count
722 % Get the next line
723 l = fgets(fh);
724 if isequal(l, -1)
725 break; % Quit, no rectangle found
726 end
727 % Check if the line contains the background rectangle
728 if isequal(regexp(l, ' *0 +0 +\d+ +\d+ +r[fe] *[\n\r]+', 'start'), 1)
729 % Set the line to whitespace and quit
730 l(1:regexp(l, '[\n\r]', 'start', 'once')-1) = ' ';
731 fseek(fh, -numel(l), 0);
732 fprintf(fh, l);
733 % Reduce the count
734 count = count - 1;
735 end
736end
737% Close the file
738fclose(fh);
739end
740
741function b = isvector(options)
742b = options.pdf || options.eps;
743end
744
745function b = isbitmap(options)
746b = options.png || options.tif || options.jpg || options.bmp || options.im || options.alpha;
747end
748
749% Helper function
750function A = make_cell(A)
751if ~iscell(A)
752 A = {A};
753end
754end
755
756function add_bookmark(fname, bookmark_text)
757% Adds a bookmark to the temporary EPS file after %%EndPageSetup
758% Read in the file
759fh = fopen(fname, 'r');
760if fh == -1
761 error('File %s not found.', fname);
762end
763try
764 fstrm = fread(fh, '*char')';
765catch ex
766 fclose(fh);
767 rethrow(ex);
768end
769fclose(fh);
770
771% Include standard pdfmark prolog to maximize compatibility
772fstrm = strrep(fstrm, '%%BeginProlog', sprintf('%%%%BeginProlog\n/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse'));
773% Add page bookmark
774fstrm = strrep(fstrm, '%%EndPageSetup', sprintf('%%%%EndPageSetup\n[ /Title (%s) /OUT pdfmark',bookmark_text));
775
776% Write out the updated file
777fh = fopen(fname, 'w');
778if fh == -1
779 error('Unable to open %s for writing.', fname);
780end
781try
782 fwrite(fh, fstrm, 'char*1');
783catch ex
784 fclose(fh);
785 rethrow(ex);
786end
787fclose(fh);
788end
789
790function set_tick_mode(Hlims, ax)
791% Set the tick mode of linear axes to manual
792% Leave log axes alone as these are tricky
793M = get(Hlims, [ax 'Scale']);
794if ~iscell(M)
795 M = {M};
796end
797M = cellfun(@(c) strcmp(c, 'linear'), M);
798set(Hlims(M), [ax 'TickMode'], 'manual');
799end
Note: See TracBrowser for help on using the repository browser.