| 1 | function [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
 | 
|---|
| 863 | end
 | 
|---|
| 864 | 
 | 
|---|
| 865 | function 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',   {{}});
 | 
|---|
| 895 | end
 | 
|---|
| 896 | 
 | 
|---|
| 897 | function [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
 | 
|---|
| 1171 | end
 | 
|---|
| 1172 | 
 | 
|---|
| 1173 | function 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
 | 
|---|
| 1198 | end
 | 
|---|
| 1199 | 
 | 
|---|
| 1200 | function 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>
 | 
|---|
| 1202 | end
 | 
|---|
| 1203 | 
 | 
|---|
| 1204 | function 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
 | 
|---|
| 1211 | end
 | 
|---|
| 1212 | 
 | 
|---|
| 1213 | function 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);
 | 
|---|
| 1239 | end
 | 
|---|
| 1240 | 
 | 
|---|
| 1241 | function b = isvector(options)
 | 
|---|
| 1242 |     b = options.pdf || options.eps;
 | 
|---|
| 1243 | end
 | 
|---|
| 1244 | 
 | 
|---|
| 1245 | function b = isbitmap(options)
 | 
|---|
| 1246 |     b = options.png || options.tif || options.jpg || options.bmp || options.im || options.alpha;
 | 
|---|
| 1247 | end
 | 
|---|
| 1248 | 
 | 
|---|
| 1249 | % Helper function
 | 
|---|
| 1250 | function A = make_cell(A)
 | 
|---|
| 1251 |     if ~iscell(A)
 | 
|---|
| 1252 |         A = {A};
 | 
|---|
| 1253 |     end
 | 
|---|
| 1254 | end
 | 
|---|
| 1255 | 
 | 
|---|
| 1256 | function 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);
 | 
|---|
| 1288 | end
 | 
|---|
| 1289 | 
 | 
|---|
| 1290 | function 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
 | 
|---|
| 1313 | end
 | 
|---|
| 1314 | 
 | 
|---|
| 1315 | function 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
 | 
|---|
| 1333 | end
 | 
|---|