source: MML/trunk/machine/SOLEIL/common/toolbox/export_fig/export_fig.m @ 4

Last change on this file since 4 was 4, checked in by zhangj, 11 years ago

Initial import--MML version from SOLEIL@2013

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