|
8 | 8 | % export_fig ... -<format>
|
9 | 9 | % export_fig ... -nocrop
|
10 | 10 | % export_fig ... -c[<val>,<val>,<val>,<val>]
|
11 |
| -% export_fig ... -transparent |
| 11 | +% export_fig ... -transparent or: -transparent=<color> |
12 | 12 | % export_fig ... -native
|
13 | 13 | % export_fig ... -m<val>
|
14 | 14 | % export_fig ... -r<val>
|
|
112 | 112 | % Multiple formats can be specified, without restriction.
|
113 | 113 | % For example: export_fig('-jpg', '-pdf', '-png', ...)
|
114 | 114 | % Note: '-tif','-tiff' are equivalent, and so are '-jpg','-jpeg'.
|
115 |
| -% -transparent - option indicating that the figure background is to be made |
116 |
| -% transparent (PNG,PDF,TIF,EPS,EMF formats only). Implies -noinvert. |
| 115 | +% -transparent - indicates that figure background should be made transparent. |
| 116 | +% Note: PNG,GIF,TIF,PDF,EPS,EMF formats only. Implies -noinvert. |
| 117 | +% -transparent=<color> convert all pixels in the specified color (RGB tripplet |
| 118 | +% or a Matlab predefined color string e.g. 'r'). Usage examples: |
| 119 | +% -transparent=g or -transparent=[1,.5,.2] or -transparent=80,65,235 |
| 120 | +% Optional suffix +-<value> adds tolerance to pixels color matching |
| 121 | +% for example: -transparent=g+-30 or -transparent=[1,.5,.2]+-0.1 |
| 122 | +% Note: only supported by PNG,GIF,TIF formats. |
117 | 123 | % -nocrop - option indicating that empty margins should not be cropped.
|
118 | 124 | % -c[<val>,<val>,<val>,<val>] - option indicating crop amounts. Must be
|
119 | 125 | % a 4-element vector of numeric values: [top,right,bottom,left]
|
|
399 | 405 | % 21/02/24: (3.44) Fixed: text objects with normalized units were not exported in some cases (issue #373); added check for invalid ghostscript installation (issue #365)
|
400 | 406 | % 02/05/24: (3.45) Display the builtin error message when uifigure cannot be exported (issue #387); fixed contour labels with non-default FontName incorrectly exported as Courier (issue #388)
|
401 | 407 | % 09/05/24: (3.46) Added -xkcd option (thanks @slayton); added .fig input and output format (previously undocumented & buggy); redirect .tex output to matlab2tikz utility
|
| 408 | +% 05/11/24: (3.47) Fixed -transparency in case the default bgcolor is already used in the figure (issue #398); enabled specifying non-default transparency color via -transparency parameter; suppress warnings about setting figure position; multiple -xkcd fixes |
402 | 409 | %}
|
403 | 410 |
|
404 | 411 | if nargout
|
|
436 | 443 | [fig, options] = parse_args(nargout, fig, argNames, varargin{:});
|
437 | 444 |
|
438 | 445 | % Check for newer version and exportgraphics/copygraphics compatibility
|
439 |
| - currentVersion = 3.46; |
| 446 | + currentVersion = 3.47; |
440 | 447 | if options.version % export_fig's version requested - return it and bail out
|
441 | 448 | imageData = currentVersion;
|
442 | 449 | return
|
|
675 | 682 |
|
676 | 683 | % Initialize
|
677 | 684 | tmp_nam = '';
|
| 685 | + isBgColor = false(0); |
678 | 686 | exported_files = 0;
|
679 | 687 |
|
680 |
| - % Main processing |
| 688 | + % Main processing |
681 | 689 | try
|
682 | 690 | oldWarn = warning;
|
683 | 691 |
|
|
693 | 701 | error('export_fig:padding','For bitmap output (png,jpg,tif,bmp) the padding value (-p) must be between -1<p<1')
|
694 | 702 | end
|
695 | 703 | % Print large version to array
|
696 |
| - [A, tcol, alpha] = getFigImage(fig, magnify, renderer, options, pixelpos); |
| 704 | + [A, bgcol, alpha] = getFigImage(fig, magnify, renderer, options, pixelpos); |
697 | 705 | % Get the background colour
|
| 706 | + if isempty(options.tcol), tcol = bgcol; else, tcol = options.tcol; end |
698 | 707 | if options.transparent
|
699 | 708 | if (options.png || options.alpha || options.gif || options.tif)
|
700 | 709 | try %options.aa_factor < 4 % default, faster but lines are not anti-aliased
|
701 | 710 | % If all pixels are indicated as opaque (i.e. something went wrong with the Java screen-capture)
|
702 |
| - isBgColor = A(:,:,1) == tcol(1) & ... |
703 |
| - A(:,:,2) == tcol(2) & ... |
704 |
| - A(:,:,3) == tcol(3); |
| 711 | + A2 = single(A); |
| 712 | + tcol = single(tcol); |
| 713 | + ttol = single(options.ttol); |
| 714 | + isBgColor = abs(A2(:,:,1)-tcol(1)) <= ttol & ... |
| 715 | + abs(A2(:,:,2)-tcol(2)) <= ttol & ... |
| 716 | + abs(A2(:,:,3)-tcol(3)) <= ttol; |
705 | 717 | % Set the bgcolor pixels to be fully-transparent
|
706 |
| - A(repmat(isBgColor,[1,1,3])) = 254; %=off-white % TODO: more memory efficient without repmat |
| 718 | + %A(repmat(isBgColor,[1,1,3])) = 254; %=off-white % TODO: more memory efficient without repmat |
707 | 719 | alpha(isBgColor) = 0;
|
708 | 720 | catch % older logic - much slower and causes figure flicker
|
709 | 721 | if true % to fold the code below...
|
|
805 | 817 | if options.crop
|
806 | 818 | %[alpha, v] = crop_borders(alpha, 0, 1, options.crop_amounts);
|
807 | 819 | %A = A(v(1):v(2),v(3):v(4),:);
|
808 |
| - [A, vA, vB] = crop_borders(A, tcol, options.bb_padding, options.crop_amounts); |
| 820 | + [A, vA, vB] = crop_borders(A, bgcol, options.bb_padding, options.crop_amounts); |
809 | 821 | if ~any(isnan(vB)) % positive padding
|
810 | 822 | sz = size(A); % Fix issue #308
|
811 | 823 | B = repmat(uint8(zeros(1,1,size(alpha,3))),sz([1,2])); % Fix issue #307 %=zeros(sz([1,2]),'uint8');
|
|
825 | 837 | end
|
826 | 838 | %}
|
827 | 839 | % Revert the figure properties back to their original values
|
828 |
| - set(fig, 'Units',oldFigUnits, 'Position',pos, 'Color',tcol_orig); |
| 840 | + oldWarn = warning('off','MATLAB:Figure:SetPosition'); |
| 841 | + try set(fig, 'Units',oldFigUnits, 'Position',pos, 'Color',tcol_orig); catch, end |
| 842 | + warning(oldWarn); |
829 | 843 | % Check for greyscale images
|
830 | 844 | if options.colourspace == 2
|
831 | 845 | % Convert to greyscale
|
@@ -1694,6 +1708,8 @@ function notify(filename)
|
1694 | 1708 | 'crop', true, ...
|
1695 | 1709 | 'crop_amounts', nan(1,4), ... % auto-crop all 4 image sides
|
1696 | 1710 | 'transparent', false, ...
|
| 1711 | + 'tcol', [], ... |
| 1712 | + 'ttol', 0, ... |
1697 | 1713 | 'renderer', 0, ... % 0: default, 1: OpenGL, 2: ZBuffer, 3: Painters
|
1698 | 1714 | 'pdf', false, ...
|
1699 | 1715 | 'eps', false, ...
|
@@ -1775,12 +1791,51 @@ function notify(filename)
|
1775 | 1791 | else %if ischar(thisArg) && ~isempty(thisArg)
|
1776 | 1792 | if thisArg(1) == '-'
|
1777 | 1793 | addToOptionsStr = true;
|
| 1794 | + [thisArg,extra] = strtok(thisArg,'='); |
1778 | 1795 | switch lower(thisArg(2:end))
|
1779 | 1796 | case 'nocrop'
|
1780 | 1797 | options.crop = false;
|
1781 | 1798 | options.crop_amounts = [0,0,0,0];
|
1782 | 1799 | case {'trans', 'transparent'}
|
1783 | 1800 | options.transparent = true;
|
| 1801 | + extra = strtrim(lower(extra)); |
| 1802 | + if length(extra) > 1 |
| 1803 | + [extra,tol] = strtok(extra(2:end),'+-'); %discrad '=' |
| 1804 | + if extra(1) >= 'a' && extra(1) <= 'z' |
| 1805 | + % convert predefined color => RGB |
| 1806 | + colIdx = find(extra(1)=='wrgbcmyk',1); |
| 1807 | + assert(~isempty(colIdx),'export_fig:invalid_tcol','Invalid transparent color ''%s'' specified',extra); |
| 1808 | + defaultColors = 255 * uint8([1,1,1; ... w |
| 1809 | + 1,0,0; ... r |
| 1810 | + 0,1,0; ... g |
| 1811 | + 0,0,1; ... b |
| 1812 | + 0,1,1; ... c |
| 1813 | + 1,0,1; ... m |
| 1814 | + 1,1,0; ... y |
| 1815 | + 0,0,0]); % k |
| 1816 | + options.tcol = defaultColors(colIdx,:); |
| 1817 | + else |
| 1818 | + tcol = str2num(extra); %#ok<ST2NM> |
| 1819 | + assert(isequal(size(tcol),[1,3]),'export_fig:invalid_tcol','Invalid transparent color %s specified',extra); |
| 1820 | + if all(tcol <= 1) %fractional values |
| 1821 | + tcol = 255 * tcol; %[0-1] => [0-255] |
| 1822 | + end |
| 1823 | + options.tcol = uint8(tcol); |
| 1824 | + end |
| 1825 | + if length(tol) > 2 |
| 1826 | + tol = tol(3:end); % discard '+-' |
| 1827 | + ttol = str2num(tol); %#ok<ST2NM> |
| 1828 | + assert(isscalar(ttol) && ttol>=0,'export_fig:invalid_ttol','Invalid transparent color tolerance %s specified',tol); |
| 1829 | + if ttol <= 1 %fractional value |
| 1830 | + ttol = 255 * ttol; %[0-1] => [0-255] |
| 1831 | + end |
| 1832 | + options.ttol = uint8(ttol); |
| 1833 | + elseif ~isempty(tol) % just '+-' |
| 1834 | + warning('export_fig:invalid_ttol','No transparent color tolerance specified - ignored'); |
| 1835 | + end |
| 1836 | + elseif ~isempty(extra) % just '=' |
| 1837 | + warning('export_fig:invalid_tcol','No transparent color specified - ignored'); |
| 1838 | + end |
1784 | 1839 | case 'opengl'
|
1785 | 1840 | options.renderer = 1;
|
1786 | 1841 | case 'zbuffer'
|
@@ -1929,8 +1984,8 @@ function notify(filename)
|
1929 | 1984 | error('export_fig:BadOptionValue','export_fig metadata must be a struct or cell-array of name-value pairs');
|
1930 | 1985 | end
|
1931 | 1986 | metadata = cellfun(@num2str,metadata(:)','uniform',0);
|
1932 |
| - str = sprintf(' /%s (%s)', metadata{:}); |
1933 |
| - options.gs_options{end+1} = ['-c "[' str ' /DOCINFO pdfmark"']; |
| 1987 | + extra = sprintf(' /%s (%s)', metadata{:}); |
| 1988 | + options.gs_options{end+1} = ['-c "[' extra ' /DOCINFO pdfmark"']; |
1934 | 1989 | skipNext = 1;
|
1935 | 1990 | otherwise
|
1936 | 1991 | try
|
@@ -2098,6 +2153,11 @@ function notify(filename)
|
2098 | 2153 | end
|
2099 | 2154 | end
|
2100 | 2155 |
|
| 2156 | + % transparent color cannot be specified for vector output |
| 2157 | + if ~isempty(options.tcol) && ~isbitmap(options) |
| 2158 | + error('export_fig:vector_tcol','Transparent color cannot be specified with non-bitmap outputs'); |
| 2159 | + end |
| 2160 | + |
2101 | 2161 | % Quick bail-out if no figure found
|
2102 | 2162 | if isempty(fig), return; end
|
2103 | 2163 |
|
@@ -2232,6 +2292,7 @@ function notify(filename)
|
2232 | 2292 | end
|
2233 | 2293 | end
|
2234 | 2294 | end
|
| 2295 | + |
2235 | 2296 | function options = setOptionsFormat(options, ext)
|
2236 | 2297 | switch lower(ext(2:end))
|
2237 | 2298 | case {'tif', 'tiff'}, options.tif = true;
|
@@ -2335,27 +2396,50 @@ function eps_remove_background(fname, count)
|
2335 | 2396 | options.gif || options.im || options.alpha;
|
2336 | 2397 | end
|
2337 | 2398 |
|
2338 |
| -function [A, tcol, alpha] = getFigImage(fig, magnify, renderer, options, pos) |
| 2399 | +function [A, bgcol, alpha] = getFigImage(fig, magnify, renderer, options, pos) |
2339 | 2400 | if options.transparent
|
2340 |
| - % MATLAB "feature": figure size can change when changing color in -nodisplay mode |
2341 |
| - % Note: figure background is set to off-white, not 'w', to handle common white elements (issue #330) |
2342 |
| - set(fig, 'Color',254/255*[1,1,1], 'Position',pos); |
2343 |
| - % repaint figure, otherwise Java screencapture will see black bgcolor |
2344 |
| - % Yair 19/12/21 - unnecessary: drawnow is called at top of print2array |
2345 |
| - %drawnow; |
| 2401 | + % Modify the figure's bgcolor to off-white |
| 2402 | + if isempty(options.tcol) |
| 2403 | + bgcol = uint8(254*[1,1,1]); %default bgcolor =off-white |
| 2404 | + |
| 2405 | + % Determine off-white shade not already used in the fig - issue #398 |
| 2406 | + A = getFigImage2(fig, magnify, renderer, options); % get RGB tripplets |
| 2407 | + A = unique(reshape(A,[],3),'rows'); % reshape [m,n,3] => [m*n,3] |
| 2408 | + A = sum(double(A).*(256.^[2,1,0]),2); % convert RGB tripplets => int |
| 2409 | + d = A(find(diff(A)>1,1,'last')+1) - 1; %=largest RGB value -1 (off-white) |
| 2410 | + if ~isempty(d) |
| 2411 | + n=2; while n>=0, p=256^n; bgcol(3-n)=floor(d/p); d=rem(d,p); n=n-1; end %int => RGB tripplet |
| 2412 | + end |
| 2413 | + |
| 2414 | + % MATLAB "feature": figure size can change when changing color in -nodisplay mode |
| 2415 | + % Note: figure background is set to off-white, not 'w', to handle common white elements (issue #330) |
| 2416 | + set(fig, 'Color',double(bgcol)/255, 'Position',pos); |
| 2417 | + |
| 2418 | + % repaint figure, otherwise Java screencapture will see black bgcolor |
| 2419 | + % Yair 19/12/21 - unnecessary: drawnow is called at top of print2array |
| 2420 | + %drawnow; |
| 2421 | + else |
| 2422 | + %bgcol = options.tcol; |
| 2423 | + end |
2346 | 2424 | end
|
| 2425 | + |
2347 | 2426 | % Print large version to array
|
| 2427 | + [A, bgcol, alpha] = getFigImage2(fig, magnify, renderer, options); |
| 2428 | + |
| 2429 | + % In transparent mode, set the bgcolor to white |
| 2430 | + if options.transparent |
| 2431 | + % Note: bgcol should already be [255,255,255] here, but just in case it's not... |
| 2432 | + %bgcol = uint8(254*[1,1,1]); %=off-white |
| 2433 | + end |
| 2434 | +end |
| 2435 | + |
| 2436 | +function [A, bgcol, alpha] = getFigImage2(fig, magnify, renderer, options) |
2348 | 2437 | try
|
2349 | 2438 | % The following code might cause out-of-memory errors
|
2350 |
| - [A, tcol, alpha] = print2array(fig, magnify, renderer); |
| 2439 | + [A, bgcol, alpha] = print2array(fig, magnify, renderer); |
2351 | 2440 | catch
|
2352 | 2441 | % This is more conservative in memory, but perhaps kills transparency(?)
|
2353 |
| - [A, tcol, alpha] = print2array(fig, magnify/options.aa_factor, renderer, 'retry'); |
2354 |
| - end |
2355 |
| - % In transparent mode, set the bgcolor to white |
2356 |
| - if options.transparent |
2357 |
| - % Note: tcol should already be [255,255,255] here, but just in case it's not... |
2358 |
| - tcol = uint8(254*[1,1,1]); %=off-white |
| 2442 | + [A, bgcol, alpha] = print2array(fig, magnify/options.aa_factor, renderer, 'retry'); |
2359 | 2443 | end
|
2360 | 2444 | end
|
2361 | 2445 |
|
|
0 commit comments