1function
eps2pdf(source, dest, crop, append, gray, quality, gs_options) %#ok<*RGXPI>
2%EPS2PDF Convert an eps file to pdf format
using ghostscript
7%
eps2pdf(source, dest, crop, append)
8%
eps2pdf(source, dest, crop, append, gray)
9%
eps2pdf(source, dest, crop, append, gray, quality)
10%
eps2pdf(source, dest, crop, append, gray, quality, gs_options)
12% This function converts an eps file to pdf format. The output can be
13% optionally cropped and also converted to grayscale. If the output pdf
14% file already exists then the eps file can optionally be appended as a
new
15% page on the end of the eps file. The level of bitmap compression can also
18% This function
requires that you have
ghostscript installed on your system.
19% Ghostscript can be downloaded from: http:
22% source - filename of the source eps file to convert. The filename is
23% assumed to already have the extension
".eps".
24% dest - filename of the destination pdf file. The filename is assumed
25% to already have the extension
".pdf".
26% crop -
boolean indicating whether to crop the borders off the pdf.
28% append -
boolean indicating whether the eps should be appended to the
29% end of the pdf as a
new page (
if the pdf exists already).
31% gray -
boolean indicating whether the output pdf should be grayscale
32% or not. Default:
false.
33% quality - scalar indicating the level of image bitmap quality to
34% output. A larger value gives a higher quality. quality > 100
35% gives lossless output. Default:
ghostscript prepress
default.
36% gs_options - optional
ghostscript options (e.g.:
'-dNoOutputFonts'). If
37% multiple options are needed, enclose in call array: {
'-a',
'-b'}
39% Copyright (C) Oliver Woodford 2009-2014, Yair Altman 2015-
41% Suggestion of appending pdf files provided by Matt C at:
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.
48% 26/02/15: If temp dir is not writable, use the dest folder
for temp destination files (Javier Paredes)
49% 28/02/15: Enable users to specify optional
ghostscript options (issue #36)
50% 01/03/15: Upon GS error, retry without the -sFONTPATH= option (
this might solve
51% some /findfont errors according to James Rankin, FEX Comment 23/01/15)
52% 23/06/15: Added extra debug
info in
case of
ghostscript error; code indentation
53% 04/10/15: Suggest a workaround
for issue #41 (missing font path; thanks Mariia Fedotenkova)
54% 22/02/16: Bug fix from latest
release of
this file (workaround
for issue #41)
55% 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
59% 15/01/20: Added information about the GS/destination filepath in
case of error (issue #294)
60% 20/01/20: Attempted fix
for issue #285: unsupported patch transparency in some Ghostscript versions
61% 12/02/20: Improved fix
for issue #285: add -dNOSAFER and -dALLOWPSTRANSPARENCY (thanks @linasstonys)
62% 26/08/21: Added GS
version to error message; fixed some problems with PDF append (issue #339)
63% 20/02/23: Added GS fixes suggested by @scholnik (issues #285, #368)
66 downsampleOptions = [
'-dDownsampleColorImages=false ' ...
67 '-dDownsampleGrayImages=false ' ...
68 '-dDownsampleMonoImages=false']; %issue #368
69 options = [
'-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress ' ...
70 downsampleOptions
' -sOutputFile="' dest
'"'];
74 options = [options
' -dEPSCrop'];
80 options = [options
' -sFONTPATH="' fp
'"'];
83 % Set the grayscale option
85 options = [options
' -sColorConversionStrategy=Gray -dProcessColorModel=/DeviceGray'];
88 % Set the bitmap quality
90 if nargin > 5 && ~isempty(quality)
91 qualityOptions =
' -dAutoFilterColorImages=false -dAutoFilterGrayImages=false';
93 qualityOptions = [qualityOptions
' -dColorImageFilter=/FlateEncode -dGrayImageFilter=/FlateEncode'];
94 qualityOptions = [qualityOptions
' -c ".setpdfwrite << /ColorImageDownsampleThreshold 10 /GrayImageDownsampleThreshold 10 >> setdistillerparams"'];
96 qualityOptions = [qualityOptions
' -dColorImageFilter=/DCTEncode -dGrayImageFilter=/DCTEncode'];
97 v = 1 + (quality < 80);
98 quality = 1 - quality / 100;
99 s = sprintf(
'<< /QFactor %.2f /Blend 1 /HSample [%d 1 1 %d] /VSample [%d 1 1 %d] >>', quality, v, v, v, v);
100 qualityOptions = [qualityOptions
' -c ".setpdfwrite << /ColorImageDict ' s
' /GrayImageDict ' s
' >> setdistillerparams"'];
102 options = [options qualityOptions];
105 % Enable users to specify optional
ghostscript options (issue #36)
106 if nargin > 6 && ~isempty(gs_options)
107 if iscell(gs_options)
108 gs_options = sprintf(
' %s',gs_options{:});
109 elseif ~ischar(gs_options)
110 error(
'gs_options input argument must be a string or cell-array of strings');
112 gs_options = [
' ' gs_options];
114 options = [options gs_options];
117 % Check
if the output file exists
118 if nargin > 3 && append && exist(dest,
'file') == 2
119 % Store the original filesize
for later use below
121 file_info = dir(dest);
122 orig_bytes = file_info.bytes;
126 % File exists - append current figure to the end
127 tmp_nam = [tempname
'.pdf'];
128 [fpath,fname,fext] = fileparts(tmp_nam);
130 % Ensure that the temp dir is writable (Javier Paredes 26/2/15)
131 fid = fopen(tmp_nam,'w');
136 % Temp dir is not writable, so use the dest folder
137 fpath = fileparts(dest);
138 tmp_nam = fullfile(fpath,[fname fext]);
140 % Copy the original (dest) pdf file to temporary folder
141 copyfile(dest, tmp_nam);
142 % Produce an interim pdf of the source eps, rather than adding the eps directly (issue
#233)
143 %
this will
override the original (dest) pdf file
144 orig_options = options;
146 [~,fname] = fileparts(tempname);
147 tmp_nam2 = fullfile(fpath,[fname fext]); % ensure
using a writable folder (not necessarily tempdir)
148 copyfile(dest, tmp_nam2);
149 % Add the original pdf (tmp_nam) and interim pdf (dest=>tmp_nam2) as inputs to
ghostscript
150 %options = [options
' -f "' tmp_nam
'" "' source
'"']; % append the source eps to dest pdf
151 options = [options
' -f "' tmp_nam
'" "' tmp_nam2
'"']; % append the interim pdf to dest pdf
155 % The output pdf should now be in dest
157 % If the returned message is non-empty, a possible error may have
158 % occured, so check the file size to ensure whether the file grew
159 if ~isempty(message) && ~isempty(orig_bytes)
160 file_info = dir(dest);
161 new_bytes = file_info.bytes;
162 if new_bytes < orig_bytes + 100
163 % Looks like nothing substantial (
if anything) was appended to
164 % the original pdf, so
try adding the eps file directly (issue #339)
165 options = [orig_options
' -f "' tmp_nam
'" "' source
'"']; % append the source eps to dest pdf
170 % Delete the intermediate (temporary) files
174 % Delete the intermediate files and rethrow the error
180 % File doesn
't exist or should be over-written
181 % Add the source eps file as input to ghostscript
182 options = [options ' -f
"' source '"'];
183 % Convert to pdf using ghostscript
184 [status, message] = ghostscript(options);
189 % Catch and correct undefined .setopacityalpha errors (issue #285)
190 % (see explanation inside print2eps.m)
191 if ~isempty(regexpi(message,'undefined in .setopacityalpha
'))
192 % First try with -dNOSAFER and -dALLOWPSTRANSPARENCY (thanks @linasstonys)
193 new_options = [options ' -dNOSAFER -dALLOWPSTRANSPARENCY
'];
194 [status, message] = ghostscript(new_options);
195 if ~status % hurray! (no error)
197 elseif isempty(regexpi(message,'undefined in .setopacityalpha
')) % still some other error
198 options = new_options;
199 else % we still get a .setopacityalpha error
200 % Remove the transparency and retry
201 fstrm = read_write_entire_textfile(source);
202 fstrm = regexprep(fstrm, '0?\.\d+ .setopacityalpha \w+\n
', '');
203 read_write_entire_textfile(source, fstrm);
204 [status, message] = ghostscript(options);
205 if ~status % hurray! (no error)
206 % Alert the user that transparency is not supported
207 warning('export_fig:GS:quality
','Export_fig Face/Edge alpha transparancy is ignored - not supported by your Ghostscript
version')
213 % Retry without the -sFONTPATH= option (this might solve some GS
214 % /findfont errors according to James Rankin, FEX Comment 23/01/15)
215 orig_options = options;
217 options = regexprep(options, ' -sFONTPATH=[^ ]+
',' ');
218 [status, message] = ghostscript(options);
219 if ~status % hurray! (no error)
220 warning('export_fig:GS:fontpath
','Export_fig font option is ignored - not supported by your Ghostscript
version')
225 % Retry with updated or no quality options (may solve problems with GS 9.51+, issue #285)
226 if ~isempty(qualityOptions)
227 % First try replacing .setpdfwrite as suggested in ghostscript error (issue #285)
228 options = strrep(orig_options, '.setpdfwrite
', '3000000 setvmthreshold
');
229 if ~ghostscript(options) % hurray! (no error)
230 % No warning: there's no known drawback when
this works so no need to inform the user
231 %warning(
'export_fig:GS:setpdfwrite',
'Successfully worked around deprecated .setpdfwrite')
234 % Well, we tried. Fall back to no quality options.
235 options = strrep(orig_options, qualityOptions, '');
237 warning('export_fig:GS:quality','Export_fig quality option ignored - not supported by your Ghostscript
version')
240 % Hmm, perhaps the problem is just with the downsampleOptions?
241 options = strrep(orig_options, downsampleOptions, '');
243 warning('export_fig:GS:downsample','Export_fig quality option ignored - not supported by your Ghostscript
version')
246 % Nope, last attempt: remove both downsampleOptions & qualityOptions
247 options = strrep(orig_options, qualityOptions, '');
248 options = strrep(options, downsampleOptions, '');
250 if ~status % hurray! (no error)
251 warning('export_fig:GS:quality2','Export_fig quality option ignored - not supported by your Ghostscript
version')
254 else % no quality options, the problem lies elsewhere...
255 % Hmm, perhaps the problem is just with the downsampleOptions?
256 options = strrep(orig_options, downsampleOptions, '');
258 warning('export_fig:GS:downsample','Export_fig quality option ignored - not supported by your Ghostscript
version')
262 % Any other ideas, anyone?
266 error(['Unable to generate pdf. Ensure that the destination folder (' fileparts(dest) ') is writable.']);
267 elseif ~isempty(strfind(message,'/typecheck in /findfont')) %
#ok<STREMP>
268 % Suggest a workaround
for issue #41 (missing font path)
269 font_name = strtrim(regexprep(message,
'.*Operand stack:\s*(.*)\s*Execution.*',
'$1'));
270 fprintf(2,
'Ghostscript error: could not find the following font(s): %s\n', font_name);
271 %fpath = fileparts(mfilename(
'fullpath'));
272 %gs_fonts_file = fullfile(fpath,
'.ignore',
'gs_font_path.txt');
273 [unused, gs_fonts_file] =
user_string(
'gs_font_path'); %#ok<ASGLU>
274 fprintf(2,
' try to add the font''s folder to your %s file\n\n', gs_fonts_file);
275 error(
'export_fig error');
277 gs_options = strtrim(gs_options);
278 fprintf(2,
'\nGhostscript error: ');
279 msg = regexprep(message,
'^Error: /([^\n]+).*',
'$1');
280 if ~isempty(msg) && ~strcmp(msg,message)
283 fprintf(2,
'\n * perhaps %s is open by another application\n', dest);
284 try gs_version = str2num(evalc(
'ghostscript(''--version'');'));
catch, gs_version =
''; end %#ok<ST2NM>
285 if ~isempty(gs_version), gs_version = [
' ' num2str(gs_version)]; end
286 if ~isempty(gs_options)
287 fprintf(2,
' * or maybe your Ghostscript version%s does not accept the extra "%s" option(s) that you requested\n', gs_version, gs_options);
289 fprintf(2,
' * or maybe you have another gs executable in your system''s path\n\n');
290 fprintf(2,
'Ghostscript path: %s\n',
user_string(
'ghostscript'));
291 fprintf(2,
'Ghostscript options: %s\n\n', orig_options);
297% Function to
return (and create, where necessary) the font path
304 % Start with the default path
305 fp = getenv('GS_FONTPATH');
306 % Add on the typical directories for a given OS
311 fp = [fp getenv('WINDIR') filesep 'Fonts'];
316 fp = [fp '/usr/share/fonts:/usr/local/share/fonts:/usr/share/fonts/X11:/usr/local/share/fonts/X11:/usr/share/fonts/truetype:/usr/local/share/fonts/truetype'];
function version(in silent)
Return a scalar MATLAB string containing the latest available ParaMonte MATLAB version newer than the...
function eps2pdf(in source, in dest, in crop, in append, in gray, in quality, in gs_options)
function ghostscript(in cmd)
function info()
Return a MATLAB string containing the current system information.
function release(in type)
Return a scalar MATLAB string containing the MATLAB release version, year, or season as requested.
function user_string(in string_name, in string)
function which(in vendor)
Return the a MATLAB string containing the path to the first mpiexec executable binary found in system...