Code covered by the BSD License  

Highlights from
pdfapp: a pedestrian pdf concatenator

pdfapp: a pedestrian pdf concatenator

by

 

31 Jan 2010 (Updated )

PDFAPP appends PDF files to a new PDF file

r=pdfapp(fapp,varargin)
%PDFAPP		appends PDF files to a new PDF file
%
%		PDFAPP concatenates existing PDF files into
%		one PDF file using a user installed version
%		of GHOSTSCRIPT (GS)
%		in essence, it creates an input file @INPUT
%		for the GS application and runs it by a
%		call to SYSTEM()
%
%INSTALLATION
%-------------------------------------------------------------------------------
%		PDFAPP looks for the location of the GS suite in a
%		preference, which is kept across MATLAB sessions in
%			gsloc=getpref('pdfapp','app')
%
%		when PDFAPP is run for the first time, a file dialog
%		asks the user to point to the GS application, which
%		typically is
%			GSPATH/gswin32c.exe	[= command line GS]
%		eg,	g:\usr\gs\gs8.64\bin\gswin32c.exe
%		on a microsoft windows (MS) system and automatically
%		creates the preference
%
%		see also: print, system, setpref, getpref, rmpref
%
%SYNTAX
%-------------------------------------------------------------------------------
%		    PDFAPP(FAPP,FLST1,...,OPT1,FLSTx,...,FLSTn,OPTx,...,OPTn)
%		R = PDFAPP(...)
%
%INPUT
%-------------------------------------------------------------------------------
% FAPP	:	name of file to append to
% FLST	:	file list(s)
%		- cell of char strings
%		- char string
%
% OPT		description
% -------------------------------------------------------
%   -1	:	overwrite existing output file
%    1	:	show PDF after creation		[MS only]
%    2	:	do NOT show runtime processing
%    3	:	save input file in GS.INF
%		- overwrite existing file!
%NOTE
%-------------------------------------------------------------------------------
%		it is NOT possible to append a PDF file onto itself
%
%EXAMPLE
%-------------------------------------------------------------------------------
%	%	create two PDF files in the current folder
%		surf(peaks(64));
%		print -dpdf -r300 ex_01.pdf;
%		plot(1:10,'-ks');
%		print -dpdf -r600 ex_02.pdf;
%	%	append several copies and show result [option: 1]
%	%	delete output file if it exists [option -1]
%		d=dir('ex_*.pdf');
%		pdfapp('ex_03',{d.name},'ex_01.pdf','ex_02.pdf',-1,1);

% created:
%	us	15-Mar-2006 us@neurol.unizh.ch
% modified:
%	us	16-Mar-2010 19:45:32
%
% localid:	us@USZ|ws-nos-36362|x86|Windows XP|7.10.0.499.R2010a

%-------------------------------------------------------------------------------
function	r=pdfapp(fapp,varargin)

		magic='PDFAPP';
		pver='16-Mar-2010 19:45:32';

		r=PDFAPP_getapp(magic,pver);
		par={
			['-I"',r.gsroot,'\ps_files"']
			['-I"',r.gsroot,'\fonts"']
			'-dQUIET'
			'-dNOPAUSE'
			'-dBATCH'
			'-sPAPERSIZE=a4'
			'-sDEVICE=pdfwrite'
		};

		finf='gs.inf';
		fpdf='.pdf';
		opt=[];
		sflg=false;

	if	nargin < 2
		help(mfilename);
	if	~nargout
		clear	r;
	end
		return;
	end

		in=cellfun(@isnumeric,varargin);
	if	any(in)
		opt=[varargin{in}];
		varargin(in)=[];
	if	any(opt==2)
		sflg=true;
	end
	end
		fapp=PDFAPP_getname(fapp,fpdf);

		r.opt=opt;
		r.par=par;
		r.out=fapp;

% check for existence of output file
	if	~any(opt==-1)				&&...
		exist(fapp,'file')
		warning('pdfapp:write','%s> cannot overwrite existing file: %s',magic,fapp);
		return;
	end

		t0=clock;
		par=[
			par
			{['-sOUTPUTFILE="',r.out,'"']}
		];

% create input file list
		PDFAPP_disp(sflg,sprintf('PDFAPP> %s',r.out));
		cc=0;
	for	j=1:numel(varargin)
		flst=varargin{j};

	if	~iscell(flst)				&&...
		ischar(flst)
		flst={flst};
	end

		nl=numel(flst);
	for	i=1:nl
		cf=PDFAPP_getname(flst{i},fpdf);
	if	~strcmp(cf,fapp)			&&...
		exist(cf,'file');
		cc=cc+1;
		PDFAPP_disp(sflg,sprintf('%5d > %s',cc,cf));
		r.in=[
			r.in
			['"',cf,'"']
		];
	else
		PDFAPP_disp(sflg,sprintf('%5d ! %s',0,cf));
	end
	end
	end

% create GS input file
	if	cc
		com=[
			par
			r.in
		];

		[fp,msg]=fopen(r.gsipar,'wt');
	if	fp > 0
		txt=sprintf('%s\n',com{:});
		fwrite(fp,txt,'uchar');
		fclose(fp);
	else
		error('%s> cannot open output file <%s>\n%s',magic,fapp,msg);
	end
		r.gscoml=sprintf('"%s" @%s',r.gsexec,r.gsipar);

		[ss,msg]=system(r.gscoml);
	if	ss
		error(msg);
	end
		d=dir(fapp);
		siz=d.bytes/1024;
		PDFAPP_disp(sflg,sprintf('PDFAPP> %s   [%d kb]',fapp,round(siz)));
	else
		siz=0;
		PDFAPP_disp(sflg,sprintf('PDFAPP> %s   [not created]',fapp));
	end
		r.runtime=etime(clock,t0);

		r.par=par;
		r.nin=numel(r.in);
		r.in=r.in;
		r.size=siz;

	if	any(r.opt==3)
		movefile(r.gsipar,finf);
		r.gsipar=finf;
	else
	if	exist(r.gsipar,'file')
		delete(r.gsipar);
	end
		r.gsipar=[];
	end
	if	ispc
	if	any(r.opt==1)				&&...
		r.nin					&&...
		exist(r.out,'file')
		system(r.out);
	end
	end
	if	~nargout
		clear	r;
	end
end
%-------------------------------------------------------------------------------
function	r=PDFAPP_getapp(magic,pver)

		r.magic=magic;
		r.ver=pver;
		r.MLver=version;
		r.runtime=[];
		r.opt=[];
		r.gsroot=[];
		r.gsfile=[];
		r.gsexec=[];
		r.gsipar=['gs_',reshape(num2hex(rand(1,2)).',1,[]),'.inf'];
		r.gscoml=[];
		r.par={};
		r.nin=0;
		r.in={};
		r.out=[];

		app=getpref(lower(magic));
	if	isempty(app)
		[gsexec,gsroot]=uigetfile({'*.exe'},'selecte GHOSTSCRIPT executable');
		[gsroot,gsbin]=fileparts(gsroot(1:end-1));
		gsfile=[gsroot,filesep,gsbin,filesep,gsexec];
		setpref(lower(magic),'app',gsfile);
	else
		gsfile=app.app;
	end
	if	~exist(gsfile,'file')
		rmpref(lower(magic));
		error('%s> cannot find GHOSTSCRIPT executable: %s',magic,gsfile);
	end
		r.gsfile=gsfile;
		[r.gsroot,r.gsexec]=fileparts(gsfile);
		[r.gsroot,gsbin]=fileparts(r.gsroot(1:end-1));	%#ok
		r.gsexec=[r.gsroot,filesep,'bin',filesep,r.gsexec];
end
%-------------------------------------------------------------------------------
function	fapp=PDFAPP_getname(fapp,fpdf)

		[fpat,frot,fext]=fileparts(fapp);
	if	isempty(fpat)
		fpat=cd;
	end
	if	isempty(fext)
		fext=fpdf;
	end
		fapp=[fpat,filesep,frot,fext];
end
%-------------------------------------------------------------------------------
function	PDFAPP_disp(sflg,txt)

	if	~sflg
		disp(txt);
	end
end
%-------------------------------------------------------------------------------

Contact us