print_convert

PURPOSE ^

PRINT_CONVERT: print figures with anti-aliasing and trim them

SYNOPSIS ^

function print_convert(filename, varargin)

DESCRIPTION ^

PRINT_CONVERT: print figures with anti-aliasing and trim them
  PRINT_CONVERT(FILENAME,OPT) prints current figure to FILENAME, which 
  must include extenstion.

  OPT is either a string specifying dpi in the format '-r150' or a struct
  with (some of) these fields:
   opt.resolution   = 150;              % 150 dpi (default: 125)
   opt.pagesize     = [width, height];  % in current PageUnits or 'auto'
                                        % to match the size on the screen
                                        % (default: [8, 6] inches)
   opt.jpeg_quality = 85;               % jpeg quality (default: 85)
   opt.imwrite_opts = {'BitDepth',8};   % options to IMWRITE (default: '')
   opt.horz_cut     = 20;               % remove horizontal gaps larger
                                        % than 50 pixels (default: 20)
   opt.horz_space   = 10;               % replace the removed horizontal
                                        % gaps with 10 px of background
                                        % (default: 10)
   opt.vert_cut     = 20;               % remove vertical gaps larger
                                        % than 50 pixels (default: 20)
   opt.vert_space   = 10;               % replace the removed vertical
                                        % gaps with 10 px of background
                                        % (default: 10)
   opt.supersampling_factor = 2;        % anti-aliasing (default: 1 for
                                        % images, 2 for graphs). Higher is
                                        % smoother.
   opt.crop_slack   = [top,bot,left,right] %don't crop right to boundary
   opt.figno        = number            % print figure, otherwise gca

  Note that opt.imwrite_opts takes precedence over opt.jpeq_quality.

  print_convert has pre-version 3.7 options, which are deprecated

  Examples
   print_convert('outname.png')         % uses default options
   print_convert outname.png
   print_convert outname.png -r150      % set dpi=150
   print_convert outname.png -p10x20    % pagesize 10x20
   print_convert outname.png -pauto     % pagesize = size on screen
   print_convert('outname.png',opts);   % use options

 See also IMWRITE

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function print_convert(filename, varargin)
0002 %PRINT_CONVERT: print figures with anti-aliasing and trim them
0003 %  PRINT_CONVERT(FILENAME,OPT) prints current figure to FILENAME, which
0004 %  must include extenstion.
0005 %
0006 %  OPT is either a string specifying dpi in the format '-r150' or a struct
0007 %  with (some of) these fields:
0008 %   opt.resolution   = 150;              % 150 dpi (default: 125)
0009 %   opt.pagesize     = [width, height];  % in current PageUnits or 'auto'
0010 %                                        % to match the size on the screen
0011 %                                        % (default: [8, 6] inches)
0012 %   opt.jpeg_quality = 85;               % jpeg quality (default: 85)
0013 %   opt.imwrite_opts = {'BitDepth',8};   % options to IMWRITE (default: '')
0014 %   opt.horz_cut     = 20;               % remove horizontal gaps larger
0015 %                                        % than 50 pixels (default: 20)
0016 %   opt.horz_space   = 10;               % replace the removed horizontal
0017 %                                        % gaps with 10 px of background
0018 %                                        % (default: 10)
0019 %   opt.vert_cut     = 20;               % remove vertical gaps larger
0020 %                                        % than 50 pixels (default: 20)
0021 %   opt.vert_space   = 10;               % replace the removed vertical
0022 %                                        % gaps with 10 px of background
0023 %                                        % (default: 10)
0024 %   opt.supersampling_factor = 2;        % anti-aliasing (default: 1 for
0025 %                                        % images, 2 for graphs). Higher is
0026 %                                        % smoother.
0027 %   opt.crop_slack   = [top,bot,left,right] %don't crop right to boundary
0028 %   opt.figno        = number            % print figure, otherwise gca
0029 %
0030 %  Note that opt.imwrite_opts takes precedence over opt.jpeq_quality.
0031 %
0032 %  print_convert has pre-version 3.7 options, which are deprecated
0033 %
0034 %  Examples
0035 %   print_convert('outname.png')         % uses default options
0036 %   print_convert outname.png
0037 %   print_convert outname.png -r150      % set dpi=150
0038 %   print_convert outname.png -p10x20    % pagesize 10x20
0039 %   print_convert outname.png -pauto     % pagesize = size on screen
0040 %   print_convert('outname.png',opts);   % use options
0041 %
0042 % See also IMWRITE
0043  
0044 % (C) Andy Adler and Bartlomiej Grychtol 2010-2021. License: GPL v2 or v3.
0045 % $Id: print_convert.m 6505 2022-12-30 14:52:55Z aadler $
0046 %
0047 %  Compatibility with pre-3.7 features:
0048 %  ------------------------------------
0049 %  PRINT_CONVERT(FILENAME, OPTIONS, PAGEHWR)
0050 %
0051 %  FILENAME : filename to print to file type is the extension
0052 %  OPTIONS  : specify dpi as '-density N'
0053 %
0054 %   print_convert('outname.png','-density 150') % resolution to 150 dpi
0055  
0056 if ischar(filename) && strcmp(filename,'UNIT_TEST'); do_unit_test; return; end
0057 
0058 pp = parse_options(filename, varargin{:});
0059 
0060 
0061 % change properties
0062 pp = set_prop(pp,'InvertHardCopy','off');
0063 pp = set_prop(pp,'Color','w');
0064 pp = set_pagesize(pp);
0065 
0066 % revert changed properties at exit
0067 cleanupObj = onCleanup(@() set(pp.figno, pp.old{:})); % current state of pp.old only!
0068 
0069 % print to array
0070 im = print(pp.figno,'-RGBImage',pp.resolution);
0071 
0072 im = bitmap_downsize(im, pp.factor);
0073 im = crop_image(im,pp);
0074 try
0075    imwrite(im,pp.filename,pp.imwrite_opts{:});
0076 catch e
0077    eidors_msg(['Call to IMWRITE failed.'...
0078                'Probably opt.imwrite_opts is incorrect for %s files.'],...
0079                upper(pp.fmt), 1);
0080    disp('opt.imwrite_opts:');
0081    disp(pp.imwrite_opts);
0082    rethrow(e);
0083 end
0084 
0085 % place file in clipboard
0086 if pp.clip
0087    copy2clipboard(pp)
0088 end
0089 
0090 function pp = set_pagesize(pp)
0091 if ~isfield(pp, 'pagesize') % no user definition
0092     pos = [0.25 0.25 8 6]; % Matlab's default before R2016a
0093     if isfield(pp, 'aspect_ratio') % old interface
0094         pos(4) = pos(3) * pp.aspect_ratio;
0095     end
0096     pp = set_prop(pp,   'PaperUnits','inches',...
0097                         'PaperPositionMode','manual', ...
0098                         'PaperPosition', pos);
0099 elseif ischar(pp.pagesize)
0100     switch pp.pagesize
0101         case 'auto'
0102             pp = set_prop(pp, 'PaperPositionMode', 'auto');
0103         otherwise
0104             warning('Page size %s not understood', pp.pagesize);
0105     end
0106 else
0107     pos = [0 0 pp.pagesize];
0108     pp = set_prop(pp, ...
0109         'PaperPositionMode','manual', ...
0110         'PaperSize', pp.pagesize+1, ... % big enough
0111         'PaperPosition', pos);
0112 end    
0113 
0114 function pp = set_prop(pp, varargin)
0115     prop = {};
0116     for i = 1:2:numel(varargin)
0117         prop(1, end+1) = varargin(i);
0118         prop{2, end  } = get(pp.figno, varargin{i});
0119     end
0120     pp.old = [fliplr(prop), pp.old]; % store in reverse order to revert correctly
0121     set(pp.figno, varargin{:})
0122         
0123 
0124 function copy2clipboard(pp)
0125    if isunix()
0126       cmd = sprintf(['xclip -selection ' ... 
0127           'clipboard -t image/%s -i %s'], ...
0128             pp.fmt, pp.filename);
0129       [status] = system(cmd);
0130       if status ~=0
0131           warning 'calling xclip to clipboard failed';
0132       end
0133    else
0134       cmd = 'Powershell -command Set-Clipboard -Path ';
0135       status = system([cmd pp.filename]);
0136       if status ~=0
0137         warning 'Powershell Set-Clipboard failed';
0138       end
0139    end
0140 
0141 function im = crop_image(im,pp)
0142    tu = pp.crop_slack(1);
0143    bu = pp.crop_slack(2) + 1; %remove starting one more
0144    lu = pp.crop_slack(3);
0145    ru = pp.crop_slack(4) + 1;
0146 
0147    szim = size(im);
0148    bdr = squeeze(mean(double(im(1,:,:)),2));
0149  
0150    isbdr = true(szim(1),szim(2));
0151    for i=1:szim(3);
0152      isbdr = isbdr & (im(:,:,i) == bdr(i));
0153    end
0154  
0155    horz = [true,all(isbdr,1),true];
0156    horzpt = find(diff(horz)) - 1; % first 'true'
0157    if isempty(horzpt)
0158       eidors_msg('Image is blank. Cropping aborted.',1);
0159       return
0160    end
0161    im(:,horzpt(end)+ru:end,:)= []; % remove higher first
0162    if pp.horz_cut >0;
0163       horz_e_pt = find(diff(horz)==-1) -1; horz_e_pt(1) = [];
0164       horz_s_pt = find(diff(horz)==+1)   ; horz_s_pt(end) = [];
0165       idx = find(horz_e_pt - horz_s_pt > pp.horz_cut);
0166       for i=fliplr(idx) % remove higher first
0167         im(:,horz_s_pt(i)+pp.horz_space:horz_e_pt(i),:)= [];
0168       end
0169    end
0170    im(:,1:horzpt(1)-lu ,:)= [];
0171  
0172    vert = [true,all(isbdr,2)',true];
0173    vertpt = find(diff(vert)) - 1; % first 'true'
0174    im(vertpt(end)+bu:end,:,:)= [];
0175    if pp.vert_cut >0;
0176       vert_e_pt = find(diff(vert)==-1) -1; vert_e_pt(1) = [];
0177       vert_s_pt = find(diff(vert)==+1)   ; vert_s_pt(end) = [];
0178       idx = find(vert_e_pt - vert_s_pt > pp.vert_cut);
0179       for i=fliplr(idx) % remove higher first
0180         im(vert_s_pt(i)+pp.vert_space:vert_e_pt(i),:,:)= [];
0181       end
0182    end
0183    im(1:vertpt(1)-tu ,:,:)= [];
0184  
0185     
0186 % factor = 1 if all plots only contain images, 2 otherwise
0187 function f = default_factor
0188    f = 1; % default for images
0189    sp = get(gcf,'Children'); % subplots
0190    for i = 1:length(sp)
0191       obj = get(sp(i),'Children');
0192       tp  = get(obj,'Type');
0193       if ~all(strcmp(tp,'image'))
0194          f = 2;
0195          return;
0196       end
0197    end 
0198    
0199 function fmt = parse_format(filename)   
0200     ext = lower(regexp(filename,'(?<=\.).+$','match'));
0201     if isempty(ext); error('no filename extension detected (%s)',filename); end
0202     switch ext{1}
0203        case {'jpg', 'jpeg'}
0204           fmt = 'jpg';
0205        case {'j2c', 'j2k', 'jp2'}
0206           fmt = 'jp2';
0207        case {'tif','tiff'}
0208           fmt = 'tif';
0209        otherwise
0210           fmt = ext{1};
0211     end
0212        
0213 function pp = parse_options(filename,varargin)
0214    
0215    pp.fmt = parse_format(filename);
0216    if strcmp(filename, ['{clipboard}.',pp.fmt])
0217       pp.clip = true;
0218       pp.filename = [tempname(),'.',pp.fmt]; 
0219    else
0220       pp.clip = false;
0221       pp.filename = filename;
0222    end
0223 
0224    pp.jpeg_quality = 85; % default jpeg quality
0225    pp.imwrite_opts = {}; % initial
0226    pp.horz_cut = 20;
0227    pp.horz_space = 10;
0228    pp.vert_cut = 20;
0229    pp.vert_space = 10;
0230    pp.factor = default_factor;
0231    pp.resolution = sprintf('-r%d',125 * pp.factor);
0232    pp.crop_slack = [0,0,0,0];
0233    if exist('OCTAVE_VERSION')
0234       pp.figno = gcf;
0235    else
0236       pp.figno = get(gcf,'Number');
0237    end
0238    pp.old = {};
0239    
0240  
0241 % Old options
0242    if nargin == 1   
0243       return; 
0244    end
0245  
0246    opt = varargin{1};
0247    if ischar(opt)
0248       for i = 1:length(varargin); opt = varargin{i}; parseok=false;
0249           val =regexp(opt,'-density (\d+)','tokens');
0250           if ~isempty(val);
0251              pp.resolution = sprintf('-r%d', str2double(val{1}{1}) * pp.factor);
0252              parseok=true;
0253           end
0254 
0255           val =regexp(opt,'-r(\d+)','tokens');
0256           if ~isempty(val);
0257              pp.resolution = sprintf('-r%d', str2double(val{1}{1}) * pp.factor);
0258              parseok=true;
0259           end
0260 
0261           if strcmp(opt,'-pauto') 
0262              pp.pagesize = 'auto';
0263              parseok=true;
0264           end
0265 
0266           val =regexp(opt,'-p(\d+)x(\d+)','tokens');
0267           if ~isempty(val);
0268              pp.pagesize = [str2num(val{1}{1}), str2num(val{1}{2})];
0269              parseok=true;
0270           end
0271 
0272           if ~parseok
0273              eidors_msg('print_convert: option (%s) not understood',opt,0)
0274           end
0275       end
0276    elseif isstruct(opt)
0277      if isfield(opt,'figno');
0278         pp.figno = opt.figno;
0279      end
0280      if isfield(opt,'supersampling_factor')
0281         pp.factor = opt.supersampling_factor;
0282      end
0283      if isfield(opt,'resolution');
0284          pp.resolution = sprintf('-r%d', opt.resolution * pp.factor);
0285      else
0286          pp.resolution = sprintf('-r%d',125 * pp.factor);
0287      end
0288      if isfield(opt,'pagesize');
0289          pp.pagesize = opt.pagesize;
0290      end
0291      % TODO, this code can copy from opt to pp
0292      if isfield(opt,'jpeg_quality')
0293         pp.jpeg_quality = opt.jpeg_quality;
0294      end
0295      if strcmp(pp.fmt,'jpg')
0296         pp.imwrite_opts = {'quality',pp.jpeg_quality}; 
0297      end
0298      if isfield(opt,'imwrite_opts');
0299         pp.imwrite_opts = opt.imwrite_opts;
0300         if strcmp(pp.fmt,'jpg') && ~any(strcmpi(pp.imwrite_opts,'quality'))
0301            pp.imwrite_opts(end+1:end+2) = {'quality',pp.jpeg_quality};
0302         end
0303      end
0304     
0305      if isfield(opt,'horz_cut');
0306          pp.horz_cut = opt.horz_cut;
0307      end
0308      if isfield(opt,'vert_cut');
0309          pp.vert_cut = opt.vert_cut;
0310      end
0311      if isfield(opt,'vert_space');
0312         if opt.vert_space >= pp.vert_cut;
0313            warning('Option vert_space must be smaller than vert_cut. Ingoring');
0314         else
0315            pp.vert_space = opt.vert_space;
0316         end
0317      end
0318      if isfield(opt,'horz_space');
0319         if opt.horz_space >= pp.horz_cut;
0320            warning('Option vert_space must be smaller than vert_cut. Ingoring');
0321         else
0322            pp.horz_space = opt.horz_space;
0323         end
0324      end
0325      if isfield(opt,'crop_slack');
0326         pp.crop_slack = opt.crop_slack;
0327      end
0328    else
0329       error('Can''t parse options');
0330    end
0331  
0332  
0333 function do_unit_test
0334    fprintf('Doing UNIT_TEST for print_convert\n');
0335    fid = fopen('print_convert_test.html','w');
0336    fprintf(fid,'<HTML><BODY>\n');
0337    for i=1:26;
0338      switch i;
0339        case {9,10}; typ = 'jpg';
0340        otherwise; typ = 'png';
0341      end
0342      fprintf(fid,...
0343      '<H1>%02d</H1><table border=1><tr><td><img src="pc%02d.%s"></table>\n',i,i,typ);
0344    end
0345    fprintf(fid,'</BODY></HTML>\n');
0346    fclose(fid);
0347    eidors_msg('TO VIEW OUTPUT, OPEN FILE print_convert_test.html',1);
0348  
0349    im = mk_image( ng_mk_cyl_models(1,[16,.5],.05),1);
0350    clf; show_fem(im);
0351    print_convert pc01.png
0352  
0353    im = mk_image( mk_common_model('b2c2',8), 1:256);
0354    clf; show_fem(im);
0355    print_convert pc02.png
0356  
0357  
0358    clf; subplot(221); show_fem(im); 
0359         subplot(224); show_slices(im); 
0360    print_convert pc03.png
0361  
0362    print_convert pc04.png '-density 50'
0363    print_convert pc05.png '-r100'
0364 
0365    print_convert pc05.png '-p10x20'
0366    print_convert pc05.png '-pauto'
0367    print_convert pc06.png '-r100' '-p10x20'
0368  
0369 % No longer supported ... not useful
0370 %  print_convert('pc06.png', '-r100' , 1/8)
0371 %  print_convert('pc06.png', '-r100' , 3/1)
0372  
0373    opt.resolution = 100;
0374    print_convert('pc07.png', opt);
0375    opt.pagesize = [8,2];
0376    print_convert('pc08.png', opt);
0377  
0378    print_convert('pc09a.jpg');
0379    
0380    opt.pagesize = [8,6];
0381    print_convert('pc09.jpg', opt);
0382   
0383    
0384    opt.imwrite_opts = {'Quality',20};
0385    print_convert('pc10.jpg', opt);
0386    
0387    opt.imwrite_opts = {'Quality',100};
0388    print_convert('pc10b.jpg', opt);
0389  
0390    opt.imwrite_opts = {};
0391    opt.horz_cut = 50;
0392    print_convert('pc11.png', opt);
0393  
0394    opt.vert_cut = 50;
0395    print_convert('pc12.png', opt);
0396  
0397    clf; subplot(331); show_fem(im); 
0398         subplot(335); show_slices(im); 
0399         subplot(339); show_slices(im); 
0400    opt.vert_cut = 30;
0401    print_convert('pc13.png', opt);
0402    
0403    im = mk_image( ng_mk_cyl_models(1,[16,.5],.05),1);
0404    clf; show_fem(im);
0405    clear opt; opt.supersampling_factor = 1;
0406    print_convert('pc14.png', opt);
0407  
0408    clear opt; opt.supersampling_factor = 2;
0409    print_convert('pc15.png', opt);
0410  
0411    clear opt; opt.supersampling_factor = 3;
0412    print_convert('pc16.png', opt);
0413    
0414    clear opt; opt.supersampling_factor = 4;
0415    print_convert('pc17.png', opt);
0416    
0417    clear opt; opt.supersampling_factor = 8;
0418    print_convert('pc18.png', opt);
0419  
0420

Generated on Fri 30-Dec-2022 19:44:54 by m2html © 2005