Changeset 24460


Ignore:
Timestamp:
12/08/19 19:39:55 (5 years ago)
Author:
Mathieu Morlighem
Message:

CHG: upgrading exprt_fig

Location:
issm/trunk-jpl/externalpackages/export_fig
Files:
2 deleted
11 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified issm/trunk-jpl/externalpackages/export_fig/README.md

    r21315 r24460  
    1010
    1111Perhaps the best way to demonstrate what export_fig can do is with some examples.
     12
     13*Note: `export_fig` currently supports only figures created with the `figure` function, or GUIDE. Figures created using `uifigure` or AppDesigner are only partially supported. See issues [#287](https://github.com/altmany/export_fig/issues/287), [#261](https://github.com/altmany/export_fig/issues/261) for details.*
    1214 
    1315### Examples
     
    169171```
    170172
    171 **Specifying the figure/axes** - if you have mutiple figures open you can specify which figure to export using its handle: 
     173**Specifying the figure/axes** - if you have multiple figures open you can specify which figure to export using its handle: 
    172174```Matlab
    173175export_fig(figure_handle, filename);
     
    212214**Smoothed/interpolated images in output PDF** - if you produce a PDF using export_fig and images in the PDF look overly smoothed or interpolated, this is because the software you are using to view the PDF is smoothing or interpolating the image data. The image is not smoothed in the PDF file itself. If the software has an option to disable this feature, you should select it. Alternatively, use another PDF viewer that doesn't exhibit this problem. 
    213215 
    214 **Locating Ghostscript/pdftops** - You may find a dialogue box appears when using export_fig, asking you to locate either [Ghostscript](http://www.ghostscript.com) or [pdftops](http://www.foolabs.com/xpdf). These are separate applications which export_fig requires to perform certain functions. If such a dialogue appears it is because export_fig can't find the application automatically. This is because you either haven't installed it, or it isn't in the normal place. Make sure you install the applications correctly first. They can be downloaded from the following places: 
     216**Locating Ghostscript/pdftops** - You may find a dialogue box appears when using export_fig, asking you to locate either [Ghostscript](http://www.ghostscript.com) or [pdftops (part of the Xpdf package)](http://www.xpdfreader.com). These are separate applications which export_fig requires to perform certain functions. If such a dialogue appears it is because export_fig can't find the application automatically. This is because you either haven't installed it, or it isn't in the normal place. Make sure you install the applications correctly first. They can be downloaded from the following places: 
    215217 1. Ghostscript:     [www.ghostscript.com](http://www.ghostscript.com)
    216  2. pdftops (install the Xpdf package): [www.foolabs.com/xpdf](http://www.foolabs.com/xpdf)
     218 2. pdftops (install the Xpdf package): [www.xpdfreader.com](http://www.xpdfreader.com)
    217219
    218220If you choose to install them in a non-default location then point export_fig
  • TabularUnified issm/trunk-jpl/externalpackages/export_fig/append_pdfs.m

    r21315 r24460  
    3535% 26/02/15: If temp dir is not writable, use the output folder for temp
    3636%           files when appending (Javier Paredes); sanity check of inputs
     37% 24/01/18: Fixed error in case of existing output file (append mode)
     38% 24/01/18: Fixed issue #213: non-ASCII characters in folder names on Windows
     39% 06/12/18: Avoid an "invalid escape-char" warning upon error
    3740
    3841function append_pdfs(varargin)
    3942
    40 if nargin < 2,  return;  end  % sanity check
     43    if nargin < 2,  return;  end  % sanity check
    4144
    42 % Are we appending or creating a new file
    43 append = exist(varargin{1}, 'file') == 2;
    44 output = [tempname '.pdf'];
    45 try
    46     % Ensure that the temp dir is writable (Javier Paredes 26/2/15)
    47     fid = fopen(output,'w');
    48     fwrite(fid,1);
    49     fclose(fid);
    50     delete(output);
    51     isTempDirOk = true;
    52 catch
    53     % Temp dir is not writable, so use the output folder
    54     [dummy,fname,fext] = fileparts(output); %#ok<ASGLU>
    55     fpath = fileparts(varargin{1});
    56     output = fullfile(fpath,[fname fext]);
    57     isTempDirOk = false;
     45    % Are we appending or creating a new file
     46    append = exist(varargin{1}, 'file') == 2;
     47    output = [tempname '.pdf'];
     48    try
     49        % Ensure that the temp dir is writable (Javier Paredes 26/2/15)
     50        fid = fopen(output,'w');
     51        fwrite(fid,1);
     52        fclose(fid);
     53        delete(output);
     54        isTempDirOk = true;
     55    catch
     56        % Temp dir is not writable, so use the output folder
     57        [dummy,fname,fext] = fileparts(output); %#ok<ASGLU>
     58        fpath = fileparts(varargin{1});
     59        output = fullfile(fpath,[fname fext]);
     60        isTempDirOk = false;
     61    end
     62    if ~append
     63        output = varargin{1};
     64        varargin = varargin(2:end);
     65    end
     66
     67    % Create the command file
     68    if isTempDirOk
     69        cmdfile = [tempname '.txt'];
     70    else
     71        cmdfile = fullfile(fpath,[fname '.txt']);
     72    end
     73    prepareCmdFile(cmdfile, output, varargin{:});
     74
     75    % Call ghostscript
     76    [status, errMsg] = ghostscript(['@"' cmdfile '"']);
     77
     78    % Check for ghostscript execution errors
     79    if status && ~isempty(strfind(errMsg,'undefinedfile')) && ispc %#ok<STREMP>
     80        % Fix issue #213: non-ASCII characters in folder names on Windows
     81        for fileIdx = 2 : numel(varargin)
     82            [fpath,fname,fext] = fileparts(varargin{fileIdx});
     83            varargin{fileIdx} = fullfile(normalizePath(fpath),[fname fext]);
     84        end
     85        % Rerun ghostscript with the normalized folder names
     86        prepareCmdFile(cmdfile, output, varargin{:});
     87        [status, errMsg] = ghostscript(['@"' cmdfile '"']);
     88    end
     89
     90    % Delete the command file
     91    delete(cmdfile);
     92
     93    % Check for ghostscript execution errors
     94    if status
     95        errMsg = strrep(errMsg,'\','\\');  % Avoid an "invalid escape-char" warning
     96        error('YMA:export_fig:append_pdf',errMsg);
     97    end
     98
     99    % Rename the file if needed
     100    if append
     101        movefile(output, varargin{1}, 'f');
     102    end
    58103end
    59 if ~append
    60     output = varargin{1};
    61     varargin = varargin(2:end);
     104
     105% Prepare a text file with ghostscript directives
     106function prepareCmdFile(cmdfile, output, varargin)
     107    fh = fopen(cmdfile, 'w');
     108    fprintf(fh, '-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sOutputFile="%s" -f', output);
     109    fprintf(fh, ' "%s"', varargin{:});
     110    fclose(fh);
    62111end
    63 % Create the command file
    64 if isTempDirOk
    65     cmdfile = [tempname '.txt'];
    66 else
    67     cmdfile = fullfile(fpath,[fname '.txt']);
     112
     113% Convert long/non-ASCII folder names into their short ASCII equivalents
     114function pathStr = normalizePath(pathStr)
     115    [fpath,fname,fext] = fileparts(pathStr);
     116    if isempty(fpath) || strcmpi(fpath,pathStr), return, end
     117    dirOutput = evalc(['system(''dir /X /AD "' pathStr '*"'')']);
     118    shortName = strtrim(regexprep(dirOutput,{'.*> *',[fname fext '.*']},''));
     119    if isempty(shortName)
     120        shortName = [fname fext];
     121    end
     122    fpath = normalizePath(fpath);  %recursive until entire fpath is processed
     123    pathStr = fullfile(fpath, shortName);
    68124end
    69 fh = fopen(cmdfile, 'w');
    70 fprintf(fh, '-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sOutputFile="%s" -f', output);
    71 fprintf(fh, ' "%s"', varargin{:});
    72 fclose(fh);
    73 % Call ghostscript
    74 ghostscript(['@"' cmdfile '"']);
    75 % Delete the command file
    76 delete(cmdfile);
    77 % Rename the file if needed
    78 if append
    79     movefile(output, varargin{1});
    80 end
    81 end
  • TabularUnified issm/trunk-jpl/externalpackages/export_fig/copyfig.m

    r21315 r24460  
    1414%    fh_new - The handle of the created figure.
    1515
    16 % Copyright (C) Oliver Woodford 2012
     16% Copyright (C) Oliver Woodford 2012, Yair Altman 2015
    1717
    1818% 26/02/15: If temp dir is not writable, use the dest folder for temp
    1919%           destination files (Javier Paredes)
    2020% 15/04/15: Suppress warnings during copyobj (Dun Kirk comment on FEX page 2013-10-02)
     21% 09/09/18: Fix issue #252: Workaround for cases where copyobj() fails for any reason
    2122
    2223    % Set the default
     
    2526    end
    2627    % Is there a legend?
    27     if isempty(findall(fh, 'Type', 'axes', 'Tag', 'legend'))
     28    useCopyobj = isempty(findall(fh, 'Type', 'axes', 'Tag', 'legend'));
     29    if useCopyobj
    2830        % Safe to copy using copyobj
    29         oldWarn = warning('off'); %#ok<WNOFF>  %Suppress warnings during copyobj (Dun Kirk comment on FEX page 2013-10-02)
    30         fh = copyobj(fh, 0);
     31        oldWarn = warning('off'); %Suppress warnings during copyobj (Dun Kirk comment on FEX page 2013-10-02)
     32        try
     33            fh = copyobj(fh, 0);
     34        catch
     35            % Fix issue #252: Workaround for cases where copyobj() fails for any reason
     36            useCopyobj = false;  % if copyobj() croaks, use file save/load below
     37        end
    3138        warning(oldWarn);
    32     else
     39    end
     40    if ~useCopyobj
    3341        % copyobj will change the figure, so save and then load it instead
    3442        tmp_nam = [tempname '.fig'];
  • TabularUnified issm/trunk-jpl/externalpackages/export_fig/eps2pdf.m

    r21671 r24460  
    4242% http://www.mathworks.com/matlabcentral/fileexchange/23629
    4343
    44 % Thank you to Fabio Viola for pointing out compression artifacts, leading
    45 % to the quality setting.
    46 % Thank you to Scott for pointing out the subsampling of very small images,
    47 % which was fixed for lossless compression settings.
    48 
    49 % 9/12/2011 Pass font path to ghostscript.
    50 % 26/02/15: If temp dir is not writable, use the dest folder for temp
    51 %           destination files (Javier Paredes)
     44% Thank you Fabio Viola for pointing out compression artifacts, leading to the quality setting.
     45% Thank you Scott for pointing out the subsampling of very small images, which was fixed for lossless compression settings.
     46
     47% 09/12/11: Pass font path to ghostscript
     48% 26/02/15: If temp dir is not writable, use the dest folder for temp destination files (Javier Paredes)
    5249% 28/02/15: Enable users to specify optional ghostscript options (issue #36)
    5350% 01/03/15: Upon GS error, retry without the -sFONTPATH= option (this might solve
     
    5754% 22/02/16: Bug fix from latest release of this file (workaround for issue #41)
    5855% 20/03/17: Added informational message in case of GS croak (issue #186)
     56% 16/01/18: Improved appending of multiple EPS files into single PDF (issue #233; thanks @shartjen)
     57% 18/10/19: Workaround for GS 9.51+ .setpdfwrite removal problem (issue #285)
     58% 18/10/19: Warn when ignoring GS fontpath or quality options; clarified error messages
    5959
    6060    % Intialise the options string for ghostscript
    6161    options = ['-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sOutputFile="' dest '"'];
     62
    6263    % Set crop option
    6364    if nargin < 3 || crop
    6465        options = [options ' -dEPSCrop'];
    6566    end
     67
    6668    % Set the font path
    6769    fp = font_path();
     
    6971        options = [options ' -sFONTPATH="' fp '"'];
    7072    end
     73
    7174    % Set the grayscale option
    7275    if nargin > 4 && gray
    7376        options = [options ' -sColorConversionStrategy=Gray -dProcessColorModel=/DeviceGray'];
    7477    end
     78
    7579    % Set the bitmap quality
     80    qualityOptions = '';
    7681    if nargin > 5 && ~isempty(quality)
    77         options = [options ' -dAutoFilterColorImages=false -dAutoFilterGrayImages=false'];
     82        qualityOptions = ' -dAutoFilterColorImages=false -dAutoFilterGrayImages=false';
    7883        if quality > 100
    79             options = [options ' -dColorImageFilter=/FlateEncode -dGrayImageFilter=/FlateEncode -c ".setpdfwrite << /ColorImageDownsampleThreshold 10 /GrayImageDownsampleThreshold 10 >> setdistillerparams"'];
     84            qualityOptions = [qualityOptions ' -dColorImageFilter=/FlateEncode -dGrayImageFilter=/FlateEncode'];
     85            qualityOptions = [qualityOptions ' -c ".setpdfwrite << /ColorImageDownsampleThreshold 10 /GrayImageDownsampleThreshold 10 >> setdistillerparams"'];
    8086        else
    81             options = [options ' -dColorImageFilter=/DCTEncode -dGrayImageFilter=/DCTEncode'];
     87            qualityOptions = [qualityOptions ' -dColorImageFilter=/DCTEncode -dGrayImageFilter=/DCTEncode'];
    8288            v = 1 + (quality < 80);
    8389            quality = 1 - quality / 100;
    8490            s = sprintf('<< /QFactor %.2f /Blend 1 /HSample [%d 1 1 %d] /VSample [%d 1 1 %d] >>', quality, v, v, v, v);
    85             options = sprintf('%s -c ".setpdfwrite << /ColorImageDict %s /GrayImageDict %s >> setdistillerparams"', options, s, s);
    86         end
    87     end
     91            qualityOptions = [qualityOptions ' -c ".setpdfwrite << /ColorImageDict ' s ' /GrayImageDict ' s ' >> setdistillerparams"'];
     92        end
     93        options = [options qualityOptions];
     94    end
     95
    8896    % Enable users to specify optional ghostscript options (issue #36)
    8997    if nargin > 6 && ~isempty(gs_options)
     
    97105        options = [options gs_options];
    98106    end
     107
    99108    % Check if the output file exists
    100109    if nargin > 3 && append && exist(dest, 'file') == 2
    101110        % File exists - append current figure to the end
    102         tmp_nam = tempname;
     111        tmp_nam = [tempname '.pdf'];
     112        [fpath,fname,fext] = fileparts(tmp_nam);
    103113        try
    104114            % Ensure that the temp dir is writable (Javier Paredes 26/2/15)
     
    109119        catch
    110120            % Temp dir is not writable, so use the dest folder
    111             [dummy,fname,fext] = fileparts(tmp_nam); %#ok<ASGLU>
    112121            fpath = fileparts(dest);
    113122            tmp_nam = fullfile(fpath,[fname fext]);
    114123        end
    115         % Copy the file
     124        % Copy the existing (dest) pdf file to temporary folder
    116125        copyfile(dest, tmp_nam);
    117         % Add the output file names
    118         options = [options ' -f "' tmp_nam '" "' source '"'];
     126        % Produce an interim pdf of the source eps, rather than adding the eps directly (issue #233)
     127        ghostscript([options ' -f "' source '"']);
     128        [~,fname] = fileparts(tempname);
     129        tmp_nam2 = fullfile(fpath,[fname fext]); % ensure using a writable folder (not necessarily tempdir)
     130        copyfile(dest, tmp_nam2);
     131        % Add the existing pdf and interim pdf as inputs to ghostscript
     132        %options = [options ' -f "' tmp_nam '" "' source '"'];  % append the source eps to dest pdf
     133        options = [options ' -f "' tmp_nam '" "' tmp_nam2 '"']; % append the interim pdf to dest pdf
    119134        try
    120135            % Convert to pdf using ghostscript
    121136            [status, message] = ghostscript(options);
    122137        catch me
    123             % Delete the intermediate file
     138            % Delete the intermediate files and rethrow the error
    124139            delete(tmp_nam);
     140            delete(tmp_nam2);
    125141            rethrow(me);
    126142        end
    127         % Delete the intermediate file
     143        % Delete the intermediate (temporary) files
    128144        delete(tmp_nam);
     145        delete(tmp_nam2);
    129146    else
    130147        % File doesn't exist or should be over-written
    131         % Add the output file names
     148        % Add the source eps file as input to ghostscript
    132149        options = [options ' -f "' source '"'];
    133150        % Convert to pdf using ghostscript
    134151        [status, message] = ghostscript(options);
    135152    end
     153
    136154    % Check for error
    137155    if status
     
    142160            options = regexprep(options, ' -sFONTPATH=[^ ]+ ',' ');
    143161            status = ghostscript(options);
    144             if ~status, return; end  % hurray! (no error)
    145         end
     162            if ~status % hurray! (no error)
     163                warning('export_fig:GS:fontpath','Export_fig font option is ignored - not supported by your Ghostscript version')
     164                return
     165            end
     166        end
     167
     168        % Retry without quality options (may solve problems with GS 9.51+, issue #285)
     169        if ~isempty(qualityOptions)
     170            options = strrep(orig_options, qualityOptions, '');
     171            [status, message] = ghostscript(options);
     172            if ~status % hurray! (no error)
     173                warning('export_fig:GS:quality','Export_fig quality option is ignored - not supported by your Ghostscript version')
     174                return
     175            end
     176        end
     177
    146178        % Report error
    147179        if isempty(message)
    148             error('Unable to generate pdf. Check destination directory is writable.');
    149         elseif ~isempty(strfind(message,'/typecheck in /findfont'))
     180            error('Unable to generate pdf. Ensure that the destination folder is writable.');
     181        elseif ~isempty(strfind(message,'/typecheck in /findfont')) %#ok<STREMP>
    150182            % Suggest a workaround for issue #41 (missing font path)
    151183            font_name = strtrim(regexprep(message,'.*Operand stack:\s*(.*)\s*Execution.*','$1'));
     
    158190            fprintf(2, '\nGhostscript error: perhaps %s is open by another application\n', dest);
    159191            if ~isempty(gs_options)
    160                 fprintf(2, '  or maybe the%s option(s) are not accepted by your GS version\n', gs_options);
     192                fprintf(2, '  or maybe your Ghostscript version does not accept the extra "%s" option(s) that you requested\n', gs_options);
    161193            end
    162194            fprintf(2, '  or maybe you have another gs executable in your system''s path\n');
  • TabularUnified issm/trunk-jpl/externalpackages/export_fig/export_fig.m

    r21671 r24460  
    1 function [imageData, alpha] = export_fig(varargin)
     1function [imageData, alpha] = export_fig(varargin) %#ok<*STRCL1>
    22%EXPORT_FIG  Exports figures in a publication-quality format
    33%
     
    2525%   export_fig ... -update
    2626%   export_fig ... -nofontswap
     27%   export_fig ... -font_space <char>
    2728%   export_fig ... -linecaps
     29%   export_fig ... -noinvert
     30%   export_fig ... -preserve_size
     31%   export_fig ... -options <optionsStruct>
    2832%   export_fig(..., handle)
    2933%
     
    3842%   - Render images at native resolution (optional for bitmap formats)
    3943%   - 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)
     44%   - Semi-transparent patch objects supported (png, tif)
     45%   - RGB, CMYK or grayscale output (CMYK only with pdf, eps, tif)
    4246%   - 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%   - Optional rounded line-caps (pdf, eps)
     48%   - Optionally append to file (pdf, tif)
     49%   - Vector formats: pdf, eps, svg
     50%   - Bitmap formats: png, tif, jpg, bmp, export to workspace
    4751%
    4852% This function is especially suited to exporting figures for use in
     
    5862% background; only TIF & PNG formats support transparency of patch objects.
    5963%
    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.
     64% The choice of renderer (opengl/zbuffer/painters) has a large impact on the
     65% output quality. The default value (opengl for bitmaps, painters for vector
     66% formats) generally gives good results, but if you aren't satisfied
     67% then try another renderer.  Notes:
     68%   1) For vector formats (EPS,PDF), only painters generates vector graphics
     69%   2) For bitmap formats, only opengl correctly renders transparent patches
     70%   3) For bitmap formats, only painters correctly scales line dash and dot
     71%      lengths when magnifying or anti-aliasing
     72%   4) Fonts may be substitued with Courier when using painters
    6973%
    7074% When exporting to vector format (PDF & EPS) and bitmap format using the
     
    7276% on your system. You can download this from:
    7377%   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
     78% When exporting to EPS it additionally requires pdftops, from the Xpdf
     79% suite of functions. You can download this from: http://xpdfreader.com
     80%
     81% SVG output uses the fig2svg (https://github.com/kupiqu/fig2svg) or plot2svg
     82% (https://github.com/jschwizer99/plot2svg) utilities, or Matlab's built-in
     83% SVG export if neither of these utilities are available on Matlab's path.
     84% Note: cropping/padding are not supported in export_fig's SVG output.
    7785%
    7886% Inputs:
    7987%   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.
     88%             relative path) of the file the figure is to be saved as. If
     89%             a path is not specified, the figure is saved in the current
     90%             directory. If no name and no output arguments are specified,
     91%             the default name, 'export_fig_out', is used. If neither a
     92%             file extension nor a format are specified, a ".png" is added
     93%             and the figure saved in that format.
     94%   -<format> - string(s) containing the output file extension(s). Options:
     95%             '-pdf', '-eps', '-svg', '-png', '-tif', '-jpg' and '-bmp'.
     96%             Multiple formats can be specified, without restriction.
     97%             For example: export_fig('-jpg', '-pdf', '-png', ...)
     98%             Either '-tif','-tiff' can be specified, and either '-jpg','-jpeg'.
     99%   -nocrop - option indicating that empty margins should not be cropped.
    93100%   -c[<val>,<val>,<val>,<val>] - option indicating crop amounts. Must be
    94101%             a 4-element vector of numeric values: [top,right,bottom,left]
    95102%             where NaN/Inf indicate auto-cropping, 0 means no cropping,
    96103%             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).
     104%   -transparent - option indicating that the figure background is to be made
     105%             transparent (PNG,PDF,TIF,EPS formats only). Implies -noinvert.
    99106%   -m<val> - option where val indicates the factor to magnify the
    100107%             on-screen figure pixel dimensions by when generating bitmap
     
    116123%             effects on image quality (disable with the -a1 option).
    117124%   -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).
     125%             use for bitmap outputs. '-a1' means no anti-aliasing;
     126%             '-a4' is the maximum amount (default).
    120127%   -<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.
     128%             zbuffer). Default value: opengl for bitmap formats or
     129%             figures with patches and/or transparent annotations;
     130%             painters for vector formats without patches/transparencies.
    124131%   -<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.
     132%             be saved in: RGB (default), CMYK or gray. Usage example: '-gray'.
     133%             Note: CMYK is only supported in PDF, EPS and TIF formats.
     134%   -q<val> - option to vary bitmap image quality (PDF, EPS, JPG formats only).
     135%             A larger val, in the range 0-100, produces higher quality and
     136%             lower compression. val > 100 results in lossless compression.
     137%             Default: '-q95' for JPG, ghostscript prepress default for PDF,EPS.
     138%             Note: lossless compression can sometimes give a smaller file size
     139%             than the default lossy compression, depending on the image type.
    134140%   -p<val> - option to pad a border of width val to exported files, where
    135141%             val is either a relative size with respect to cropped image
     
    139145%             If used, the -nocrop flag will be ignored, i.e. the image will
    140146%             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).
     147%   -append - option indicating that if the file already exists the figure is to
     148%             be appended as a new page, instead of being overwritten (default).
     149%             PDF & TIF output formats only.
    144150%   -bookmark - option to indicate that a bookmark with the name of the
    145 %               figure is to be created in the output file (pdf only).
     151%             figure is to be created in the output file (PDF format only).
    146152%   -clipboard - option to save output as an image on the system clipboard.
    147 %                Note: background transparency is not preserved in clipboard
     153%             Note: background transparency is not preserved in clipboard
    148154%   -d<gs_option> - option to indicate a ghostscript setting. For example,
    149 %                   -dMaxBitmap=0 or -dNoOutputFonts (Ghostscript 9.15+).
     155%             -dMaxBitmap=0 or -dNoOutputFonts (Ghostscript 9.15+).
    150156%   -depsc -  option to use EPS level-3 rather than the default level-2 print
    151157%             device. This solves some bugs with Matlab's default -depsc2 device
     
    155161%             done in vector formats (only): 11 standard Matlab fonts are
    156162%             replaced by the original figure fonts. This option prevents this.
     163%   -font_space <char> - option to set a spacer character for font-names that
     164%             contain spaces, used by EPS/PDF. Default: ''
    157165%   -linecaps - option to create rounded line-caps (vector formats only).
     166%   -noinvert - option to avoid setting figure's InvertHardcopy property to
     167%             'off' during output (this solves some problems of empty outputs).
     168%   -preserve_size - option to preserve the figure's PaperSize property in output
     169%             file (PDF/EPS formats only; default is to not preserve it).
     170%   -options <optionsStruct> - format-specific parameters as defined in Matlab's
     171%             documentation of the imwrite function, contained in a struct under
     172%             the format name. For example to specify the JPG Comment parameter,
     173%             pass a struct such as this: options.JPG.Comment='abc'. Similarly,
     174%             options.PNG.BitDepth=4. Valid only for PNG,TIF,JPG output formats.
    158175%   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.
     176%             handles, but the objects must be in the same figure) which is
     177%             to be saved. Default: gcf (handle of current figure).
    161178%
    162179% Outputs:
     
    248265% 22/03/17: Fixed issue #187: only set manual ticks when no exponent is present
    249266% 09/04/17: Added -linecaps option (idea by Baron Finer, issue #192)
     267% 15/09/17: Fixed issue #205: incorrect tick-labels when Ticks number don't match the TickLabels number
     268% 15/09/17: Fixed issue #210: initialize alpha map to ones instead of zeros when -transparent is not used
     269% 18/09/17: Added -font_space option to replace font-name spaces in EPS/PDF (workaround for issue #194)
     270% 18/09/17: Added -noinvert option to solve some export problems with some graphic cards (workaround for issue #197)
     271% 08/11/17: Fixed issue #220: axes exponent is removed in HG1 when TickMode is 'manual' (internal Matlab bug)
     272% 08/11/17: Fixed issue #221: alert if the requested folder does not exist
     273% 19/11/17: Workaround for issue #207: alert when trying to use transparent bgcolor with -opengl
     274% 29/11/17: Workaround for issue #206: warn if exporting PDF/EPS for a figure that contains an image
     275% 11/12/17: Fixed issue #230: use OpenGL renderer when exported image contains transparency (also see issue #206)
     276% 30/01/18: Updated SVG message to point to https://github.com/kupiqu/plot2svg and display user-selected filename if available
     277% 27/02/18: Fixed issue #236: axes exponent cropped from output if on right-hand axes
     278% 29/05/18: Fixed issue #245: process "string" inputs just like 'char' inputs
     279% 13/08/18: Fixed issue #249: correct black axes color to off-black to avoid extra cropping with -transparent
     280% 27/08/18: Added a possible file-open reason in EPS/PDF write-error message (suggested by "craq" on FEX page)
     281% 22/09/18: Xpdf website changed to xpdfreader.com
     282% 23/09/18: Fixed issue #243: only set non-bold font (workaround for issue #69) in R2015b or earlier; warn if changing font
     283% 23/09/18: Workaround for issue #241: don't use -r864 in EPS/PDF outputs when -native is requested (solves black lines problem)
     284% 18/11/18: Issue #261: Added informative alert when trying to export a uifigure (which is not currently supported)
     285% 13/12/18: Issue #261: Fixed last commit for cases of specifying axes/panel handle as input, rather than a figure handle
     286% 13/01/19: Issue #72: Added basic SVG output support
     287% 04/02/19: Workaround for issues #207 and #267: -transparent implies -noinvert
     288% 08/03/19: Issue #269: Added ability to specify format-specific options for PNG,TIF,JPG outputs; fixed help section
     289% 21/03/19: Fixed the workaround for issues #207 and #267 from 4/2/19 (-transparent now does *NOT* imply -noinvert; -transparent output should now be ok in all formats)
     290% 12/06/19: Issue #277: Enabled preservation of figure's PaperSize in output PDF/EPS file
     291% 06/08/19: Remove warning message about obsolete JavaFrame in R2019b
     292% 30/10/19: Fixed issue #261: added support for exporting uifigures and uiaxes (thanks to idea by @MarvinILA)
    250293%}
    251294
     
    266309    % Ensure that we have a figure handle
    267310    if isequal(fig,-1)
    268         return;  % silent bail-out
     311        return  % silent bail-out
    269312    elseif isempty(fig)
    270313        error('No figure found');
     314    else
     315        oldWarn = warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame');
     316        warning off MATLAB:ui:javaframe:PropertyToBeRemoved
     317        uifig = handle(ancestor(fig,'figure'));
     318        try jf = get(uifig,'JavaFrame'); catch, jf=1; end
     319        warning(oldWarn);
     320        if isempty(jf)  % this is a uifigure
     321            %error('Figures created using the uifigure command or App Designer are not supported by export_fig. See <a href="https://github.com/altmany/export_fig/issues/261">issue #261</a> for details.');
     322            if numel(fig) > 1
     323                error('export_fig:uifigure:multipleHandles', 'export_fig only supports exporting a single uifigure handle at a time; array of handles is not currently supported.')
     324            elseif ~any(strcmpi(fig.Type,{'figure','axes'}))
     325                error('export_fig:uifigure:notFigureOrAxes', 'export_fig only supports exporting a uifigure or uiaxes handle; other handles of a uifigure are not currently supported.')
     326            end
     327            % fig is either a uifigure or uiaxes handle
     328            isUiaxes = strcmpi(fig.Type,'axes');
     329            if isUiaxes
     330                % Label the specified axes so that we can find it in the legacy figure
     331                oldUserData = fig.UserData;
     332                tempStr = tempname;
     333                fig.UserData = tempStr;
     334            end
     335            try
     336                % Create an invisible legacy figure at the same position/size as the uifigure
     337                hNewFig = figure('Units',uifig.Units, 'Position',uifig.Position, 'MenuBar','none', 'ToolBar','none', 'Visible','off');
     338                % Copy the uifigure contents onto the new invisible legacy figure
     339                try
     340                    hChildren = allchild(uifig); %=uifig.Children;
     341                    copyobj(hChildren,hNewFig);
     342                catch
     343                    warning('export_fig:uifigure:controls', 'Some uifigure controls cannot be exported by export_fig and will not appear in the generated output.');
     344                end
     345                try fig.UserData = oldUserData; catch, end  % restore axes UserData, if modified above
     346                % Replace the uihandle in the input args with the legacy handle
     347                if isUiaxes  % uiaxes
     348                    % Locate the corresponding axes handle in the new legacy figure
     349                    hAxes = findall(hNewFig,'type','axes','UserData',tempStr);
     350                    if isempty(hAxes) % should never happen, check just in case
     351                        hNewHandle = hNewFig;  % export the figure instead of the axes
     352                    else
     353                        hNewHandle = hAxes;  % new axes handle found: use it instead of the uiaxes
     354                    end
     355                else  % uifigure
     356                    hNewHandle = hNewFig;
     357                end
     358                varargin(cellfun(@(c)isequal(c,fig),varargin)) = {hNewHandle};
     359                % Rerun export_fig on the legacy figure (with the replaced handle)
     360                [imageData, alpha] = export_fig(varargin{:});
     361                % Delete the temp legacy figure and bail out
     362                try delete(hNewFig); catch, end
     363                return
     364            catch err
     365                % Clean up the temp legacy figure and report the error
     366                try delete(hNewFig); catch, end
     367                rethrow(err)
     368            end
     369        end
    271370    end
    272371
     
    337436            % Set the FontWeight of axes labels/titles to 'normal'
    338437            % 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');
     438            % Issue #243: only set non-bold font (workaround for issue #69) in R2015b or earlier
     439            try isPreR2016a = verLessThan('matlab','8.7'); catch, isPreR2016a = true; end
     440            if isPreR2016a
     441                texLabels = findall(fig, 'type','text', 'FontWeight','bold');
     442                symbolIdx = ~cellfun('isempty',strfind({texLabels.String},'\'));
     443                if ~isempty(symbolIdx)
     444                    set(texLabels(symbolIdx), 'FontWeight','normal');
     445                    warning('export_fig:BoldTexLabels', 'Bold labels with Tex symbols converted into non-bold in export_fig (fix for issue #69)');
     446                end
     447            end
    342448        end
    343449    catch
     
    365471
    366472    % Set to print exactly what is there
    367     set(fig, 'InvertHardcopy', 'off');
     473    if options.invert_hardcopy
     474        try set(fig, 'InvertHardcopy', 'off'); catch, end  % fail silently in uifigures
     475    end
     476
    368477    % Set the renderer
    369478    switch options.renderer
     
    377486            renderer = '-opengl'; % Default for bitmaps
    378487    end
     488
     489    hImages = findall(fig,'type','image');
    379490
    380491    % Handle transparent patches
     
    390501        elseif ~options.png && ~options.tif  % issue #168
    391502            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);
     503        end
     504    elseif ~isempty(hImages)
     505        % Fix for issue #230: use OpenGL renderer when exported image contains transparency
     506        for idx = 1 : numel(hImages)
     507            cdata = get(hImages(idx),'CData');
     508            if any(isnan(cdata(:)))
     509                hasTransparency = true;
     510                break
     511            end
    392512        end
    393513    end
     
    428548                set(hCB(yCol==0), 'YColor', [0 0 0]);
    429549                set(hCB(xCol==0), 'XColor', [0 0 0]);
     550                % Correct black axes color to off-black (issue #249)
     551                hAxes = findall(fig, 'Type','axes');
     552                hXs = fixBlackAxle(hAxes, 'XColor');
     553                hYs = fixBlackAxle(hAxes, 'YColor');
     554                hZs = fixBlackAxle(hAxes, 'ZColor');
    430555
    431556                % The following code might cause out-of-memory errors
     
    445570                set(hCB(yCol==3), 'YColor', [1 1 1]);
    446571                set(hCB(xCol==3), 'XColor', [1 1 1]);
     572                % Revert the black axes colors
     573                set(hXs, 'XColor', [0,0,0]);
     574                set(hYs, 'YColor', [0,0,0]);
     575                set(hZs, 'ZColor', [0,0,0]);
    447576
    448577                % The following code might cause out-of-memory errors
     
    487616                    res = options.magnify * get(0, 'ScreenPixelsPerInch') / 25.4e-3;
    488617                    % Save the png
    489                     imwrite(A, [options.name '.png'], 'Alpha', double(alpha), 'ResolutionUnit', 'meter', 'XResolution', res, 'YResolution', res);
     618                    [format_options, bitDepth] = getFormatOptions(options, 'png');  %Issue #269
     619                    if ~isempty(bitDepth) && bitDepth < 16 && size(A,3) == 3
     620                        % BitDepth specification requires using a color-map
     621                        [A, map] = rgb2ind(A, 256);
     622                        imwrite(A, map, [options.name '.png'], 'Alpha',double(alpha), 'ResolutionUnit','meter', 'XResolution',res, 'YResolution',res, format_options{:});
     623                    else
     624                        imwrite(A, [options.name '.png'], 'Alpha',double(alpha), 'ResolutionUnit','meter', 'XResolution',res, 'YResolution',res, format_options{:});
     625                    end
    490626                    % Clear the png bit
    491627                    options.png = false;
     
    544680                if options.alpha
    545681                    imageData = A;
    546                     alpha = zeros(size(A, 1), size(A, 2), 'single');
     682                    alpha = ones(size(A, 1), size(A, 2), 'single');
    547683                end
    548684            end
     
    550686            if options.png
    551687                res = options.magnify * get(0, 'ScreenPixelsPerInch') / 25.4e-3;
    552                 imwrite(A, [options.name '.png'], 'ResolutionUnit', 'meter', 'XResolution', res, 'YResolution', res);
     688                [format_options, bitDepth] = getFormatOptions(options, 'png');  %Issue #269
     689                if ~isempty(bitDepth) && bitDepth < 16 && size(A,3) == 3
     690                    % BitDepth specification requires using a color-map
     691                    [A, map] = rgb2ind(A, 256);
     692                    imwrite(A, map, [options.name '.png'], 'ResolutionUnit','meter', 'XResolution',res, 'YResolution',res, format_options{:});
     693                else
     694                    imwrite(A, [options.name '.png'], 'ResolutionUnit','meter', 'XResolution',res, 'YResolution',res, format_options{:});
     695                end
    553696            end
    554697            if options.bmp
     
    561704                    quality = 95;
    562705                end
     706                format_options = getFormatOptions(options, 'jpg');  %Issue #269
    563707                if quality > 100
    564                     imwrite(A, [options.name '.jpg'], 'Mode', 'lossless');
     708                    imwrite(A, [options.name '.jpg'], 'Mode','lossless', format_options{:});
    565709                else
    566                     imwrite(A, [options.name '.jpg'], 'Quality', quality);
     710                    imwrite(A, [options.name '.jpg'], 'Quality',quality, format_options{:});
    567711                end
    568712            end
     
    580724                end
    581725                append_mode = {'overwrite', 'append'};
    582                 imwrite(A, [options.name '.tif'], 'Resolution', options.magnify*get(0, 'ScreenPixelsPerInch'), 'WriteMode', append_mode{options.append+1});
     726                format_options = getFormatOptions(options, 'tif');  %Issue #269
     727                imwrite(A, [options.name '.tif'], 'Resolution',options.magnify*get(0,'ScreenPixelsPerInch'), 'WriteMode',append_mode{options.append+1}, format_options{:});
    583728            end
    584729        end
     
    590735                if hasTransparency || hasPatches
    591736                    % This is *MUCH* slower, but more accurate for patches and transparent annotations (issue #39)
    592                     renderer = '-painters'; %ISSM fix
     737                    renderer = '-opengl';
    593738                else
    594739                    renderer = '-painters';
     
    624769            end
    625770            % Generate the options for print
    626             p2eArgs = {renderer, sprintf('-r%d', options.resolution)};
     771            printArgs = {renderer};
     772            if ~isempty(options.resolution)  % issue #241
     773                printArgs{end+1} = sprintf('-r%d', options.resolution);
     774            end
    627775            if options.colourspace == 1  % CMYK
    628776                % Issue #33: due to internal bugs in Matlab's print() function, we can't use its -cmyk option
    629                 %p2eArgs{end+1} = '-cmyk';
     777                %printArgs{end+1} = '-cmyk';
    630778            end
    631779            if ~options.crop
    632780                % Issue #56: due to internal bugs in Matlab's print() function, we can't use its internal cropping mechanism,
    633781                % therefore we always use '-loose' (in print2eps.m) and do our own cropping (in crop_borders)
    634                 %p2eArgs{end+1} = '-loose';
     782                %printArgs{end+1} = '-loose';
    635783            end
    636784            if any(strcmpi(varargin,'-depsc'))
    637785                % Issue #45: lines in image subplots are exported in invalid color.
    638786                % The workaround is to use the -depsc parameter instead of the default -depsc2
    639                 p2eArgs{end+1} = '-depsc';
     787                printArgs{end+1} = '-depsc';
    640788            end
    641789            try
     790                % Remove background if requested (issue #207)
     791                originalBgColor = get(fig, 'Color');
     792                [hXs, hYs, hZs] = deal([]);
     793                if options.transparent %&& ~isequal(get(fig, 'Color'), 'none')
     794                    if options.renderer == 1  % OpenGL
     795                        warning('export_fig:openglTransparentBG', '-opengl sometimes fails to produce transparent backgrounds; in such a case, try to use -painters instead');
     796                    end
     797
     798                    % Fix for issue #207, #267 (corrected)
     799                    set(fig,'Color','none');
     800
     801                    % Correct black axes color to off-black (issue #249)
     802                    hAxes = findall(fig, 'Type','axes');
     803                    hXs = fixBlackAxle(hAxes, 'XColor');
     804                    hYs = fixBlackAxle(hAxes, 'YColor');
     805                    hZs = fixBlackAxle(hAxes, 'ZColor');
     806                end
    642807                % Generate an eps
    643                 print2eps(tmp_nam, fig, options, p2eArgs{:});
     808                print2eps(tmp_nam, fig, options, printArgs{:});
     809                % {
    644810                % Remove the background, if desired
    645                 if options.transparent && ~isequal(get(fig, 'Color'), 'none')
     811                if options.transparent %&& ~isequal(get(fig, 'Color'), 'none')
    646812                    eps_remove_background(tmp_nam, 1 + using_hg2(fig));
    647                 end
     813
     814                    % Revert the black axes colors
     815                    set(hXs, 'XColor', [0,0,0]);
     816                    set(hYs, 'YColor', [0,0,0]);
     817                    set(hZs, 'ZColor', [0,0,0]);
     818                end
     819                %}
     820                % Restore the figure's previous background color (if modified)
     821                try set(fig,'Color',originalBgColor); drawnow; catch, end
    648822                % Fix colorspace to CMYK, if requested (workaround for issue #33)
    649823                if options.colourspace == 1  % CMYK
     
    671845                    % Alert in case of error creating output PDF/EPS file (issue #179)
    672846                    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']);
     847                        errMsg = ['Could not create ' pdf_nam ' - perhaps the folder does not exist, or you do not have write permissions, or the file is open in another application'];
     848                        error(errMsg);
    674849                    else
    675850                        error('Could not generate the intermediary EPS file.');
     
    677852                end
    678853            catch ex
     854                % Restore the figure's previous background color (in case it was not already restored)
     855                try set(fig,'Color',originalBgColor); drawnow; catch, end
    679856                % Delete the eps
    680857                delete(tmp_nam);
     858                % Rethrow the EPS/PDF-generation error
    681859                rethrow(ex);
    682860            end
     
    718896                end
    719897            end
     898            % Issue #206: warn if the figure contains an image
     899            if ~isempty(hImages) && strcmpi(renderer,'-opengl')  % see addendum to issue #206
     900                warnMsg = ['exporting images to PDF/EPS may result in blurry images on some viewers. ' ...
     901                           'If so, try to change viewer, or increase the image''s CData resolution, or use -opengl renderer, or export via the print function. ' ...
     902                           'See <a href="matlab:web(''https://github.com/altmany/export_fig/issues/206'',''-browser'');">issue #206</a> for details.'];
     903                warning('export_fig:pdf_eps:blurry_image', warnMsg);
     904            end
     905        end
     906
     907        % SVG format
     908        if options.svg
     909            oldUnits = get(fig,'Units');
     910            filename = [options.name '.svg'];
     911            % Adapted from Dan Joshea's https://github.com/djoshea/matlab-save-figure :
     912            try %if verLessThan('matlab', '8.4')
     913                % Try using the fig2svg/plot2svg utilities
     914                try
     915                    fig2svg(filename, fig);  %https://github.com/kupiqu/fig2svg
     916                catch
     917                    plot2svg(filename, fig); %https://github.com/jschwizer99/plot2svg
     918                    warning('export_fig:SVG:plot2svg', 'export_fig used the plot2svg utility for SVG output. Better results may be gotten via the fig2svg utility (https://github.com/kupiqu/fig2svg).');
     919                end
     920            catch %else  % (neither fig2svg nor plot2svg are available)
     921                % Try Matlab's built-in svg engine (from Batik Graphics2D for java)
     922                try
     923                    set(fig,'Units','pixels');   % All data in the svg-file is saved in pixels
     924                    printArgs = {renderer};
     925                    if ~isempty(options.resolution)
     926                        printArgs{end+1} = sprintf('-r%d', options.resolution);
     927                    end
     928                    print(fig, '-dsvg', printArgs{:}, filename);
     929                    warning('export_fig:SVG:print', 'export_fig used Matlab''s built-in SVG output engine. Better results may be gotten via the fig2svg utility (https://github.com/kupiqu/fig2svg).');
     930                catch err  % built-in print() failed - maybe an old Matlab release (no -dsvg)
     931                    set(fig,'Units',oldUnits);
     932                    filename = strrep(filename,'export_fig_out','filename');
     933                    msg = ['SVG output is not supported for your figure: ' err.message '\n' ...
     934                        'Try one of the following alternatives:\n' ...
     935                        '  1. saveas(gcf,''' filename ''')\n' ...
     936                        '  2. fig2svg utility: https://github.com/kupiqu/fig2svg\n' ...  % Note: replaced defunct https://github.com/jschwizer99/plot2svg with up-to-date fork on https://github.com/kupiqu/fig2svg
     937                        '  3. export_fig to EPS/PDF, then convert to SVG using non-Matlab tools\n'];
     938                    error(sprintf(msg)); %#ok<SPERR>
     939                end
     940            end
     941            % SVG output was successful if we reached this point
     942            % Restore original figure units
     943            set(fig,'Units',oldUnits);
     944            % Add warning about unsupported export_fig options with SVG output
     945            if any(~isnan(options.crop_amounts)) || any(options.bb_padding)
     946                warning('export_fig:SVG:options', 'export_fig''s SVG output does not [currently] support cropping/padding.');
     947            end
    720948        end
    721949
     
    726954        else
    727955            % Reset the hardcopy mode
    728             set(fig, 'InvertHardcopy', old_mode);
     956            try set(fig, 'InvertHardcopy', old_mode); catch, end  % fail silently in uifigures
    729957            % Reset the axes limit and tick modes
    730958            for a = 1:numel(Hlims)
     
    7751003                error(javachk('awt', 'export_fig -clipboard output'));
    7761004            catch
    777                 warning('export_fig -clipboard output failed: requires Java to work');
     1005                warning('export_fig:clipboardJava', 'export_fig -clipboard output failed: requires Java to work');
    7781006                return;
    7791007            end
     
    8211049                cb.setContents(imSelection, []);
    8221050            catch
    823                 warning('export_fig -clipboard output failed: %s', lasterr); %#ok<LERR>
     1051                warning('export_fig:clipboardFailed', 'export_fig -clipboard output failed: %s', lasterr); %#ok<LERR>
    8241052            end
    8251053        end
     
    8351063            fprintf(2, 'Please ensure:\n');
    8361064            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');
     1065            if isvector(options)
     1066                if ismac
     1067                    fprintf(2, '  and that you have <a href="http://pages.uoregon.edu/koch">Ghostscript</a> installed\n');
     1068                else
     1069                    fprintf(2, '  and that you have <a href="http://www.ghostscript.com">Ghostscript</a> installed\n');
     1070                end
    8411071            end
    8421072            try
    8431073                if options.eps
    844                     fprintf(2, '  and that you have <a href="http://www.foolabs.com/xpdf">pdftops</a> installed\n');
     1074                    fprintf(2, '  and that you have <a href="http://xpdfreader.com/download.html">pdftops</a> installed\n');
    8451075                end
    8461076            catch
     
    8661096    % Default options used by export_fig
    8671097    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',   {{}});
     1098        'name',            'export_fig_out', ...
     1099        'crop',            true, ...
     1100        'crop_amounts',    nan(1,4), ...  % auto-crop all 4 image sides
     1101        'transparent',     false, ...
     1102        'renderer',        0, ...         % 0: default, 1: OpenGL, 2: ZBuffer, 3: Painters
     1103        'pdf',             false, ...
     1104        'eps',             false, ...
     1105        'svg',             false, ...
     1106        'png',             false, ...
     1107        'tif',             false, ...
     1108        'jpg',             false, ...
     1109        'bmp',             false, ...
     1110        'clipboard',       false, ...
     1111        'colourspace',     0, ...         % 0: RGB/gray, 1: CMYK, 2: gray
     1112        'append',          false, ...
     1113        'im',              false, ...
     1114        'alpha',           false, ...
     1115        'aa_factor',       0, ...
     1116        'bb_padding',      0, ...
     1117        'magnify',         [], ...
     1118        'resolution',      [], ...
     1119        'bookmark',        false, ...
     1120        'closeFig',        false, ...
     1121        'quality',         [], ...
     1122        'update',          false, ...
     1123        'fontswap',        true, ...
     1124        'font_space',      '', ...
     1125        'linecaps',        false, ...
     1126        'invert_hardcopy', true, ...
     1127        'format_options',  struct, ...
     1128        'preserve_size',   false, ...
     1129        'gs_options',      {{}});
    8951130end
    8961131
    8971132function [fig, options] = parse_args(nout, fig, varargin)
    8981133    % Parse the input arguments
     1134
     1135    % Convert strings => chars
     1136    varargin = cellfun(@str2char,varargin,'un',false);
    8991137
    9001138    % Set the defaults
     
    9311169                    case 'eps'
    9321170                        options.eps = true;
     1171                    case 'svg'
     1172                        options.svg = true;
    9331173                    case 'png'
    9341174                        options.png = true;
     
    9571197                        options.im = true;
    9581198                        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>
    9651199                    case 'update'
    9661200                        % Download the latest version of export_fig into the export_fig folder
     
    9691203                            folderName = fileparts(which(mfilename('fullpath')));
    9701204                            targetFileName = fullfile(folderName, datestr(now,'yyyy-mm-dd.zip'));
    971                             urlwrite(zipFileName,targetFileName);
     1205                            urlwrite(zipFileName,targetFileName); %#ok<URLWR>
    9721206                        catch
    9731207                            error('Could not download %s into %s\n',zipFileName,targetFileName);
     
    9821216                    case 'nofontswap'
    9831217                        options.fontswap = false;
     1218                    case 'font_space'
     1219                        options.font_space = varargin{a+1};
     1220                        skipNext = true;
    9841221                    case 'linecaps'
    9851222                        options.linecaps = true;
     1223                    case 'noinvert'
     1224                        options.invert_hardcopy = false;
     1225                    case 'preserve_size'
     1226                        options.preserve_size = true;
     1227                    case 'options'
     1228                        % Issue #269: format-specific options
     1229                        inputOptions = varargin{a+1};
     1230                        %options.format_options  = inputOptions;
     1231                        if isempty(inputOptions), continue, end
     1232                        formats = fieldnames(inputOptions(1));
     1233                        for idx = 1 : numel(formats)
     1234                            optionsStruct = inputOptions.(formats{idx});
     1235                            %optionsCells = [fieldnames(optionsStruct) struct2cell(optionsStruct)]';
     1236                            formatName = regexprep(lower(formats{idx}),{'tiff','jpeg'},{'tif','jpg'});
     1237                            options.format_options.(formatName) = optionsStruct; %=optionsCells(:)';
     1238                        end
     1239                        skipNext = true;
    9861240                    otherwise
    9871241                        try
     
    10441298                [p, options.name, ext] = fileparts(varargin{a});
    10451299                if ~isempty(p)
     1300                    % Issue #221: alert if the requested folder does not exist
     1301                    if ~exist(p,'dir'),  error(['Folder ' p ' does not exist!']);  end
    10461302                    options.name = [p filesep options.name];
    10471303                end
     
    10721328                        end
    10731329                    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>
     1330                        options.svg = true;
    10791331                    otherwise
    10801332                        options.name = varargin{a};
     
    11271379    % If requested, set the resolution to the native vertical resolution of the
    11281380    % 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)
     1381    if native
     1382        if isbitmap(options)
     1383            % Find a suitable image
     1384            list = findall(fig, 'Type','image', 'Tag','export_fig_native');
     1385            if isempty(list)
     1386                list = findall(fig, 'Type','image', 'Visible','on');
     1387            end
     1388            for hIm = list(:)'
     1389                % Check height is >= 2
     1390                height = size(get(hIm, 'CData'), 1);
     1391                if height < 2
    11481392                    continue
    11491393                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
     1394                % Account for the image filling only part of the axes, or vice versa
     1395                yl = get(hIm, 'YData');
     1396                if isscalar(yl)
     1397                    yl = [yl(1)-0.5 yl(1)+height+0.5];
     1398                else
     1399                    yl = [min(yl), max(yl)];  % fix issue #151 (case of yl containing more than 2 elements)
     1400                    if ~diff(yl)
     1401                        continue
     1402                    end
     1403                    yl = yl + [-0.5 0.5] * (diff(yl) / (height - 1));
     1404                end
     1405                hAx = get(hIm, 'Parent');
     1406                yl2 = get(hAx, 'YLim');
     1407                % Find the pixel height of the axes
     1408                oldUnits = get(hAx, 'Units');
     1409                set(hAx, 'Units', 'pixels');
     1410                pos = get(hAx, 'Position');
     1411                set(hAx, 'Units', oldUnits);
     1412                if ~pos(4)
     1413                    continue
     1414                end
     1415                % Found a suitable image
     1416                % Account for stretch-to-fill being disabled
     1417                pbar = get(hAx, 'PlotBoxAspectRatio');
     1418                pos = min(pos(4), pbar(2)*pos(3)/pbar(1));
     1419                % Set the magnification to give native resolution
     1420                options.magnify = abs((height * diff(yl2)) / (pos * diff(yl)));  % magnification must never be negative: issue #103
     1421                break
     1422            end
     1423        elseif options.resolution == 864  % don't use -r864 in vector mode if user asked for -native
     1424            options.resolution = []; % issue #241 (internal Matlab bug produces black lines with -r864)
     1425        end
     1426    end
     1427end
     1428
     1429% Convert a possible string => char (issue #245)
     1430function value = str2char(value)
     1431    if isa(value,'string')
     1432        value = char(value);
    11701433    end
    11711434end
     
    13041567            hAxes = Hlims(idx(idx2));
    13051568            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
     1569            tickVals = get(hAxes,[ax 'Tick']);
     1570            tickStrs = get(hAxes,[ax 'TickLabel']);
     1571            try % Fix issue #236
     1572                exponents = [hAxes.([ax 'Axis']).SecondaryLabel];
     1573            catch
     1574                exponents = [hAxes.([ax 'Ruler']).SecondaryLabel];
     1575            end
     1576            if isempty([exponents.String])
     1577                % Fix for issue #205 - only set manual ticks when the Ticks number match the TickLabels number
     1578                if numel(tickVals) == numel(tickStrs)
     1579                    set(hAxes, props{:});  % no exponent and matching ticks, so update both ticks and tick labels to manual
     1580                end
    13081581            end
    13091582        catch  % probably HG1
    1310             set(hAxes, props{:});  % revert back to old behavior
     1583            % Fix for issue #220 - exponent is removed in HG1 when TickMode is 'manual' (internal Matlab bug)
     1584            if isequal(tickVals, str2num(tickStrs)') %#ok<ST2NM>
     1585                set(hAxes, props{:});  % revert back to old behavior
     1586            end
    13111587        end
    13121588    end
     
    13321608    end
    13331609end
     1610
     1611function hBlackAxles = fixBlackAxle(hAxes, axleName)
     1612    hBlackAxles = [];
     1613    for idx = 1 : numel(hAxes)
     1614        ax = hAxes(idx);
     1615        axleColor = get(ax, axleName);
     1616        if isequal(axleColor,[0,0,0]) || isequal(axleColor,'k')
     1617            hBlackAxles(end+1) = ax; %#ok<AGROW>
     1618        end
     1619    end
     1620    set(hBlackAxles, axleName, [0,0,0.01]);  % off-black
     1621end
     1622
     1623% Issue #269: format-specific options
     1624function [optionsCells, bitDepth] = getFormatOptions(options, formatName)
     1625    bitDepth = [];
     1626    try
     1627        optionsStruct = options.format_options.(lower(formatName));
     1628    catch
     1629        % User did not specify any extra parameters for this format
     1630        optionsCells = {};
     1631        return
     1632    end
     1633    optionNames = fieldnames(optionsStruct);
     1634    optionVals  = struct2cell(optionsStruct);
     1635    optionsCells = [optionNames, optionVals]';
     1636    if nargout < 2, return, end  % bail out if BitDepth is not required
     1637    try
     1638        idx = find(strcmpi(optionNames,'BitDepth'), 1, 'last');
     1639        if ~isempty(idx)
     1640            bitDepth = optionVals{idx};
     1641        end
     1642    catch
     1643        % never mind - ignore
     1644    end
     1645end
  • TabularUnified issm/trunk-jpl/externalpackages/export_fig/im2gif.m

    r18904 r24460  
    4242% Copyright (C) Oliver Woodford 2011
    4343
     44%{
     45% 14/02/18: Merged issue #235: reduced memory usage, improved performance (thanks to @numb7rs)
     46% 30/11/19: Merged issue #288: Fix im2gif.m for greyscale TIFF images (thanks @Blackbelt1221)
     47%}
     48
    4449function im2gif(A, varargin)
    4550
    46 % Parse the input arguments
    47 [A, options] = parse_args(A, varargin{:});
    48 
    49 if options.crop ~= 0
    50     % Crop
    51     A = crop_borders(A, A(ceil(end/2),1,:,1));
    52 end
    53 
    54 % Convert to indexed image
    55 [h, w, c, n] = size(A);
    56 A = reshape(permute(A, [1 2 4 3]), h, w*n, c);
    57 map = unique(reshape(A, h*w*n, c), 'rows');
    58 if size(map, 1) > 256
    59     dither_str = {'dither', 'nodither'};
    60     dither_str = dither_str{1+(options.dither==0)};
    61     if options.ncolors <= 1
    62         [B, map] = rgb2ind(A, options.ncolors, dither_str);
    63         if size(map, 1) > 256
    64             [B, map] = rgb2ind(A, 256, dither_str);
     51    % Parse the input arguments
     52    [A, options] = parse_args(A, varargin{:});
     53
     54    if options.crop ~= 0
     55        % Crop
     56        A = crop_borders(A, A(ceil(end/2),1,:,1));
     57    end
     58
     59    % Convert to indexed image
     60    [h, w, c, n] = size(A);
     61
     62    % Issue #235: Using unique(A,'rows') on the whole image stack at once causes
     63    % massive memory usage when dealing with large images (at least on Matlab 2017b).
     64    % Running unique(...) on individual frames, then again on the results drastically
     65    % reduces the memory usage & slightly improves the execution time (@numb7rs).
     66    uns = cell(1,size(A,4));
     67    for nn=1:size(A,4)
     68        uns{nn}=unique(reshape(A(:,:,:,nn), h*w, c),'rows');
     69    end
     70    map=unique(cell2mat(uns'),'rows');
     71
     72    A = reshape(permute(A, [1 2 4 3]), h, w*n, c);
     73
     74    if size(map, 1) > 256
     75        dither_str = {'dither', 'nodither'};
     76        dither_str = dither_str{1+(options.dither==0)};
     77        if options.ncolors <= 1
     78            [B, map] = rgb2ind(A, options.ncolors, dither_str);
     79            if size(map, 1) > 256
     80                [B, map] = rgb2ind(A, 256, dither_str);
     81            end
     82        else
     83            [B, map] = rgb2ind(A, min(round(options.ncolors), 256), dither_str);
    6584        end
    6685    else
    67         [B, map] = rgb2ind(A, min(round(options.ncolors), 256), dither_str);
    68     end
    69 else
    70     if max(map(:)) > 1
    71         map = double(map) / 255;
    72         A = double(A) / 255;
    73     end
    74     B = rgb2ind(im2double(A), map);
    75 end
    76 B = reshape(B, h, w, 1, n);
    77 
    78 % Bug fix to rgb2ind
    79 map(B(1)+1,:) = im2double(A(1,1,:));
    80 
    81 % Save as a gif
    82 imwrite(B, map, options.outfile, 'LoopCount', round(options.loops(1)), 'DelayTime', options.delay);
     86        if max(map(:)) > 1
     87            map = double(map) / 255;
     88            A = double(A) / 255;
     89        end
     90        B = rgb2ind(im2double(A), map);
     91    end
     92    B = reshape(B, h, w, 1, n);
     93
     94    % Bug fix to rgb2ind
     95    map(B(1)+1,:) = im2double(A(1,1,:));
     96
     97    % Save as a gif
     98    imwrite(B, map, options.outfile, 'LoopCount', round(options.loops(1)), 'DelayTime', options.delay);
    8399end
    84100
    85101%% Parse the input arguments
    86102function [A, options] = parse_args(A, varargin)
    87 % Set the defaults
    88 options = struct('outfile', '', ...
    89                  'dither', true, ...
    90                  'crop', true, ...
    91                  'ncolors', 256, ...
    92                  'loops', 65535, ...
    93                  'delay', 1/15);
    94 
    95 % Go through the arguments
    96 a = 0;
    97 n = numel(varargin);
    98 while a < n
    99     a = a + 1;
    100     if ischar(varargin{a}) && ~isempty(varargin{a})
    101         if varargin{a}(1) == '-'
    102             opt = lower(varargin{a}(2:end));
    103             switch opt
    104                 case 'nocrop'
    105                     options.crop = false;
    106                 case 'nodither'
    107                     options.dither = false;
    108                 otherwise
    109                     if ~isfield(options, opt)
    110                         error('Option %s not recognized', varargin{a});
    111                     end
    112                     a = a + 1;
    113                     if ischar(varargin{a}) && ~ischar(options.(opt))
    114                         options.(opt) = str2double(varargin{a});
    115                     else
    116                         options.(opt) = varargin{a};
    117                     end
    118             end
    119         else
    120             options.outfile = varargin{a};
    121         end
    122     end
    123 end
    124 
    125 if isempty(options.outfile)
    126     if ~ischar(A)
    127         error('No output filename given.');
    128     end
    129     % Generate the output filename from the input filename
    130     [path, outfile] = fileparts(A);
    131     options.outfile = fullfile(path, [outfile '.gif']);
    132 end
    133 
    134 if ischar(A)
    135     % Read in the image
    136     A = imread_rgb(A);
    137 end
     103    % Set the defaults
     104    options = struct('outfile', '', ...
     105                     'dither', true, ...
     106                     'crop', true, ...
     107                     'ncolors', 256, ...
     108                     'loops', 65535, ...
     109                     'delay', 1/15);
     110
     111    % Go through the arguments
     112    a = 0;
     113    n = numel(varargin);
     114    while a < n
     115        a = a + 1;
     116        if ischar(varargin{a}) && ~isempty(varargin{a})
     117            if varargin{a}(1) == '-'
     118                opt = lower(varargin{a}(2:end));
     119                switch opt
     120                    case 'nocrop'
     121                        options.crop = false;
     122                    case 'nodither'
     123                        options.dither = false;
     124                    otherwise
     125                        if ~isfield(options, opt)
     126                            error('Option %s not recognized', varargin{a});
     127                        end
     128                        a = a + 1;
     129                        if ischar(varargin{a}) && ~ischar(options.(opt))
     130                            options.(opt) = str2double(varargin{a});
     131                        else
     132                            options.(opt) = varargin{a};
     133                        end
     134                end
     135            else
     136                options.outfile = varargin{a};
     137            end
     138        end
     139    end
     140
     141    if isempty(options.outfile)
     142        if ~ischar(A)
     143            error('No output filename given.');
     144        end
     145        % Generate the output filename from the input filename
     146        [path, outfile] = fileparts(A);
     147        options.outfile = fullfile(path, [outfile '.gif']);
     148    end
     149
     150    if ischar(A)
     151        % Read in the image
     152        A = imread_rgb(A);
     153    end
    138154end
    139155
    140156%% Read image to uint8 rgb array
    141157function [A, alpha] = imread_rgb(name)
    142 % Get file info
    143 info = imfinfo(name);
    144 % Special case formats
    145 switch lower(info(1).Format)
    146     case 'gif'
    147         [A, map] = imread(name, 'frames', 'all');
    148         if ~isempty(map)
    149             map = uint8(map * 256 - 0.5); % Convert to uint8 for storage
    150             A = reshape(map(uint32(A)+1,:), [size(A) size(map, 2)]); % Assume indexed from 0
    151             A = permute(A, [1 2 5 4 3]);
    152         end
    153     case {'tif', 'tiff'}
    154         A = cell(numel(info), 1);
    155         for a = 1:numel(A)
    156             [A{a}, map] = imread(name, 'Index', a, 'Info', info);
     158    % Get file info
     159    info = imfinfo(name);
     160    % Special case formats
     161    switch lower(info(1).Format)
     162        case 'gif'
     163            [A, map] = imread(name, 'frames', 'all');
    157164            if ~isempty(map)
    158165                map = uint8(map * 256 - 0.5); % Convert to uint8 for storage
    159                 A{a} = reshape(map(uint32(A{a})+1,:), [size(A) size(map, 2)]); % Assume indexed from 0
    160             end
    161             if size(A{a}, 3) == 4
    162                 % TIFF in CMYK colourspace - convert to RGB
    163                 if isfloat(A{a})
    164                     A{a} = A{a} * 255;
    165                 else
    166                     A{a} = single(A{a});
     166                A = reshape(map(uint32(A)+1,:), [size(A) size(map, 2)]); % Assume indexed from 0
     167                A = permute(A, [1 2 5 4 3]);
     168            end
     169        case {'tif', 'tiff'}
     170            A = cell(numel(info), 1);
     171            for a = 1:numel(A)
     172                [A{a}, map] = imread(name, 'Index', a, 'Info', info);
     173                if ~isempty(map)
     174                    map = uint8(map * 256 - 0.5); % Convert to uint8 for storage
     175                    A{a} = reshape(map(uint32(A{a})+1,:), [size(A) size(map, 2)]); % Assume indexed from 0
    167176                end
    168                 A{a} = 255 - A{a};
    169                 A{a}(:,:,4) = A{a}(:,:,4) / 255;
    170                 A{a} = uint8(A(:,:,1:3) .* A{a}(:,:,[4 4 4]));
    171             end
    172         end
    173         A = cat(4, A{:});
    174     otherwise
    175         [A, map, alpha] = imread(name);
    176         A = A(:,:,:,1); % Keep only first frame of multi-frame files
    177         if ~isempty(map)
    178             map = uint8(map * 256 - 0.5); % Convert to uint8 for storage
    179             A = reshape(map(uint32(A)+1,:), [size(A) size(map, 2)]); % Assume indexed from 0
    180         elseif size(A, 3) == 4
    181             % Assume 4th channel is an alpha matte
    182             alpha = A(:,:,4);
    183             A = A(:,:,1:3);
    184         end
     177                if size(A{a}, 3) == 4
     178                    % TIFF in CMYK colourspace - convert to RGB
     179                    if isfloat(A{a})
     180                        A{a} = A{a} * 255;
     181                    else
     182                        A{a} = single(A{a});
     183                    end
     184                    A{a} = 255 - A{a};
     185                    A{a}(:,:,4) = A{a}(:,:,4) / 255;
     186                    A{a} = uint8(A(:,:,1:3) .* A{a}(:,:,[4 4 4]));
     187                elseif size(A{a}, 3) < 3 %Check whether TIFF has been read in as greyscale
     188                    %Convert from greyscale to RGB colorspace (issue #288)
     189                    A{a} = cat(3, A{a}, A{a}, A{a});
     190                end
     191            end
     192            A = cat(4, A{:});
     193        otherwise
     194            [A, map, alpha] = imread(name);
     195            A = A(:,:,:,1); % Keep only first frame of multi-frame files
     196            if ~isempty(map)
     197                map = uint8(map * 256 - 0.5); % Convert to uint8 for storage
     198                A = reshape(map(uint32(A)+1,:), [size(A) size(map, 2)]); % Assume indexed from 0
     199            elseif size(A, 3) == 4
     200                % Assume 4th channel is an alpha matte
     201                alpha = A(:,:,4);
     202                A = A(:,:,1:3);
     203            end
     204    end
    185205end
    186 end
  • TabularUnified issm/trunk-jpl/externalpackages/export_fig/pdf2eps.m

    r18904 r24460  
    88% This function requires that you have pdftops, from the Xpdf suite of
    99% functions, installed on your system. This can be downloaded from:
    10 % http://www.foolabs.com/xpdf 
     10% http://xpdfreader.com
    1111%
    12 %IN:
     12% Inputs:
    1313%   source - filename of the source pdf file to convert. The filename is
    1414%            assumed to already have the extension ".pdf".
     
    1616%          already have the extension ".eps".
    1717
    18 % Copyright (C) Oliver Woodford 2009-2010
     18% Copyright (C) Oliver Woodford 2009-2010, Yair Altman 2015-
    1919
    2020% Thanks to Aldebaro Klautau for reporting a bug when saving to
    2121% non-existant directories.
    2222
     23% 22/09/2018 - Xpdf website changed to xpdfreader.com
     24
    2325function pdf2eps(source, dest)
    24 % Construct the options string for pdftops
    25 options = ['-q -paper match -eps -level2 "' source '" "' dest '"'];
    26 % Convert to eps using pdftops
    27 [status, message] = pdftops(options);
    28 % Check for error
    29 if status
    30     % Report error
    31     if isempty(message)
    32         error('Unable to generate eps. Check destination directory is writable.');
    33     else
    34         error(message);
     26    % Construct the options string for pdftops
     27    options = ['-q -paper match -eps -level2 "' source '" "' dest '"'];
     28
     29    % Convert to eps using pdftops
     30    [status, message] = pdftops(options);
     31
     32    % Check for error
     33    if status
     34        % Report error
     35        if isempty(message)
     36            error('Unable to generate eps. Check destination directory is writable.');
     37        else
     38            error(message);
     39        end
    3540    end
     41
     42    % Fix the DSC error created by pdftops
     43    fid = fopen(dest, 'r+');
     44    if fid == -1
     45        % Cannot open the file
     46        return
     47    end
     48    fgetl(fid); % Get the first line
     49    str = fgetl(fid); % Get the second line
     50    if strcmp(str(1:min(13, end)), '% Produced by')
     51        fseek(fid, -numel(str)-1, 'cof');
     52        fwrite(fid, '%'); % Turn ' ' into '%'
     53    end
     54    fclose(fid);
    3655end
    37 % Fix the DSC error created by pdftops
    38 fid = fopen(dest, 'r+');
    39 if fid == -1
    40     % Cannot open the file
    41     return
    42 end
    43 fgetl(fid); % Get the first line
    44 str = fgetl(fid); % Get the second line
    45 if strcmp(str(1:min(13, end)), '% Produced by')
    46     fseek(fid, -numel(str)-1, 'cof');
    47     fwrite(fid, '%'); % Turn ' ' into '%'
    48 end
    49 fclose(fid);
    50 end
    51 
  • TabularUnified issm/trunk-jpl/externalpackages/export_fig/pdftops.m

    r21671 r24460  
    1212%
    1313% This function requires that you have pdftops (from the Xpdf package)
    14 % installed on your system. You can download this from:
    15 % http://www.foolabs.com/xpdf
     14% installed on your system. You can download this from: http://xpdfreader.com
    1615%
    1716% IN:
     
    3130% 02/05/2016 - Search additional possible paths suggested by Jonas Stein (issue #147)
    3231% 03/05/2016 - Display the specific error message if pdftops fails for some reason (issue #148)
     32% 22/09/2018 - Xpdf website changed to xpdfreader.com; improved popup logic
     33% 03/02/2019 - Fixed one-off 'pdftops not found' error after install (Mac/Linux) (issue #266)
    3334
    3435    % Call pdftops
     
    6970    % Ask the user to enter the path
    7071    errMsg1 = 'Pdftops not found. Please locate the program, or install xpdf-tools from ';
    71     url1 = 'http://foolabs.com/xpdf';
     72    url1 = 'http://xpdfreader.com/download.html'; %='http://foolabs.com/xpdf';
    7273    fprintf(2, '%s\n', [errMsg1 '<a href="matlab:web(''-browser'',''' url1 ''');">' url1 '</a>']);
    7374    errMsg1 = [errMsg1 url1];
     
    8384    errMsg2 = [errMsg2 url1];
    8485
    85     state = 0;
     86    state = 1;
    8687    while 1
    8788        if state
     
    9596            case 'Install pdftops'
    9697                web('-browser',url1);
     98                state = 0;
    9799            case 'Issue #137'
    98100                web('-browser',url2);
     
    141143    % system returns good = 1 even when the command runs
    142144    % Look for something distinct in the help text
    143     good = ~isempty(strfind(message, 'PostScript'));
     145    good = ~isempty(strfind(message, 'PostScript')); %#ok<STREMP>
    144146
    145147    % Display the error message if the pdftops executable exists but fails for some reason
    146     if ~good && exist(path_,'file')  % file exists but generates an error
     148    % Note: on Mac/Linux, exist('pdftops','file') will always return 2 due to pdftops.m => check for '/','.' (issue #266)
     149    if ~good && exist(path_,'file') && ~isempty(regexp(path_,'[/.]')) %#ok<RGXP1> % file exists but generates an error
    147150        fprintf('Error running %s:\n', path_);
    148151        fprintf(2,'%s\n\n',message);
  • TabularUnified issm/trunk-jpl/externalpackages/export_fig/print2array.m

    r21671 r24460  
    5151% 07/07/15: Fixed issue #83: use numeric handles in HG1
    5252% 11/12/16: Fixed cropping issue reported by Harry D.
     53% 29/09/18: Fixed issue #254: error in print2array>read_tif_img
    5354%}
    5455
     
    208209% Function to create a TIF image of the figure and read it into an array
    209210function [A, err, ex] = read_tif_img(fig, res_str, renderer, tmp_nam)
     211    A =  [];  % fix for issue #254
    210212    err = false;
    211213    ex = [];
  • TabularUnified issm/trunk-jpl/externalpackages/export_fig/print2eps.m

    r21671 r24460  
    1414% where these have been changed by MATLAB, for up to 11 different fonts.
    1515%
    16 %IN:
     16% Inputs:
    1717%   filename - string containing the name (optionally including full or
    1818%              relative path) of the file the figure is to be saved as. A
     
    2626%       crop       - Cropping flag. Deafult: 0
    2727%       fontswap   - Whether to swap non-default fonts in figure. Default: true
     28%       preserve_size - Whether to preserve the figure's PaperSize. Default: false
     29%       font_space - Character used to separate font-name terms in the EPS output
     30%                    e.g. "Courier New" => "Courier-New". Default: ''
     31%                    (available only via the struct alternative)
    2832%       renderer   - Renderer used to generate bounding-box. Default: 'opengl'
    2933%                    (available only via the struct alternative)
     
    8993% 12/06/16: Improved the fix for issue #159 (in the previous commit)
    9094% 12/06/16: Fixed issue #158: transparent patch color in PDF/EPS
     95% 18/09/17: Fixed issue #194: incorrect fonts in EPS/PDF output
     96% 18/09/17: Fixed issue #195: relaxed too-tight cropping in EPS/PDF
     97% 14/11/17: Workaround for issue #211: dashed/dotted lines in 3D axes appear solid
     98% 15/11/17: Updated issue #211: only set SortMethod='ChildOrder' in HG2, and when it looks the same onscreen; support multiple figure axes
     99% 18/11/17: Fixed issue #225: transparent/translucent dashed/dotted lines appear solid in EPS/PDF
     100% 24/03/18: Fixed issue #239: black title meshes with temporary black background figure bgcolor, causing bad cropping
     101% 21/03/19: Improvement for issue #258: missing fonts in output EPS/PDF (still *NOT* fully solved)
     102% 21/03/19: Fixed issues #166,#251: Arial font is no longer replaced with Helvetica but rather treated as a non-standard user font
     103% 14/05/19: Made Helvetica the top default font-swap, replacing Courier
     104% 12/06/19: Issue #277: Enabled preservation of figure's PaperSize in output PDF/EPS file
     105% 06/08/19: Issue #281: only fix patch/textbox color if it's not opaque
    91106%}
    92107
     
    104119    crop_amounts = nan(1,4);  % auto-crop all 4 sides by default
    105120    if isstruct(export_options)
    106         try fontswap     = export_options.fontswap;     catch, fontswap = true;     end
    107         try bb_crop      = export_options.crop;         catch, bb_crop = 0;         end
    108         try crop_amounts = export_options.crop_amounts; catch,                      end
    109         try bb_padding   = export_options.bb_padding;   catch, bb_padding = 0;      end
    110         try renderer     = export_options.rendererStr;  catch, renderer = 'opengl'; end  % fix for issue #110
     121        try preserve_size = export_options.preserve_size; catch, preserve_size = false; end
     122        try fontswap      = export_options.fontswap;      catch, fontswap = true;       end
     123        try font_space    = export_options.font_space;    catch, font_space = '';       end
     124        font_space(2:end) = '';
     125        try bb_crop       = export_options.crop;          catch, bb_crop = 0;           end
     126        try crop_amounts  = export_options.crop_amounts;  catch,                        end
     127        try bb_padding    = export_options.bb_padding;    catch, bb_padding = 0;        end
     128        try renderer      = export_options.rendererStr;   catch, renderer = 'opengl';   end  % fix for issue #110
    111129        if renderer(1)~='-',  renderer = ['-' renderer];  end
    112130    else
     131        if numel(export_options) > 3  % preserve_size
     132            preserve_size = export_options(4);
     133        else
     134            preserve_size = false;
     135        end
    113136        if numel(export_options) > 2  % font-swapping
    114137            fontswap = export_options(3);
     
    127150        end
    128151        renderer = '-opengl';
     152        font_space = '';
    129153    end
    130154
     
    135159
    136160    % Set paper size
    137     old_pos_mode = get(fig, 'PaperPositionMode');
     161    old_pos_mode    = get(fig, 'PaperPositionMode');
    138162    old_orientation = get(fig, 'PaperOrientation');
    139     set(fig, 'PaperPositionMode', 'auto', 'PaperOrientation', 'portrait');
     163    old_paper_units = get(fig, 'PaperUnits');
     164    set(fig, 'PaperPositionMode','auto', 'PaperOrientation','portrait', 'PaperUnits','points');
    140165
    141166    % Find all the used fonts in the figure
     
    155180        switch f
    156181            case {'times', 'timesnewroman', 'times-roman'}
    157                 fontsl{a} = 'times-roman';
    158             case {'arial', 'helvetica'}
    159                 fontsl{a} = 'helvetica';
     182                fontsl{a} = 'times';
     183            %case {'arial', 'helvetica'}  % issues #166, #251
     184            %    fontsl{a} = 'helvetica';
    160185            case {'newcenturyschoolbook', 'newcenturyschlbk'}
    161186                fontsl{a} = 'newcenturyschlbk';
     
    167192    % Determine the font swap table
    168193    if fontswap
    169         matlab_fonts = {'Helvetica', 'Times-Roman', 'Palatino', 'Bookman', 'Helvetica-Narrow', 'Symbol', ...
    170                         'AvantGarde', 'NewCenturySchlbk', 'Courier', 'ZapfChancery', 'ZapfDingbats'};
     194        % Issue #258: Rearrange standard fonts list based on decending "problematicness"
     195        % The issue is still *NOT* fully solved because I cannot figure out how to force
     196        % the EPS postscript engine to look for the user's font on disk
     197        % Also see: https://stat.ethz.ch/pipermail/r-help/2005-January/064374.html
     198        matlab_fonts = {'Helvetica', 'Times', 'Courier', 'Symbol', 'ZapfDingbats', ...
     199                        'Palatino', 'Bookman', 'ZapfChancery', 'AvantGarde', ...
     200                        'NewCenturySchlbk', 'Helvetica-Narrow'};
    171201        matlab_fontsl = lower(matlab_fonts);
    172202        require_swap = find(~ismember(fontslu, matlab_fontsl));
     
    211241        % Compute the order to revert fonts later, without the need of a loop
    212242        [update, M] = unique(update(1:c));
    213         [M, M] = sort(M);
     243        [dummy, M] = sort(M); %#ok<ASGLU>
    214244        update = reshape(update(M), 1, []);
    215245    end
     
    228258    % Set the line color slightly off white
    229259    set(white_line_handles, 'Color', [1 1 1] - 0.00001);
     260
     261    % MATLAB bug fix (issue #211): dashed/dotted lines in 3D axes appear solid
     262    % Note: this "may limit other functionality in plotting such as hidden line/surface removal"
     263    % reference: Technical Support Case #02838114, https://mail.google.com/mail/u/0/#inbox/15fb7659f70e7bd8
     264    hAxes = findall(fig, 'Type', 'axes');
     265    if using_hg2 && ~isempty(hAxes)  % issue #211 presumably happens only in HG2, not HG1
     266        try
     267            % If there are any axes using SortMethod~='ChildOrder'
     268            oldSortMethods = get(hAxes,{'SortMethod'});  % use {'SortMethod'} to ensure we get a cell array, even for single axes
     269            if any(~strcmpi('ChildOrder',oldSortMethods))  % i.e., any oldSortMethods=='depth'
     270                % Check if the axes look visually different onscreen when SortMethod='ChildOrder'
     271                imgBefore = print2array(fig);
     272                set(hAxes,'SortMethod','ChildOrder');
     273                imgAfter  = print2array(fig);
     274                if isequal(imgBefore, imgAfter)
     275                    % They look the same, so use SortMethod='ChildOrder' when generating the EPS
     276                else
     277                    % They look different, so revert SortMethod and issue a warning message
     278                    warning('YMA:export_fig:issue211', ...
     279                            ['You seem to be using axes that have overlapping/hidden graphic elements. ' 10 ...
     280                             'Setting axes.SortMethod=''ChildOrder'' may solve potential problems in EPS/PDF export. ' 10 ...
     281                             'Additional info: https://github.com/altmany/export_fig/issues/211'])
     282                    set(hAxes,{'SortMethod'},oldSortMethods);
     283                end
     284            end
     285        catch err
     286            % ignore
     287            a=err;  %#ok<NASGU> % debug breakpoint
     288        end
     289    end
    230290
    231291    % Workaround for issue #45: lines in image subplots are exported in invalid color
     
    259319    print(fig, options{:}, name);
    260320
     321    % Restore the original axes SortMethods (if updated)
     322    try set(hAxes,{'SortMethod'},oldSortMethods); catch, end
     323
    261324    % Do post-processing on the eps file
    262325    try
     
    291354    end
    292355
     356    % Bail out if EPS post-processing is not possible
     357    if isempty(fstrm)
     358        warning('Loading EPS file failed, so unable to perform post-processing. This is usually because the figure contains a large number of patch objects. Consider exporting to a bitmap format in this case.');
     359        return
     360    end
     361
    293362    % Fix for Matlab R2014b bug (issue #31): LineWidths<0.75 are not set in the EPS (default line width is used)
    294363    try
    295         if ~isempty(fstrm) && using_hg2(fig)
     364        if using_hg2(fig)
    296365            % Convert miter joins to line joins
    297366            %fstrm = regexprep(fstrm, '\n10.0 ML\n', '\n1 LJ\n');
     
    376445    set(white_line_handles, 'Color', [1 1 1]);
    377446
     447    % Preserve the figure's PaperSize in the output file, if requested (issue #277)
     448    if preserve_size
     449        % https://stackoverflow.com/questions/19646329/postscript-document-size
     450        paper_size = get(fig, 'PaperSize');  % in [points]
     451        fstrm = sprintf('<< /PageSize [%d %d] >> setpagedevice\n%s', paper_size, fstrm);
     452    end
     453
    378454    % Reset paper size
    379     set(fig, 'PaperPositionMode', old_pos_mode, 'PaperOrientation', old_orientation);
     455    set(fig, 'PaperPositionMode',old_pos_mode, 'PaperOrientation',old_orientation, 'PaperUnits',old_paper_units);
    380456
    381457    % Reset the font names in the figure
     
    386462    end
    387463
    388     % Bail out if EPS post-processing is not possible
    389     if isempty(fstrm)
    390         warning('Loading EPS file failed, so unable to perform post-processing. This is usually because the figure contains a large number of patch objects. Consider exporting to a bitmap format in this case.');
    391         return
    392     end
    393 
    394464    % Replace the font names
    395465    if ~isempty(font_swap)
    396466        for a = 1:size(font_swap, 2)
    397             %fstrm = regexprep(fstrm, [font_swap{1,a} '-?[a-zA-Z]*\>'], font_swap{3,a}(~isspace(font_swap{3,a})));
    398             fstrm = regexprep(fstrm, font_swap{2,a}, font_swap{3,a}(~isspace(font_swap{3,a})));
     467            fontName = font_swap{3,a};
     468            %fontName = fontName(~isspace(font_swap{3,a}));
     469            if length(fontName) > 29
     470                warning('YMA:export_fig:font_name','Font name ''%s'' is longer than 29 characters. This might cause problems in some EPS/PDF readers. Consider using a different font.',fontName);
     471            end
     472            if isempty(font_space)
     473                fontName(fontName==' ') = '';
     474            else
     475                fontName(fontName==' ') = char(font_space);
     476            end
     477
     478            % Replace all instances of the standard Matlab fonts with the original user's font names
     479            %fstrm = regexprep(fstrm, [font_swap{1,a} '-?[a-zA-Z]*\>'], fontName);
     480            %fstrm = regexprep(fstrm, [font_swap{2,a} '([ \n])'], [fontName '$1']);
     481            %fstrm = regexprep(fstrm, font_swap{2,a}, fontName);  % also replace -Bold, -Italic, -BoldItalic
     482
     483            % Times-Roman's Bold/Italic fontnames don't include '-Roman'
     484            fstrm = regexprep(fstrm, [font_swap{2,a} '(\-Roman)?'], fontName);
    399485        end
    400486    end
     
    426512        pagebb_matlab = cell2mat(textscan(aa,'%f32%f32%f32%f32'));  % dimensions bb - STEP2
    427513
     514        % 1b. Fix issue #239: black title meshes with temporary black background figure bgcolor, causing bad cropping
     515        hTitles = [];
     516        if isequal(get(fig,'Color'),'none')
     517            hAxes = findall(fig,'type','axes');
     518            for idx = 1 : numel(hAxes)
     519                hAx = hAxes(idx);
     520                try
     521                    hTitle = hAx.Title;
     522                    oldColor = hTitle.Color;
     523                    if all(oldColor < 5*eps) || (ischar(oldColor) && lower(oldColor(1))=='k')
     524                        hTitles(end+1) = hTitle; %#ok<AGROW>
     525                        hTitle.Color = [0,0,.01];
     526                    end
     527                catch
     528                end
     529            end
     530        end
     531
    428532        % 2. Create a bitmap image and use crop_borders to create the relative
    429533        %    bb with respect to the PageBoundingBox
    430534        [A, bcol] = print2array(fig, 1, renderer);
    431         [aa, aa, aa, bb_rel] = crop_borders(A, bcol, bb_padding, crop_amounts);
     535        [aa, aa, aa, bb_rel] = crop_borders(A, bcol, bb_padding, crop_amounts); %#ok<ASGLU>
     536
     537        try set(hTitles,'Color','k'); catch, end
    432538
    433539        % 3. Calculate the new Bounding Box
     
    437543        %          pagebb_matlab(1)+pagew*bb_rel(3) pagebb_matlab(2)+pageh*bb_rel(4)];
    438544        bb_new = pagebb_matlab([1,2,1,2]) + [pagew,pageh,pagew,pageh].*bb_rel;  % clearer
    439         bb_offset = (bb_new-bb_matlab) + [-1,-1,1,1];  % 1px margin so that cropping is not TOO tight
     545        bb_offset = (bb_new-bb_matlab) + [-2,-2,2,2];  % 2px margin so that cropping is not TOO tight (issue #195)
    440546
    441547        % Apply the bounding box padding
     
    444550                bb_padding = round((mean([bb_new(3)-bb_new(1) bb_new(4)-bb_new(2)])*bb_padding)/0.5)*0.5; % ADJUST BB_PADDING
    445551            end
    446             add_padding = @(n1, n2, n3, n4) sprintf(' %d', str2double({n1, n2, n3, n4}) + [-bb_padding -bb_padding bb_padding bb_padding] + bb_offset);
     552            add_padding = @(n1, n2, n3, n4) sprintf(' %.0f', str2double({n1, n2, n3, n4}) + bb_offset + bb_padding*[-1,-1,1,1]); %#ok<NASGU>
    447553        else
    448             add_padding = @(n1, n2, n3, n4) sprintf(' %d', str2double({n1, n2, n3, n4}) + bb_offset); % fix small but noticeable bounding box shift
     554            add_padding = @(n1, n2, n3, n4) sprintf(' %.0f', str2double({n1, n2, n3, n4}) + bb_offset); %#ok<NASGU> % fix small but noticeable bounding box shift
    449555        end
    450556        fstrm = regexprep(fstrm, '%%BoundingBox:[ ]+([-]?\d+)[ ]+([-]?\d+)[ ]+([-]?\d+)[ ]+([-]?\d+)', '%%BoundingBox:${add_padding($1, $2, $3, $4)}');
     
    478584                    propName = propNames{propIdx};
    479585                    if strcmp(hObj.(propName).ColorType, 'truecoloralpha')
    480                         nColors = length(StoredColors);
    481586                        oldColor = hObj.(propName).ColorData;
    482                         newColor = uint8([101; 102+floor(nColors/255); mod(nColors,255); 255]);
    483                         StoredColors{end+1} = {hObj, propName, oldColor, newColor};
    484                         hObj.(propName).ColorData = newColor;
     587                        if numel(oldColor)>3 && oldColor(4)~=255  % issue #281: only fix patch/textbox color if it's not opaque
     588                            nColors = length(StoredColors);
     589                            newColor = uint8([101; 102+floor(nColors/255); mod(nColors,255); 255]);
     590                            StoredColors{end+1} = {hObj, propName, oldColor, newColor}; %#ok<AGROW>
     591                            hObj.(propName).ColorData = newColor;
     592                        end
    485593                    end
    486594                catch
     
    508616                %Find and replace the RGBA values within the EPS text fstrm
    509617                if strcmpi(propName,'Face')
    510                     oldStr = sprintf(['\n' colorID ' RC\nN\n']);
    511                     newStr = sprintf(['\n' origRGB ' RC\n' origAlpha ' .setopacityalpha true\nN\n']);
     618                    oldStr = sprintf(['\n' colorID ' RC\n']);  % ...N\n (removed to fix issue #225)
     619                    newStr = sprintf(['\n' origRGB ' RC\n' origAlpha ' .setopacityalpha true\n']);  % ...N\n
    512620                else  %'Edge'
    513                     oldStr = sprintf(['\n' colorID ' RC\n1 LJ\n']);
     621                    oldStr = sprintf(['\n' colorID ' RC\n']);  % ...1 LJ\n (removed to fix issue #225)
    514622                    newStr = sprintf(['\n' origRGB ' RC\n' origAlpha ' .setopacityalpha true\n']);
    515623                end
    516                 foundFlags(objIdx) = ~isempty(strfind(fstrm, oldStr));
     624                foundFlags(objIdx) = ~isempty(strfind(fstrm, oldStr)); %#ok<STREMP>
    517625                fstrm = strrep(fstrm, oldStr, newStr);
    518626
  • TabularUnified issm/trunk-jpl/externalpackages/export_fig/user_string.m

    r21315 r24460  
    3333%              errors. Thanks to Christian for pointing this out.
    3434% 29/05/2015 - Save file in prefdir if current folder is non-writable (issue #74)
     35% 09/01/2018 - Fix issue #232: if the string looks like a file/folder path, ensure it actually exists
    3536
    3637    if ~ischar(string_name)
     
    102103        string = fgetl(fid);
    103104        fclose(fid);
     105
     106        % Fix issue #232: if the string looks like a file/folder path, ensure it actually exists
     107        if ~isempty(string) && any(string=='\' | string=='/') && ~exist(string) %#ok<EXIST>
     108            string = '';
     109        end
    104110    end
    105111end
Note: See TracChangeset for help on using the changeset viewer.