forked from farrajota/caltech-extract-data-toolbox
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpdollar_savefig.m
291 lines (269 loc) · 13.1 KB
/
pdollar_savefig.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
function savefig(fname, varargin)
% Usage: savefig(filename, fighdl, options)
%
% Saves a pdf, eps, png, jpeg, and/or tiff of the contents of the fighandle's (or current) figure.
% It saves an eps of the figure and the uses Ghostscript to convert to the other formats.
% The result is a cropped, clean picture. There are options for using rgb or cmyk colours,
% or grayscale. You can also choose the resolution.
%
% The advantage of savefig is that there is very little empty space around the figure in the
% resulting files, you can export to more than one format at once, and Ghostscript generates
% trouble-free files.
%
% If you find any errors, please let me know! (peder at axensten dot se)
%
% filename: File name without suffix.
%
% fighdl: (default: gcf) Integer handle to figure.
%
% options: (default: '-r300', '-lossless', '-rgb') You can define your own
% defaults in a global variable savefig_defaults, if you want to, i.e.
% savefig_defaults= {'-r200','-gray'};.
% 'eps': Output in Encapsulated Post Script (no preview yet).
% 'pdf': Output in (Adobe) Portable Document Format.
% 'png': Output in Portable Network Graphics.
% 'jpeg': Output in Joint Photographic Experts Group format.
% 'tiff': Output in Tagged Image File Format (no compression: huge files!).
% '-rgb': Output in rgb colours.
% '-cmyk': Output in cmyk colours (not yet 'png' or 'jpeg' -- '-rgb' is used).
% '-gray': Output in grayscale (not yet 'eps' -- '-rgb' is used).
% '-fonts': Include fonts in eps or pdf. Includes only the subset needed.
% '-lossless': Use lossless compression, works on most formats. same as '-c0', below.
% '-c<float>': Set compression for non-indexed bitmaps in PDFs -
% 0: lossless; 0.1: high quality; 0.5: medium; 1: high compression.
% '-r<integer>': Set resolution.
% '-crop': Removes points and line segments outside the viewing area -- permanently.
% Only use this on figures where many points and/or line segments are outside
% the area zoomed in to. This option will result in smaller vector files (has no
% effect on pixel files).
% '-dbg': Displays gs command line(s).
%
% EXAMPLE:
% savefig('nicefig', 'pdf', 'jpeg', '-cmyk', '-c0.1', '-r250');
% Saves the current figure to nicefig.pdf and nicefig.png, both in cmyk and at 250 dpi,
% with high quality lossy compression.
%
% REQUIREMENT: Ghostscript. Version 8.57 works, probably older versions too, but '-dEPSCrop'
% must be supported. I think version 7.32 or newer is ok.
%
% HISTORY:
% Version 1.0, 2006-04-20.
% Version 1.1, 2006-04-27:
% - No 'epstopdf' stuff anymore! Using '-dEPSCrop' option in gs instead!
% Version 1.2, 2006-05-02:
% - Added a '-dbg' option (see options, above).
% - Now looks for a global variable 'savefig_defaults' (see options, above).
% - More detailed Ghostscript options (user will not really notice).
% - Warns when there is no device for a file-type/color-model combination.
% Version 1.3, 2006-06-06:
% - Added a check to see if there actually is a figure handle.
% - Now works in Matlab 6.5.1 (R13SP1) (maybe in 6.5 too).
% - Now compatible with Ghostscript 8.54, released 2006-06-01.
% Version 1.4, 2006-07-20:
% - Added an option '-soft' that enables anti-aliasing on pixel graphics (on by default).
% - Added an option '-hard' that don't do anti-aliasing on pixel graphics.
% Version 1.5, 2006-07-27:
% - Fixed a bug when calling with a figure handle argument.
% Version 1.6, 2006-07-28:
% - Added a crop option, see above.
% Version 1.7, 2007-03-31:
% - Fixed bug: calling print with invalid renderer value '-none'.
% - Removed GhostScript argument '-dUseCIEColor' as it sometimes discoloured things.
% Version 1.8, 2008-01-03:
% - Added MacIntel: 'MACI'.
% - Added 64bit PC (I think, can't test it myself).
% - Added option '-nointerpolate' (use it to prevent blurring of pixelated).
% - Removed '-hard' and '-soft'. Use '-nointerpolate' for '-hard', default for '-soft'.
% - Fixed the gs 8.57 warning on UseCIEColor (it's now set).
% - Added '-gray' for pdf, but gs 8.56 or newer is needed.
% - Added '-gray' and '-cmyk' for eps, but you a fairly recent gs might be needed.
% Version 1.9, 2008-07-27:
% - Added lossless compression, see option '-lossless', above. Works on most formats.
% - Added lossy compression, see options '-c<float>...', above. Works on 'pdf'.
% Thanks to Olly Woodford for idea and implementation!
% - Removed option '-nointerpolate' -- now savefig never interpolates.
% - Fixed a few small bugs and removed some mlint comments.
% Version 2.0, 2008-11-07:
% - Added the possibility to include fonts into eps or pdf.
%
% TO DO: (Need Ghostscript support for these, so don't expect anything soon...)
% - svg output.
% - '-cmyk' for 'jpeg' and 'png'.
% - Preview in 'eps'.
% - Embedded vector fonts, not bitmap, in 'eps'.
%
% Copyright (C) Peder Axensten (peder at axensten dot se), 2006.
% KEYWORDS: eps, pdf, jpg, jpeg, png, tiff, eps2pdf, epstopdf, ghostscript
%
% INSPIRATION: eps2pdf (5782), eps2xxx (6858)
%
% REQUIREMENTS: Works in Matlab 6.5.1 (R13SP1) (maybe in 6.5 too).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
op_dbg= false; % Default value.
% Compression
compr= [' -dUseFlateCompression=true -dLZWEncodePages=true -dCompatibilityLevel=1.6' ...
' -dAutoFilterColorImages=false -dAutoFilterGrayImages=false ' ...
' -dColorImageFilter=%s -dGrayImageFilter=%s']; % Compression.
lossless= sprintf (compr, '/FlateEncode', '/FlateEncode');
lossy= sprintf (compr, '/DCTEncode', '/DCTEncode' );
lossy= [lossy ' -c ".setpdfwrite << /ColorImageDict << /QFactor %g ' ...
'/Blend 1 /HSample [%s] /VSample [%s] >> >> setdistillerparams"'];
% Create gs command.
cmdEnd= ' -sDEVICE=%s -sOutputFile="%s"'; % Essential.
epsCmd= '';
epsCmd= [epsCmd ' -dSubsetFonts=true -dNOPLATFONTS']; % Future support?
epsCmd= [epsCmd ' -dUseCIEColor=true -dColorConversionStrategy=/UseDeviceIndependentColor'];
epsCmd= [epsCmd ' -dProcessColorModel=/%s']; % Color conversion.
pdfCmd= [epsCmd ' -dAntiAliasColorImages=false' cmdEnd];
epsCmd= [epsCmd cmdEnd];
% Get file name.
if((nargin < 1) || isempty(fname) || ~ischar(fname)) % Check file name.
error('No file name specified.');
end
[pathstr, namestr] = fileparts(fname);
if(isempty(pathstr)), fname= fullfile(cd, namestr); end
% Get handle.
fighdl= get(0, 'CurrentFigure'); % See gcf. % Get figure handle.
if((nargin >= 2) && (numel(varargin{1}) == 1) && isnumeric(varargin{1}))
fighdl= varargin{1};
varargin= {varargin{2:end}};
end
if(isempty(fighdl)), error('There is no figure to save!?'); end
set(fighdl, 'Units', 'centimeters') % Set paper stuff.
sz= get(fighdl, 'Position');
sz(1:2)= 0;
set(fighdl, 'PaperUnits', 'centimeters', 'PaperSize', sz(3:4), 'PaperPosition', sz);
% Set up the various devices.
% Those commented out are not yet supported by gs (nor by savefig).
% pdf-cmyk works due to the Matlab '-cmyk' export being carried over from eps to pdf.
device.eps.rgb= sprintf(epsCmd, 'DeviceRGB', 'epswrite', [fname '.eps']);
device.jpeg.rgb= sprintf(cmdEnd, 'jpeg', [fname '.jpeg']);
% device.jpeg.cmyk= sprintf(cmdEnd, 'jpegcmyk', [fname '.jpeg']);
device.jpeg.gray= sprintf(cmdEnd, 'jpeggray', [fname '.jpeg']);
device.pdf.rgb= sprintf(pdfCmd, 'DeviceRGB', 'pdfwrite', [fname '.pdf']);
device.pdf.cmyk= sprintf(pdfCmd, 'DeviceCMYK', 'pdfwrite', [fname '.pdf']);
device.pdf.gray= sprintf(pdfCmd, 'DeviceGray', 'pdfwrite', [fname '.pdf']);
device.png.rgb= sprintf(cmdEnd, 'png16m', [fname '.png']);
% device.png.cmyk= sprintf(cmdEnd, 'png???', [fname '.png']);
device.png.gray= sprintf(cmdEnd, 'pnggray', [fname '.png']);
device.tiff.rgb= sprintf(cmdEnd, 'tiff24nc', [fname '.tiff']);
device.tiff.cmyk= sprintf(cmdEnd, 'tiff32nc', [fname '.tiff']);
device.tiff.gray= sprintf(cmdEnd, 'tiffgray', [fname '.tiff']);
% Get options.
global savefig_defaults; % Add global defaults.
if( iscellstr(savefig_defaults)), varargin= {savefig_defaults{:}, varargin{:}};
elseif(ischar(savefig_defaults)), varargin= {savefig_defaults, varargin{:}};
end
varargin= {'-r300', '-lossless', '-rgb', varargin{:}}; % Add defaults.
res= '';
types= {};
fonts= 'false';
crop= false;
for n= 1:length(varargin) % Read options.
if(ischar(varargin{n}))
switch(lower(varargin{n}))
case {'eps','jpeg','pdf','png','tiff'}, types{end+1}= lower(varargin{n});
case '-rgb', color= 'rgb'; deps= {'-depsc2'};
case '-cmyk', color= 'cmyk'; deps= {'-depsc2', '-cmyk'};
case '-gray', color= 'gray'; deps= {'-deps2'};
case '-fonts', fonts= 'true';
case '-lossless', comp= 0;
case '-crop', crop= true;
case '-dbg', op_dbg= true;
otherwise
if(regexp(varargin{n}, '^\-r[0-9]+$')), res= varargin{n};
elseif(regexp(varargin{n}, '^\-c[0-9.]+$')), comp= str2double(varargin{n}(3:end));
else warning('pax:savefig:inputError', 'Unknown option in argument: ''%s''.', varargin{n});
end
end
else
warning('pax:savefig:inputError', 'Wrong type of argument: ''%s''.', class(varargin{n}));
end
end
types= unique(types);
if(isempty(types)), error('No output format given.'); end
if (comp == 0) % Lossless compression
gsCompr= lossless;
elseif (comp <= 0.1) % High quality lossy
gsCompr= sprintf(lossy, comp, '1 1 1 1', '1 1 1 1');
else % Normal lossy
gsCompr= sprintf(lossy, comp, '2 1 1 2', '2 1 1 2');
end
% Generate the gs command.
switch(computer) % Get gs command.
case {'MAC','MACI'}, gs= '/usr/local/bin/gs';
case {'PCWIN'}, gs= 'gswin32c.exe';
case {'PCWIN64'}, gs= 'gswin64c.exe';
otherwise, gs= 'gs';
end
gs= [gs ' -q -dNOPAUSE -dBATCH -dEPSCrop']; % Essential.
gs= [gs ' -dPDFSETTINGS=/prepress -dEmbedAllFonts=' fonts]; % Must be first?
gs= [gs ' -dUseFlateCompression=true']; % Useful stuff.
gs= [gs ' -dAutoRotatePages=/None']; % Probably good.
gs= [gs ' -dHaveTrueTypes']; % Probably good.
gs= [gs ' ' res]; % Add resolution to cmd.
if(crop && ismember(types, {'eps', 'pdf'})) % Crop the figure.
fighdl= do_crop(fighdl);
end
% Output eps from Matlab.
renderer= ['-' lower(get(fighdl, 'Renderer'))]; % Use same as in figure.
if(strcmpi(renderer, '-none')), renderer= '-painters'; end % We need a valid renderer.
deps = [deps '-loose']; % added by PPD seems to help w cropping in matlab 2014b :(
print(fighdl, deps{:}, '-noui', renderer, res, [fname '-temp']); % Output the eps.
% Convert to other formats.
for n= 1:length(types) % Output them.
if(isfield(device.(types{n}), color))
cmd= device.(types{n}).(color); % Colour model exists.
else
cmd= device.(types{n}).rgb; % Use alternative.
if(~strcmp(types{n}, 'eps')) % It works anyways for eps (VERY SHAKY!).
warning('pax:savefig:deviceError', ...
'No device for %s using %s. Using rgb instead.', types{n}, color);
end
end
cmp= lossless;
if (strcmp(types{n}, 'pdf')), cmp= gsCompr; end % Lossy compr only for pdf.
if (strcmp(types{n}, 'eps')), cmp= ''; end % eps can't use lossless.
cmd= sprintf('%s %s %s -f "%s-temp.eps"', gs, cmd, cmp, fname);% Add up.
status= system(cmd); % Run Ghostscript.
if (op_dbg || status), display (cmd), end
end
delete([fname '-temp.eps']); % Clean up.
end
function fig= do_crop(fig)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Remove line segments that are outside the view.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
haxes= findobj(fig, 'Type', 'axes', '-and', 'Tag', '');
for n=1:length(haxes)
xl= get(haxes(n), 'XLim');
yl= get(haxes(n), 'YLim');
lines= findobj(haxes(n), 'Type', 'line');
for m=1:length(lines)
x= get(lines(m), 'XData');
y= get(lines(m), 'YData');
inx= (xl(1) <= x) & (x <= xl(2)); % Within the x borders.
iny= (yl(1) <= y) & (y <= yl(2)); % Within the y borders.
keep= inx & iny; % Within the box.
if(~strcmp(get(lines(m), 'LineStyle'), 'none'))
crossx= ((x(1:end-1) < xl(1)) & (xl(1) < x(2:end))) ... % Crossing border x1.
| ((x(1:end-1) < xl(2)) & (xl(2) < x(2:end))) ... % Crossing border x2.
| ((x(1:end-1) > xl(1)) & (xl(1) > x(2:end))) ... % Crossing border x1.
| ((x(1:end-1) > xl(2)) & (xl(2) > x(2:end))); % Crossing border x2.
crossy= ((y(1:end-1) < yl(1)) & (yl(1) < y(2:end))) ... % Crossing border y1.
| ((y(1:end-1) < yl(2)) & (yl(2) < y(2:end))) ... % Crossing border y2.
| ((y(1:end-1) > yl(1)) & (yl(1) > y(2:end))) ... % Crossing border y1.
| ((y(1:end-1) > yl(2)) & (yl(2) > y(2:end))); % Crossing border y2.
crossp= [( (crossx & iny(1:end-1) & iny(2:end)) ... % Crossing a x border within y limits.
| (crossy & inx(1:end-1) & inx(2:end)) ... % Crossing a y border within x limits.
| crossx & crossy ... % Crossing a x and a y border (corner).
), false ...
];
crossp(2:end)= crossp(2:end) | crossp(1:end-1); % Add line segment's secont end point.
keep= keep | crossp;
end
set(lines(m), 'XData', x(keep))
set(lines(m), 'YData', y(keep))
end
end
end