forked from altmany/export_fig
-
Notifications
You must be signed in to change notification settings - Fork 0
/
export_fig.m
3111 lines (2981 loc) · 161 KB
/
export_fig.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
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
function [imageData, alpha] = export_fig(varargin) %#ok<*STRCL1,*DATST,*TNOW1>
%EXPORT_FIG Exports figures in a publication-quality format
%
% Examples:
% imageData = export_fig
% [imageData, alpha] = export_fig
% export_fig filename
% export_fig ... -<format>
% export_fig ... -nocrop
% export_fig ... -c[<val>,<val>,<val>,<val>]
% export_fig ... -transparent
% export_fig ... -native
% export_fig ... -m<val>
% export_fig ... -r<val>
% export_fig ... -a<val>
% export_fig ... -q<val>
% export_fig ... -p<val>
% export_fig ... -n<val> or: -n<val>,<val>
% export_fig ... -x<val> or: -x<val>,<val>
% export_fig ... -s<val> or: -s<val>,<val>
% export_fig ... -d<gs_option>
% export_fig ... -depsc
% export_fig ... -metadata <metaDataInfo>
% export_fig ... -<renderer>
% export_fig ... -<colorspace>
% export_fig ... -append
% export_fig ... -bookmark
% export_fig ... -clipboard<:format>
% export_fig ... -update
% export_fig ... -version
% export_fig ... -nofontswap
% export_fig ... -font_space <char>
% export_fig ... -linecaps
% export_fig ... -noinvert
% export_fig ... -preserve_size
% export_fig ... -options <optionsStruct>
% export_fig ... -silent
% export_fig ... -notify
% export_fig ... -regexprep <pattern> <replace>
% export_fig ... -toolbar
% export_fig ... -menubar
% export_fig ... -contextmenu
% export_fig(..., handle)
% export_fig(..., figName)
%
% This function saves a figure or single axes to one or more vector and/or
% bitmap file formats, and/or outputs a rasterized version to the workspace,
% with the following properties:
% - Figure/axes reproduced as it appears on screen
% - Cropped/padded borders (optional)
% - Embedded fonts (vector formats)
% - Improved line and grid line styles
% - Anti-aliased graphics (bitmap formats)
% - Render images at native resolution (optional for bitmap formats)
% - Transparent background supported (pdf, eps, png, tif, gif)
% - Semi-transparent patch objects supported (png, tif)
% - RGB, CMYK or grayscale output (CMYK only with pdf, eps, tif)
% - Variable image compression, including lossless (pdf, eps, jpg)
% - Optional rounded line-caps (pdf, eps)
% - Optionally append to file (pdf, tif, gif)
% - Vector formats: pdf, eps, emf, svg
% - Bitmap formats: png, tif, jpg, bmp, gif, clipboard, export to workspace
%
% This function is especially suited to exporting figures for use in
% publications and presentations, because of the high quality and
% portability of media produced.
%
% Note that the background color and figure dimensions are reproduced
% (the latter approximately, and ignoring cropping & magnification) in the
% output file. For transparent background (and semi-transparent patch
% objects), use the -transparent option or set the figure 'Color' property
% to 'none'. To make axes transparent set the axes 'Color' property to
% 'none'. PDF, EPS, TIF & PNG are the only formats that support a transparent
% background; only TIF & PNG formats support transparency of patch objects.
%
% The choice of renderer (opengl/zbuffer/painters) has a large impact on the
% output quality. The default value (opengl for bitmaps, painters for vector
% formats) generally gives good results, but if you aren't satisfied
% then try another renderer. Notes:
% 1) For vector formats (EPS,PDF), only painters generates vector graphics
% 2) For bitmap formats, only opengl correctly renders transparent patches
% 3) For bitmap formats, only painters correctly scales line dash and dot
% lengths when magnifying or anti-aliasing
% 4) Fonts may be substitued with Courier when using painters
%
% When exporting to vector format (PDF & EPS) and bitmap format using the
% painters renderer, this function requires that ghostscript is installed
% on your system. You can download this from: http://www.ghostscript.com
% When exporting to EPS it additionally requires pdftops, from the Xpdf
% suite of functions. You can download this from: http://xpdfreader.com
%
% SVG output uses Matlab's built-in SVG export if available, or otherwise the
% fig2svg (https://github.com/kupiqu/fig2svg) or plot2svg
% (https://github.com/jschwizer99/plot2svg) utilities, if available.
% Note: cropping/padding are not supported in export_fig's SVG and EMF output.
%
% Inputs:
% filename - string containing the name (optionally including full or
% relative path) of the file the figure is to be saved as. If
% no path is specified, the figure is saved in the current folder.
% If no name and no output arguments are specified, the figure's
% FileName property is used. If this property is empty, then the
% default name 'export_fig_out' is used. If neither file extension
% nor a format parameter are specified, a ".png" is added to the
% filename and the figure saved in PNG format.
% -<format> - string(s) containing the output file extension(s). Options:
% '-pdf','-eps','emf','-svg','-png','-tif','-jpg','-gif' and '-bmp'.
% Multiple formats can be specified, without restriction.
% For example: export_fig('-jpg', '-pdf', '-png', ...)
% Note: '-tif','-tiff' are equivalent, and so are '-jpg','-jpeg'.
% -transparent - option indicating that the figure background is to be made
% transparent (PNG,PDF,TIF,EPS,EMF formats only). Implies -noinvert.
% -nocrop - option indicating that empty margins should not be cropped.
% -c[<val>,<val>,<val>,<val>] - option indicating crop amounts. Must be
% a 4-element vector of numeric values: [top,right,bottom,left]
% where NaN/Inf indicates auto-cropping, 0 means no cropping, any
% other value means cropping in pixel amounts. e.g. '-c7,15,0,NaN'
% Note: this option is not supported by SVG and EMF formats.
% -p<val> - option to pad a border of width val to exported files, where
% val is either a relative size with respect to cropped image
% size (i.e. p=0.01 adds a 1% border). For EPS & PDF formats,
% val can also be integer in units of 1/72" points (abs(val)>1).
% val can be positive (padding) or negative (extra cropping).
% If used, the -nocrop flag will be ignored, i.e. the image will
% always be cropped and then padded. Default: 0 (i.e. no padding).
% Note: this option is not supported by SVG and EMF formats.
% -m<val> - option val indicates the factor to magnify the figure dimensions
% when generating bitmap outputs (does not affect vector formats).
% Default: '-m1' (i.e. val=1). Note: val~=1 slows down export_fig.
% -r<val> - option val indicates the resolution (in pixels per inch) to
% export bitmap and vector outputs, without changing dimensions of
% the on-screen figure. Default: '-r864' (for vector output only).
% Note: -m option overides -r option for bitmap exports only.
% -native - option indicating that the output resolution (when outputting
% a bitmap format) should be such that the vertical resolution
% of the first suitable image found in the figure is at the
% native resolution of that image. To specify a particular
% image to use, give it the tag 'export_fig_native'.
% Notes: This overrides any value set with the -m and -r options.
% It also assumes that the image is displayed front-to-parallel
% with the screen. The output resolution is approximate and
% should not be relied upon. Anti-aliasing can have adverse
% effects on image quality (disable with the -a1 option).
% -a1, -a2, -a3, -a4 - option indicating the amount of anti-aliasing (AA) to
% use for bitmap outputs, when GraphicsSmoothing is not available.
% '-a1'=no AA; '-a4'=max. Default: 3 for HG1, 1 for HG2.
% -<renderer> - option to force a particular renderer (painters, opengl or
% [in R2014a or older] zbuffer). Default value: opengl for bitmap
% formats or figures with patches and/or transparent annotations;
% painters for vector formats without patches/transparencies.
% -<colorspace> - option indicating which colorspace color figures should
% be saved in: RGB (default), CMYK or gray. Usage example: '-gray'.
% Note: CMYK is only supported in PDF, EPS and TIF formats.
% -q<val> - option to vary bitmap image quality (PDF, EPS, JPG formats only).
% A larger val, in the range 0-100, produces higher quality and
% lower compression. val > 100 results in lossless compression.
% Default: '-q95' for JPG, ghostscript prepress default for PDF,EPS.
% Note: lossless compression can sometimes give a smaller file size
% than the default lossy compression, depending on the image type.
% -n<val> - option to set minimum output image size (bitmap formats only).
% The output size can be specified as a single value (for both rows
% & cols, e.g. -n200) or comma-separated values (e.g. -n300,400).
% Use an Inf value to keep a dimension unchanged (e.g. -n50,inf).
% Use a NaN value to keep aspect ratio unchanged (e.g. -n50,nan).
% -x<val> - option to set maximum output image size (bitmap formats only).
% The output size can be specified as a single value (for both rows
% & cols, e.g. -x200) or comma-separated values (e.g. -x300,400).
% Use an Inf value to keep a dimension unchanged (e.g. -x50,inf).
% Use a NaN value to keep aspect ratio unchanged (e.g. -x50,nan).
% -s<val> - option to scale output image to specific size (bitmap formats only).
% The fixed size can be specified as a single value (for rows=cols) or
% comma-separated values (e.g. -s300,400). Each value can be a scalar
% integer (signifying pixels) or percentage (e.g. -s125%). The scaling
% is done last, after any other cropping/rescaling due to other params.
% -append - option indicating that if the file already exists the figure is to
% be appended as a new page, instead of being overwritten (default).
% PDF, TIF & GIF output formats only (multi-image GIF = animated).
% -bookmark - option to indicate that a bookmark with the name of the
% figure is to be created in the output file (PDF format only).
% -clipboard - option to save output as an image on the system clipboard.
% -clipboard<:format> - copies to clipboard in the specified format:
% image (default), bitmap, emf, or pdf.
% Notes: Only -clipboard (or -clipboard:image, which is the same)
% applies export_fig parameters such as cropping, padding etc.
% -clipboard:image create a bitmap image using export_fig processing
% -clipboard:bitmap create a bitmap image as-is (no auto-cropping etc.)
% -clipboard:emf is vector format without auto-cropping; Windows-only
% -clipboard:pdf is vector format without cropping; not universally supported
% -d<gs_option> - option to indicate a ghostscript setting. For example,
% -dMaxBitmap=0 or -dNoOutputFonts (Ghostscript 9.15+).
% -depsc - option to use EPS level-3 rather than the default level-2 print
% device. This solves some bugs with Matlab's default -depsc2 device
% such as discolored subplot lines on images (vector formats only).
% -metadata <metaDataInfo> - adds the specified meta-data information to the
% exported file (PDF format only). metaDataInfo must be either a struct
% or a cell array with pairs of values: {'fieldName',fieldValue, ...}.
% Common metadata fields: Title,Author,Creator,Producer,Subject,Keywords
% -update - option to download and install the latest version of export_fig
% -version - return the current export_fig version, without any figure export
% -nofontswap - option to avoid font swapping. Font swapping is automatically
% done in vector formats (only): 11 standard Matlab fonts are
% replaced by the original figure fonts. This option prevents this.
% -font_space <char> - option to set a spacer character for font-names that
% contain spaces, used by EPS/PDF. Default: ''
% -linecaps - option to create rounded line-caps (vector formats only).
% -noinvert - option to avoid setting figure's InvertHardcopy property to
% 'off' during output (this solves some problems of empty outputs).
% -preserve_size - option to preserve the figure's PaperSize property in output
% file (PDF/EPS formats only; default is to not preserve it).
% -options <optionsStruct> - format-specific parameters as defined in Matlab's
% documentation of the imwrite function, contained in a struct under
% the format name. For example to specify the JPG Comment parameter,
% pass a struct such as this: options.JPG.Comment='abc'. Similarly,
% options.PNG.BitDepth=4. Only used by PNG,TIF,JPG,GIF output formats.
% Options can also be specified as a cell array of name-value pairs,
% e.g. {'BitDepth',4, 'Author','Yair'} - these options will be used
% by all supported output formats of the export_fig command.
% -silent - option to avoid various warning and informational messages, such
% as version update checks, transparency or renderer issues, etc.
% -notify - option to notify the user when export is done, in both a console
% message and a popup dialog (allow opening the exported file/folder).
% -regexprep <old> <new> - replaces all occurances of <old> (a regular expression
% string or array of strings; case-sensitive), with the corresponding
% <new> string(s), in EPS/PDF files (only). See regexp function's doc.
% Warning: invalid replacement can make your EPS/PDF file unreadable!
% -toolbar - adds an interactive export button to the figure's toolbar
% -menubar - adds an interactive export menu to the figure's menubar
% -contextmenu - adds interactive export menu to figure context-menu (right-click)
% handle - handle of the figure, axes or uipanels (can be an array of handles
% but all the objects must be in the same figure) to be exported.
% Default: gcf (handle of current figure).
% figName - name (title) of the figure to export (e.g. 'Figure 1' or 'My fig').
% Overriden by handle (if specified); Default: current figure
%
% Outputs:
% imageData - MxNxC uint8 image array of the exported image.
% alpha - MxN single array of alphamatte values in the range [0,1],
% for the case when the background is transparent.
%
% Some helpful examples and tips can be found at:
% https://github.com/altmany/export_fig
%
% See also PRINT, SAVEAS, ScreenCapture (on the Matlab File Exchange)
%{
% Copyright (C) Oliver Woodford 2008-2014, Yair Altman 2015-
% The idea of using ghostscript is inspired by Peder Axensten's SAVEFIG
% (fex id: 10889) which is itself inspired by EPS2PDF (fex id: 5782).
% The idea for using pdftops came from the MATLAB newsgroup (id: 168171).
% The idea of editing the EPS file to change line styles comes from Jiro
% Doke's FIXPSLINESTYLE (fex id: 17928).
% The idea of changing dash length with line width came from comments on
% fex id: 5743, but the implementation is mine :)
% The idea of anti-aliasing bitmaps came from Anders Brun's MYAA (fex id:
% 20979).
% The idea of appending figures in pdfs came from Matt C in comments on the
% FEX (id: 23629)
% Thanks to Roland Martin for pointing out the colour MATLAB
% bug/feature with colorbar axes and transparent backgrounds.
% Thanks also to Andrew Matthews for describing a bug to do with the figure
% size changing in -nodisplay mode. I couldn't reproduce it, but included a
% fix anyway.
% Thanks to Tammy Threadgill for reporting a bug where an axes is not
% isolated from gui objects.
%}
%{
% 23/02/12: Ensure that axes limits don't change during printing
% 14/03/12: Fix bug in fixing the axes limits (thanks to Tobias Lamour for reporting it).
% 02/05/12: Incorporate patch of Petr Nechaev (many thanks), enabling bookmarking of figures in pdf files.
% 09/05/12: Incorporate patch of Arcelia Arrieta (many thanks), to keep tick marks fixed.
% 12/12/12: Add support for isolating uipanels. Thanks to michael for suggesting it.
% 25/09/13: Add support for changing resolution in vector formats. Thanks to Jan Jaap Meijer for suggesting it.
% 07/05/14: Add support for '~' at start of path. Thanks to Sally Warner for suggesting it.
% 24/02/15: Fix Matlab R2014b bug (issue #34): plot markers are not displayed when ZLimMode='manual'
% 25/02/15: Fix issue #4 (using HG2 on R2014a and earlier)
% 25/02/15: Fix issue #21 (bold TeX axes labels/titles in R2014b)
% 26/02/15: If temp dir is not writable, use the user-specified folder for temporary EPS/PDF files (Javier Paredes)
% 27/02/15: Modified repository URL from github.com/ojwoodford to /altmany; Indented main function; Added top-level try-catch block to display useful workarounds
% 28/02/15: Enable users to specify optional ghostscript options (issue #36)
% 06/03/15: Improved image padding & cropping thanks to Oscar Hartogensis
% 26/03/15: Fixed issue #49 (bug with transparent grayscale images); fixed out-of-memory issue
% 26/03/15: Fixed issue #42: non-normalized annotations on HG1
% 26/03/15: Fixed issue #46: Ghostscript crash if figure units <> pixels
% 27/03/15: Fixed issue #39: bad export of transparent annotations/patches
% 28/03/15: Fixed issue #50: error on some Matlab versions with the fix for issue #42
% 29/03/15: Fixed issue #33: bugs in Matlab's print() function with -cmyk
% 29/03/15: Improved processing of input args (accept space between param name & value, related to issue #51)
% 30/03/15: When exporting *.fig files, then saveas *.fig if figure is open, otherwise export the specified fig file
% 30/03/15: Fixed edge case bug introduced yesterday (commit #ae1755bd2e11dc4e99b95a7681f6e211b3fa9358)
% 09/04/15: Consolidated header comment sections; initialize output vars only if requested (nargout>0)
% 14/04/15: Workaround for issue #45: lines in image subplots are exported in invalid color
% 15/04/15: Fixed edge-case in parsing input parameters; fixed help section to show the -depsc option (issue #45)
% 21/04/15: Bug fix: Ghostscript croaks on % chars in output PDF file (reported by Sven on FEX page, 15-Jul-2014)
% 22/04/15: Bug fix: Pdftops croaks on relative paths (reported by Tintin Milou on FEX page, 19-Jan-2015)
% 04/05/15: Merged fix #63 (Kevin Mattheus Moerman): prevent tick-label changes during export
% 07/05/15: Partial fix for issue #65: PDF export used painters rather than opengl renderer (thanks Nguyenr)
% 08/05/15: Fixed issue #65: bad PDF append since commit #e9f3cdf 21/04/15 (thanks Robert Nguyen)
% 12/05/15: Fixed issue #67: exponent labels cropped in export, since fix #63 (04/05/15)
% 28/05/15: Fixed issue #69: set non-bold label font only if the string contains symbols (\beta etc.), followup to issue #21
% 29/05/15: Added informative error message in case user requested SVG output (issue #72)
% 09/06/15: Fixed issue #58: -transparent removed anti-aliasing when exporting to PNG
% 19/06/15: Added -update option to download and install the latest version of export_fig
% 07/07/15: Added -nofontswap option to avoid font-swapping in EPS/PDF
% 16/07/15: Fixed problem with anti-aliasing on old Matlab releases
% 11/09/15: Fixed issue #103: magnification must never become negative; also fixed reported error msg in parsing input params
% 26/09/15: Alert if trying to export transparent patches/areas to non-PNG outputs (issue #108)
% 04/10/15: Do not suggest workarounds for certain errors that have already been handled previously
% 01/11/15: Fixed issue #112: use same renderer in print2eps as export_fig (thanks to Jesús Pestana Puerta)
% 10/11/15: Custom GS installation webpage for MacOS. Thanks to Andy Hueni via FEX
% 19/11/15: Fixed clipboard export in R2015b (thanks to Dan K via FEX)
% 21/02/16: Added -c option for indicating specific crop amounts (idea by Cedric Noordam on FEX)
% 08/05/16: Added message about possible error reason when groot.Units~=pixels (issue #149)
% 17/05/16: Fixed case of image YData containing more than 2 elements (issue #151)
% 08/08/16: Enabled exporting transparency to TIF, in addition to PNG/PDF (issue #168)
% 11/12/16: Added alert in case of error creating output PDF/EPS file (issue #179)
% 13/12/16: Minor fix to the commit for issue #179 from 2 days ago
% 22/03/17: Fixed issue #187: only set manual ticks when no exponent is present
% 09/04/17: Added -linecaps option (idea by Baron Finer, issue #192)
% 15/09/17: Fixed issue #205: incorrect tick-labels when Ticks number don't match the TickLabels number
% 15/09/17: Fixed issue #210: initialize alpha map to ones instead of zeros when -transparent is not used
% 18/09/17: Added -font_space option to replace font-name spaces in EPS/PDF (workaround for issue #194)
% 18/09/17: Added -noinvert option to solve some export problems with some graphic cards (workaround for issue #197)
% 08/11/17: Fixed issue #220: axes exponent is removed in HG1 when TickMode is 'manual' (internal Matlab bug)
% 08/11/17: Fixed issue #221: alert if the requested folder does not exist
% 19/11/17: Workaround for issue #207: alert when trying to use transparent bgcolor with -opengl
% 29/11/17: Workaround for issue #206: warn if exporting PDF/EPS for a figure that contains an image
% 11/12/17: Fixed issue #230: use OpenGL renderer when exported image contains transparency (also see issue #206)
% 30/01/18: Updated SVG message to point to https://github.com/kupiqu/plot2svg and display user-selected filename if available
% 27/02/18: Fixed issue #236: axes exponent cropped from output if on right-hand axes
% 29/05/18: Fixed issue #245: process "string" inputs just like 'char' inputs
% 13/08/18: Fixed issue #249: correct black axes color to off-black to avoid extra cropping with -transparent
% 27/08/18: Added a possible file-open reason in EPS/PDF write-error message (suggested by "craq" on FEX page)
% 22/09/18: Xpdf website changed to xpdfreader.com
% 23/09/18: Fixed issue #243: only set non-bold font (workaround for issue #69) in R2015b or earlier; warn if changing font
% 23/09/18: Workaround for issue #241: don't use -r864 in EPS/PDF outputs when -native is requested (solves black lines problem)
% 18/11/18: Issue #261: Added informative alert when trying to export a uifigure (which is not currently supported)
% 13/12/18: Issue #261: Fixed last commit for cases of specifying axes/panel handle as input, rather than a figure handle
% 13/01/19: Issue #72: Added basic SVG output support
% 04/02/19: Workaround for issues #207 and #267: -transparent implies -noinvert
% 08/03/19: Issue #269: Added ability to specify format-specific options for PNG,TIF,JPG outputs; fixed help section
% 21/03/19: Fixed the workaround for issues #207 and #267 from 4/2/19 (-transparent now does *NOT* imply -noinvert; -transparent output should now be ok in all formats)
% 12/06/19: Issue #277: Enabled preservation of figure's PaperSize in output PDF/EPS file
% 06/08/19: Remove warning message about obsolete JavaFrame in R2019b
% 30/10/19: Fixed issue #261: added support for exporting uifigures and uiaxes (thanks to idea by @MarvinILA)
% 12/12/19: Added warning in case user requested anti-aliased output on an aliased HG2 figure (issue #292)
% 15/12/19: Added promo message
% 08/01/20: (3.00) Added check for newer version online (initialized to version 3.00)
% 15/01/20: (3.01) Clarified/fixed error messages; Added error IDs; easier -update; various other small fixes
% 20/01/20: (3.02) Attempted fix for issue #285 (unsupported patch transparency in some Ghostscript versions); Improved suggested fixes message upon error
% 03/03/20: (3.03) Suggest to upload problematic EPS file in case of a Ghostscript error in eps2pdf (& don't delete this file)
% 22/03/20: (3.04) Workaround for issue #15; Alert if ghostscript file not found on Matlab path
% 10/05/20: (3.05) Fix the generated SVG file, based on Cris Luengo's SVG_FIX_VIEWBOX; Don't generate PNG when only SVG is requested
% 02/07/20: (3.06) Significantly improved performance (speed) and fidelity of bitmap images; Return alpha matrix for bitmap images; Fixed issue #302 (-update bug); Added EMF output; Added -clipboard formats (image,bitmap,emf,pdf); Added hints for exportgraphics/copygraphics usage in certain use-cases; Added description of new version features in the update message; Fixed issue #306 (yyaxis cropping); Fixed EPS/PDF auto-cropping with -transparent
% 06/07/20: (3.07) Fixed issue #307 (bug in padding of bitmap images); Fixed axes transparency in -clipboard:emf with -transparent
% 07/07/20: (3.08) Fixed issue #308 (bug in R2019a and earlier)
% 18/07/20: (3.09) Fixed issue #310 (bug with tiny image on HG1); Fixed title cropping bug
% 23/07/20: (3.10) Fixed issues #313,314 (figure position changes if units ~= pixels); Display multiple versions change-log, if relevant; Fixed issue #312 (PNG: only use alpha channel if -transparent was requested)
% 30/07/20: (3.11) Fixed issue #317 (bug when exporting figure with non-pixels units); Potential solve also of issue #303 (size change upon export)
% 14/08/20: (3.12) Fixed some exportgraphics/copygraphics compatibility messages; Added -silent option to suppress non-critical messages; Reduced promo message display rate to once a week; Added progress messages during export_fig('-update')
% 07/10/20: (3.13) Added version info and change-log links to update message (issue #322); Added -version option to return the current export_fig version; Avoid JavaFrame warning message; Improved exportgraphics/copygraphics infomercial message inc. support of upcoming Matlab R2021a
% 10/12/20: (3.14) Enabled user-specified regexp replacements in generated EPS/PDF files (issue #324)
% 01/07/21: (3.15) Added informative message in case of setopacityalpha error (issue #285)
% 26/08/21: (3.16) Fixed problem of white elements appearing transparent (issue #330); clarified some error messages
% 27/09/21: (3.17) Made Matlab's builtin export the default for SVG, rather than fig2svg/plot2svg (issue #316); updated transparency error message (issues #285, #343); reduced promo message frequency
% 03/10/21: (3.18) Fixed warning about invalid escaped character when the output folder does not exist (issue #345)
% 25/10/21: (3.19) Fixed print error when exporting a specific subplot (issue #347); avoid duplicate error messages
% 11/12/21: (3.20) Added GIF support, including animated & transparent-background; accept format options as cell-array, not just nested struct
% 20/12/21: (3.21) Speedups; fixed exporting non-current figure (hopefully fixes issue #318); fixed warning when appending to animated GIF
% 02/03/22: (3.22) Fixed small potential memory leak during screen-capture; expanded exportgraphics message for vector exports; fixed rotated tick labels on R2021a+
% 02/03/22: (3.23) Added -toolbar and -menubar options to add figure toolbar/menubar items for interactive figure export (issue #73); fixed edge-case bug with GIF export
% 14/03/22: (3.24) Added support for specifying figure name in addition to handle; added warning when trying to export TIF/JPG/BMP with transparency; use current figure as default handle even when its HandleVisibility is not 'on'
% 16/03/22: (3.25) Fixed occasional empty files due to excessive cropping (issues #318, #350, #351)
% 01/05/22: (3.26) Added -transparency option for TIFF files
% 15/05/22: (3.27) Fixed EPS bounding box (issue #356)
% 04/12/22: (3.28) Added -metadata option to add custom info to PDF files; fixed -clipboard export (transparent and gray-scale images; deployed apps; old Matlabs)
% 03/01/23: (3.29) Use silent mode by default in deployed apps; suggest installing ghostscript/pdftops if required yet missing; fixed invalid chars in export filename; reuse existing figure toolbar if available
% 03/02/23: (3.30) Added -contextmenu option to add interactive context-menu items; fixed: -menubar,-toolbar created the full default figure menubar/toolbar if not shown; enlarged toolbar icon; support adding export_fig icon to custom toolbars; alert if specifying multiple or invalid handle(s)
% 20/02/23: (3.31) Fixed PDF quality issues as suggested by @scholnik (issues #285, #368); minor fixes for MacOS/Linux; use figure's FileName property (if available) as the default export filename; added -gif optional format parameter; Display the export folder (full pathname) in menu items when using -toolbar, -menubar and/or -contextmenu
% 21/02/23: (3.32) Fixed EPS export error handling in deployed apps; use Matlab's builtin EPS export if pdftops is not installed or fails; disabled EMF export option on MacOS/Linux; fixed some EMF warning messages; don't export PNG if only -toolbar etc were specified
% 23/02/23: (3.33) Fixed PDF -append (issue #369); Added -notify option to notify user when the export is done; propagate all specified export_fig options to -toolbar,-menubar,-contextmenu exports; -silent is no longer set by default in deployed apps (i.e. you need to call -silent explicitly)
% 23/03/23: (3.34) Fixed error when exporting axes handle to clipboard without filename (issue #372)
% 11/04/23: (3.35) Added -n,-x,-s options to set min, max, and fixed output image size (issue #315)
% 13/04/23: (3.36) Reduced (hopefully fixed) unintended EPS/PDF image cropping (issues #97, #318); clarified warning in case of PDF/EPS export of transparent patches (issues #94, #106, #108)
% 23/04/23: (3.37) Fixed run-time error with old Matlab releases (issue #374); -notify console message about exported image now displays black (STDOUT) not red (STDERR)
% 15/05/23: (3.38) Fixed endless recursion when using export_fig in Live Scripts (issue #375); don't warn about exportgraphics/copygraphics alternatives in deployed mode
% 30/05/23: (3.39) Fixed exported bgcolor of uifigures or figures in Live Scripts (issue #377)
% 06/07/23: (3.40) For Tiff compression, use AdobeDeflate codec (if available) instead of Deflate (issue #379)
%}
if nargout
[imageData, alpha] = deal([]);
end
displaySuggestedWorkarounds = true;
% Ensure the figure is rendered correctly _now_ so that properties like axes limits are up-to-date
drawnow;
pause(0.05); % this solves timing issues with Java Swing's EDT (http://undocumentedmatlab.com/blog/solving-a-matlab-hang-problem)
% Display promo (just once every 10 days!)
persistent promo_time
if isempty(promo_time)
try promo_time = getpref('export_fig','promo_time'); catch, promo_time=-inf; end
end
if abs(now-promo_time) > 10 && ~isdeployed
programsCrossCheck;
msg = char('Gps!qspgfttjpobm!Nbumbc!bttjtubodf-!qmfbtf!dpoubdu!=%?'-1);
url = char('iuuqt;00VoepdvnfoufeNbumbc/dpn0dpotvmujoh'-1);
displayPromoMsg(msg, url);
promo_time = now;
setpref('export_fig','promo_time',now)
end
% Use the current figure as the default figure handle
% temporarily set ShowHiddenHandles='on' to access figure with HandleVisibility='off'
try oldValue = get(0,'ShowHiddenHandles'); set(0,'ShowHiddenHandles','on'); catch, end
fig = get(0, 'CurrentFigure');
try set(0,'ShowHiddenHandles',oldValue); catch, end
% Parse the input arguments
argNames = {};
for idx = nargin:-1:1, argNames{idx} = inputname(idx); end
[fig, options] = parse_args(nargout, fig, argNames, varargin{:});
% Check for newer version and exportgraphics/copygraphics compatibility
currentVersion = 3.40;
if options.version % export_fig's version requested - return it and bail out
imageData = currentVersion;
return
end
if ~options.silent && ~isdeployed
% Check for newer version (not too often)
checkForNewerVersion(currentVersion); % this breaks in version 3.05- due to regexp limitation in checkForNewerVersion()
% Hint to users to use exportgraphics/copygraphics in certain cases
alertForExportOrCopygraphics(options);
%return
end
% Ensure that we have a scalar valid figure handle
if isequal(fig,-1)
return % silent bail-out
elseif isempty(fig)
error('export_fig:NoFigure','No figure found');
elseif numel(fig) > 1
error('export_fig:MultipleFigures','export_fig can only process one figure at a time');
elseif ~ishandle(fig)
error('export_fig:InvalidHandle','invalid figure handle specified to export_fig');
elseif ~isequal(getappdata(fig,'isExportFigCopy'),true)
oldWarn = warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame');
warning off MATLAB:ui:javaframe:PropertyToBeRemoved
hFig = handle(ancestor(fig,'figure'));
try jf = get(hFig,'JavaFrame_I'); catch, try jf = get(hFig,'JavaFrame'); catch, jf=1; end, end %#ok<JAVFM>
warning(oldWarn);
if isempty(jf) % this is a uifigure
%error('export_fig:uifigures','Figures created using the uifigure command or App Designer are not supported by export_fig. See %s for details.', hyperlink('https://github.com/altmany/export_fig/issues/261','issue #261'));
if numel(fig) > 1
error('export_fig:uifigure:multipleHandles', 'export_fig only supports exporting a single uifigure handle at a time; array of handles is not currently supported.')
elseif ~any(strcmpi(fig.Type,{'figure','axes'}))
error('export_fig:uifigure:notFigureOrAxes', 'export_fig only supports exporting a uifigure or uiaxes handle; other handles of a uifigure are not currently supported.')
end
% fig is either a uifigure or uiaxes handle
isUiaxes = strcmpi(fig.Type,'axes');
if isUiaxes
% Label the specified axes so that we can find it in the legacy figure
oldUserData = fig.UserData;
tempStr = tempname;
fig.UserData = tempStr;
end
try
% Create an invisible legacy figure at the same position/size as the uifigure
hNewFig = figure('Visible','off', 'Color',hFig.Color, ...
'Units',hFig.Units, 'Position',hFig.Position, ...
'MenuBar','none', 'ToolBar','none');
% Copy the uifigure contents onto the new invisible legacy figure
try
hChildren = allchild(hFig); %=uifig.Children;
copyobj(hChildren,hNewFig);
catch
if ~options.silent
warning('export_fig:uifigure:controls', 'Some uifigure controls cannot be exported by export_fig and will not appear in the generated output.');
end
end
try fig.UserData = oldUserData; catch, end % restore axes UserData, if modified above
setappdata(hNewFig,'isExportFigCopy',true); % avoid endless recursion (issue #375)
% Replace the uihandle in the input args with the legacy handle
if isUiaxes % uiaxes
% Locate the corresponding axes handle in the new legacy figure
hAxes = findall(hNewFig,'type','axes','UserData',tempStr);
if isempty(hAxes) % should never happen, check just in case
hNewHandle = hNewFig; % export the figure instead of the axes
else
hNewHandle = hAxes; % new axes handle found: use it instead of the uiaxes
end
else % uifigure
hNewHandle = hNewFig;
end
varargin(cellfun(@(c)isequal(c,fig),varargin)) = {hNewHandle};
% Rerun export_fig on the legacy figure (with the replaced handle)
[imageData, alpha] = export_fig(varargin{:});
% Delete the temp legacy figure and bail out
try delete(hNewFig); catch, end
return
catch err
% Clean up the temp legacy figure and report the error
try delete(hNewFig); catch, end
rethrow(err)
end
end
end
% If toolbar button was requested, add it to the specified figure(s)
if options.toolbar
addToolbarButton(hFig, options);
end
% If menubar menu was requested, add it to the specified figure(s)
if options.menubar
addMenubarMenu(hFig, options);
end
% If context-menu was requested, add it to the specified handle(s)
if options.contextmenu
addContextMenu(hFig, options);
end
% Isolate the subplot, if it is one
cls = all(ismember(get(fig, 'Type'), {'axes', 'uipanel'}));
if cls
% Given handles of one or more axes, so isolate them from the rest
fig = isolate_axes(fig);
else
% Check we have a figure
if ~isequal(get(fig, 'Type'), 'figure')
error('export_fig:BadHandle','Handle must be that of a figure, axes or uipanel');
end
% Get the old InvertHardcopy mode
old_mode = get(fig, 'InvertHardcopy');
end
% from this point onward, fig is assured to be a figure handle
% Hack the font units where necessary (due to a font rendering bug in print?).
% This may not work perfectly in all cases.
% Also it can change the figure layout if reverted, so use a copy.
magnify = options.magnify * options.aa_factor;
if isbitmap(options) && magnify ~= 1
fontu = findall(fig, 'FontUnits', 'normalized');
if ~isempty(fontu)
% Some normalized font units found
if ~cls
fig = copyfig(fig);
set(fig, 'Visible', 'off');
fontu = findall(fig, 'FontUnits', 'normalized');
cls = true;
end
set(fontu, 'FontUnits', 'points');
end
end
try
% MATLAB "feature": axes limits and tick marks can change when printing
Hlims = findall(fig, 'Type', 'axes');
if ~cls
% Record the old axes limit and tick modes
Xlims = make_cell(get(Hlims, 'XLimMode'));
Ylims = make_cell(get(Hlims, 'YLimMode'));
Zlims = make_cell(get(Hlims, 'ZLimMode'));
Xtick = make_cell(get(Hlims, 'XTickMode'));
Ytick = make_cell(get(Hlims, 'YTickMode'));
Ztick = make_cell(get(Hlims, 'ZTickMode'));
Xlabel = make_cell(get(Hlims, 'XTickLabelMode'));
Ylabel = make_cell(get(Hlims, 'YTickLabelMode'));
Zlabel = make_cell(get(Hlims, 'ZTickLabelMode'));
try % XTickLabelRotation etc. was added in R2021a
Xtkrot = make_cell(get(Hlims, 'XTickLabelRotationMode'));
Ytkrot = make_cell(get(Hlims, 'YTickLabelRotationMode'));
Ztkrot = make_cell(get(Hlims, 'ZTickLabelRotationMode'));
catch
end % only in R2021a+
end
% Set all axes limit and tick modes to manual, so the limits and ticks can't change
% Fix Matlab R2014b bug (issue #34): plot markers are not displayed when ZLimMode='manual'
set_manual_axes_modes(Hlims, 'X');
set_manual_axes_modes(Hlims, 'Y');
if ~using_hg2(fig)
set_manual_axes_modes(Hlims, 'Z');
end
catch
% ignore - fix issue #4 (using HG2 on R2014a and earlier)
end
% Fix issue #21 (bold TeX axes labels/titles in R2014b when exporting to EPS/PDF)
try
if using_hg2(fig) && isvector(options)
% Set the FontWeight of axes labels/titles to 'normal'
% Fix issue #69: set non-bold font only if the string contains symbols (\beta etc.)
% Issue #243: only set non-bold font (workaround for issue #69) in R2015b or earlier
try isPreR2016a = verLessThan('matlab','8.7'); catch, isPreR2016a = true; end
if isPreR2016a
texLabels = findall(fig, 'type','text', 'FontWeight','bold');
symbolIdx = ~cellfun('isempty',strfind({texLabels.String},'\'));
if ~isempty(symbolIdx)
set(texLabels(symbolIdx), 'FontWeight','normal');
if ~options.silent
warning('export_fig:BoldTexLabels', 'Bold labels with Tex symbols converted into non-bold in export_fig (fix for issue #69)');
end
end
end
end
catch
% ignore
end
% Fix issue #42: non-normalized annotations on HG1 (internal Matlab bug)
annotationHandles = [];
try
if ~using_hg2(fig)
annotationHandles = findall(fig,'Type','hggroup','-and','-property','Units','-and','-not','Units','norm');
try % suggested by Jesús Pestana Puerta (jespestana) 30/9/2015
originalUnits = get(annotationHandles,'Units');
set(annotationHandles,'Units','norm');
catch
end
end
catch
% should never happen, but ignore in any case - issue #50
end
% Fix issue #46: Ghostscript crash if figure units <> pixels
pos = get(fig, 'Position'); % Fix issues #313, #314
oldFigUnits = get(fig,'Units');
set(fig,'Units','pixels');
pixelpos = get(fig, 'Position'); %=getpixelposition(fig);
tcol = get(fig, 'Color');
tcol_orig = tcol;
% Set to print exactly what is there
if options.invert_hardcopy
try set(fig, 'InvertHardcopy', 'off'); catch, end % fail silently in uifigures
end
% Set the renderer
switch options.renderer
case 1
renderer = '-opengl';
case 2
renderer = '-zbuffer';
case 3
renderer = '-painters';
otherwise
renderer = '-opengl'; % Default for bitmaps
end
% Initialize
tmp_nam = '';
exported_files = 0;
% Main processing
try
oldWarn = warning;
% Export bitmap formats first
if isbitmap(options)
if abs(options.bb_padding) > 1
displaySuggestedWorkarounds = false;
error('export_fig:padding','For bitmap output (png,jpg,tif,bmp) the padding value (-p) must be between -1<p<1')
end
% Print large version to array
[A, tcol, alpha] = getFigImage(fig, magnify, renderer, options, pixelpos);
% Get the background colour
if options.transparent
if (options.png || options.alpha || options.gif || options.tif)
try %options.aa_factor < 4 % default, faster but lines are not anti-aliased
% If all pixels are indicated as opaque (i.e. something went wrong with the Java screen-capture)
isBgColor = A(:,:,1) == tcol(1) & ...
A(:,:,2) == tcol(2) & ...
A(:,:,3) == tcol(3);
% Set the bgcolor pixels to be fully-transparent
A(repmat(isBgColor,[1,1,3])) = 254; %=off-white % TODO: more memory efficient without repmat
alpha(isBgColor) = 0;
catch % older logic - much slower and causes figure flicker
if true % to fold the code below...
% Get out an alpha channel
% MATLAB "feature": black colorbar axes can change to white and vice versa!
hCB = findall(fig, 'Type','axes', 'Tag','Colorbar');
if isempty(hCB)
yCol = [];
xCol = [];
else
yCol = get(hCB, 'YColor');
xCol = get(hCB, 'XColor');
if iscell(yCol)
yCol = cell2mat(yCol);
xCol = cell2mat(xCol);
end
yCol = sum(yCol, 2);
xCol = sum(xCol, 2);
end
% MATLAB "feature": apparently figure size can change when changing
% colour in -nodisplay mode
% Set the background colour to black, and set size in case it was
% changed internally
set(fig, 'Color', 'k', 'Position', pos);
% Correct the colorbar axes colours
set(hCB(yCol==0), 'YColor', [0 0 0]);
set(hCB(xCol==0), 'XColor', [0 0 0]);
% Correct black axes color to off-black (issue #249)
hAxes = findall(fig, 'Type','axes');
[hXs,hXrs] = fixBlackAxle(hAxes, 'XColor');
[hYs,hYrs] = fixBlackAxle(hAxes, 'YColor');
[hZs,hZrs] = fixBlackAxle(hAxes, 'ZColor');
% The following code might cause out-of-memory errors
try
% Print large version to array
B = print2array(fig, magnify, renderer);
% Downscale the image
B = downsize(single(B), options.aa_factor);
catch
% This is more conservative in memory, but kills transparency (issue #58)
B = single(print2array(fig, magnify/options.aa_factor, renderer));
end
% Set background to white (and set size)
set(fig, 'Color', 'w', 'Position', pos);
% Correct the colorbar axes colours
set(hCB(yCol==3), 'YColor', [1 1 1]);
set(hCB(xCol==3), 'XColor', [1 1 1]);
% Revert the black axes colors
set(hXs, 'XColor', [0,0,0]);
set(hYs, 'YColor', [0,0,0]);
set(hZs, 'ZColor', [0,0,0]);
set(hXrs, 'Color', [0,0,0]);
set(hYrs, 'Color', [0,0,0]);
set(hZrs, 'Color', [0,0,0]);
% The following code might cause out-of-memory errors
try
% Print large version to array
A = print2array(fig, magnify, renderer);
% Downscale the image
A = downsize(single(A), options.aa_factor);
catch
% This is more conservative in memory, but kills transparency (issue #58)
A = single(print2array(fig, magnify/options.aa_factor, renderer));
end
% Workaround for issue #15
szA = size(A);
szB = size(B);
if ~isequal(szA,szB)
A = A(1:min(szA(1),szB(1)), 1:min(szA(2),szB(2)), :);
B = B(1:min(szA(1),szB(1)), 1:min(szA(2),szB(2)), :);
if ~options.silent
warning('export_fig:bitmap:sizeMismatch','Problem detected by export_fig generation of a bitmap image; the generated export may look bad. Try to reduce the figure size to fit the screen, or avoid using export_fig''s -transparent option.')
end
end
% Compute the alpha map
alpha = round(sum(B - A, 3)) / (255 * 3) + 1;
A = alpha;
A(A==0) = 1;
A = B ./ A(:,:,[1 1 1]);
clear B
end %folded code...
end
%A = uint8(A);
else % JPG,BMP
warning('export_fig:unsupported:background','Matlab cannot set transparency when exporting JPG/BMP image files (see imwrite function documentation)')
end
end
% Downscale the image if its size was increased (for anti-aliasing)
if size(A,1) > 1.1 * options.magnify * pixelpos(4) %1.1 to avoid edge-cases
% Downscale the image
A = downsize(A, options.aa_factor);
alpha = downsize(alpha, options.aa_factor);
end
% Crop the margins based on the bgcolor, if requested
if options.crop
%[alpha, v] = crop_borders(alpha, 0, 1, options.crop_amounts);
%A = A(v(1):v(2),v(3):v(4),:);
[A, vA, vB] = crop_borders(A, tcol, options.bb_padding, options.crop_amounts);
if ~any(isnan(vB)) % positive padding
sz = size(A); % Fix issue #308
B = repmat(uint8(zeros(1,1,size(alpha,3))),sz([1,2])); % Fix issue #307 %=zeros(sz([1,2]),'uint8');
B(vB(1):vB(2), vB(3):vB(4), :) = alpha(vA(1):vA(2), vA(3):vA(4), :); % ADDED BY OH
alpha = B;
else % negative padding
alpha = alpha(vA(1):vA(2), vA(3):vA(4), :);
end
end
% Get the non-alpha image (presumably unneeded with Java-based screen-capture)
%{
if isbitmap(options)
% Modify the intensity of the pixels' RGB values based on their alpha transparency
% TODO: not sure that we want this with Java screen-capture values!
alph = alpha(:,:,ones(1, size(A, 3)));
A = uint8(single(A) .* alph + 255 * (1 - alph));
end
%}
% Revert the figure properties back to their original values
set(fig, 'Units',oldFigUnits, 'Position',pos, 'Color',tcol_orig);
% Check for greyscale images
if options.colourspace == 2
% Convert to greyscale
A = rgb2grey(A);
else
% Return only one channel for greyscale
A = check_greyscale(A);
end
% Change alpha from [0:255] uint8 => [0:1] single from here onward:
alpha = single(alpha) / 255;
% Clamp the image's min/max size (if specified)
sz = size(A); sz(3:end) = []; %sz=size(A,1:2); %issue #374 & X. Xu PM
szNew = options.min_size;
if numel(szNew) == 2
szNew(isinf(szNew)) = 0;
szNew = round(max(sz,szNew,'includenan'));
idxToCompare = ~isnan(szNew);
if ~isequal(sz(idxToCompare), szNew(idxToCompare))
A = imresize(A,szNew);
alpha = imresize(alpha,szNew);
end
end
szNew = options.max_size;
if numel(szNew) == 2
szNew(szNew <= 1) = inf;
szNew = round(min(sz,szNew,'includenan'));
idxToCompare = ~isnan(szNew);
if ~isequal(sz(idxToCompare), szNew(idxToCompare))
A = imresize(A,szNew);
alpha = imresize(alpha,szNew);
end
end
% Clamp the image's fixed size (if specified) - has to be done last!
szNew = options.fixed_size;
if numel(szNew) == 2
if szNew(1) < 0, szNew(1) = round(-sz(1)*szNew(1)/100); end
if szNew(2) < 0, szNew(2) = round(-sz(2)*szNew(2)/100); end
szNew(szNew <= 1) = inf;
szNew(isinf(szNew)) = sz(isinf(szNew)); % unchanged dimensions
idxToCompare = ~isnan(szNew);
if ~isequal(sz(idxToCompare), szNew(idxToCompare))
A = imresize(A,szNew);
alpha = imresize(alpha,szNew);
end
end
% Outputs
if options.im
imageData = A;
end
if options.alpha
imageData = A;
%alpha = ones(size(A, 1), size(A, 2), 'single'); %=all pixels opaque
end
% Save the images
if options.png
% Compute the resolution
res = options.magnify * get(0, 'ScreenPixelsPerInch') / 25.4e-3;
% Save the png
[format_options, bitDepth] = getFormatOptions(options, 'png'); %Issue #269
filename = [options.name '.png'];
pngOptions = {filename, 'ResolutionUnit','meter', 'XResolution',res, 'YResolution',res, format_options{:}}; %#ok<CCAT>
if options.transparent % Fix issue #312: only use alpha channel if -transparent was requested
pngOptions = [pngOptions 'Alpha',double(alpha)];
end
if ~isempty(bitDepth) && bitDepth < 16 && size(A,3) == 3
% BitDepth specification requires using a color-map
[img, map] = rgb2ind(A, 256);
imwrite(img, map, pngOptions{:});
else
imwrite(A, pngOptions{:});
end
if options.notify, notify(filename); end
end
if options.bmp
filename = [options.name '.bmp'];
imwrite(A, filename);
if options.notify, notify(filename); end
end
if options.jpg
% Save jpeg with the specified quality
quality = options.quality;
if isempty(quality)
quality = 95;
end
format_options = getFormatOptions(options, 'jpg'); %Issue #269
filename = [options.name '.jpg'];
if quality > 100
imwrite(A, filename, 'Mode','lossless', format_options{:});
else
imwrite(A, filename, 'Quality',quality, format_options{:});
end
if options.notify, notify(filename); end
end
if options.tif
% Save tif images in cmyk if wanted (and possible)
if options.colourspace == 1 && size(A, 3) == 3
img = double(255 - A);
K = min(img, [], 3);
K_ = 255 ./ max(255 - K, 1);
C = (img(:,:,1) - K) .* K_;
M = (img(:,:,2) - K) .* K_;
Y = (img(:,:,3) - K) .* K_;
img = uint8(cat(3, C, M, Y, K));
clear C M Y K K_
else
img = A;
end
resolution = options.magnify * get(0,'ScreenPixelsPerInch');
filename = [options.name '.tif'];
if options.transparent && any(alpha(:) < 1) && any(isBgColor(:))
% Need to use low-level Tiff library since imwrite/writetif doesn't support alpha channel
alpha8 = uint8(alpha*255);
tag = ['Matlab ' version ' export_fig v' num2str(currentVersion)];
mode = 'w'; if options.append, mode = 'a'; end
t = Tiff(filename,mode); %R2009a or newer
%See https://www.awaresystems.be/imaging/tiff/tifftags/baseline.html
t.setTag('ImageLength', size(img,1));
t.setTag('ImageWidth', size(img,2));
t.setTag('Photometric', Tiff.Photometric.RGB);
try %issue #379 use Tiff.Compression.AdobeDeflate by default
compressionMode = Tiff.Compression.AdobeDeflate;
catch
warning off imageio:tiffmexutils:libtiffWarning %issue #379
compressionMode = Tiff.Compression.Deflate;
end
t.setTag('Compression', compressionMode);
t.setTag('PlanarConfiguration', Tiff.PlanarConfiguration.Chunky);
t.setTag('ExtraSamples', Tiff.ExtraSamples.AssociatedAlpha);
t.setTag('ResolutionUnit', Tiff.ResolutionUnit.Inch);
t.setTag('BitsPerSample', 8);
t.setTag('SamplesPerPixel',size(img,3)+1); %+1=alpha channel
t.setTag('XResolution', resolution);
t.setTag('YResolution', resolution);
t.setTag('Software', tag);
t.write(cat(3,img,alpha8));
t.close;
else
% Use the builtin imwrite/writetif function
append_mode = {'overwrite', 'append'};
mode = append_mode{options.append+1};
format_options = getFormatOptions(options, 'tif'); %Issue #269
imwrite(img, filename, 'Resolution',resolution, 'WriteMode',mode, format_options{:});
end
if options.notify, notify(filename); end
end
if options.gif
% TODO - merge contents with im2gif.m
% Convert to color-map image required by GIF specification
[img, map] = rgb2ind(A, 256);
% Handle the case of trying to append to non-existing GIF file
% (imwrite() croaks when asked to append to a non-existing file)
filename = [options.name '.gif'];
options.append = options.append && existFile(filename);
% Set the default GIF options for imwrite()
append_mode = {'overwrite', 'append'};
writeMode = append_mode{options.append+1};
gifOptions = {'WriteMode',writeMode};
if options.transparent % only use alpha channel if -transparent was requested
exp = 256 .^ (0:2);
mapVals = sum(round(map*255).*exp,2);
tcolVal = sum(round(double(tcol)).*exp);
alphaIdx = find(mapVals==tcolVal,1);
if isempty(alphaIdx) || alphaIdx <= 0, alphaIdx = 1; end
% GIF color index of uint8/logical images starts at 0, not 1
if ~isfloat(img), alphaIdx = alphaIdx - 1; end
gifOptions = [gifOptions, 'TransparentColor',alphaIdx, ...
'DisposalMethod','restoreBG'];
else
alphaIdx = 1;
end
if ~options.append
% LoopCount and BackgroundColor can only be specified in the
% 1st GIF frame (not in append mode)
% Set default LoopCount=65535 to enable looping within MS Office
gifOptions = [gifOptions, 'LoopCount',65535, 'BackgroundColor',alphaIdx];
end
% Set GIF-specific options specified by the user (if any)
format_options = getFormatOptions(options, 'gif');
gifOptions = [gifOptions, format_options{:}];
% Save the gif file
imwrite(img, map, filename, gifOptions{:});
if options.notify, notify(filename); end
end
end
% Now export the vector formats which are based on EPS
if isvector(options)
hImages = findall(fig,'type','image');
% Set the default renderer to painters
if ~options.renderer
% Handle transparent patches
hasTransparency = ~isempty(findall(fig,'-property','FaceAlpha','-and','-not','FaceAlpha',1));
if hasTransparency
% Alert if trying to export transparent patches/areas to non-supported outputs (issues #94, #106, #108)
% http://www.mathworks.com/matlabcentral/answers/265265-can-export_fig-or-else-draw-vector-graphics-with-transparent-surfaces
% TODO - use transparency when exporting to PDF by not passing via print2eps