001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 * image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause).
006 * Copyright (c) 2006-2023 Wilhelm Burger, Mark J. Burge. All rights reserved.
007 * Visit https://imagingbook.com for additional details.
008 ******************************************************************************/
009package Tools_;
010
011import ij.IJ;
012import ij.ImagePlus;
013import ij.gui.GenericDialog;
014import ij.io.SaveDialog;
015import ij.plugin.PlugIn;
016import imagingbook.core.FileUtils;
017import imagingbook.core.jdoc.JavaDocHelp;
018import imagingbook.pdf.PdfExporter;
019import imagingbook.pdf.PdfExporter.Parameters;
020import imagingbook.pdf.Utils;
021
022import java.awt.Desktop;
023import java.nio.file.Path;
024import java.nio.file.Paths;
025
026import static imagingbook.common.ij.DialogUtils.addToDialog;
027import static imagingbook.common.ij.DialogUtils.getFromDialog;
028
029/**
030 * This ImageJ plugin exports the current image and its attached vector graphic overlay (if existent) as a PDF file. It
031 * uses the free OpenPDF library, which is based on iText4 but LGPL-licensed (see
032 * <a href="https://github.com/LibrePDF/OpenPDF">https://github.com/LibrePDF/OpenPDF</a>).
033 *
034 * @author WB
035 * @version 2022/04/23 (removed DialogListener)
036 * @see PdfExporter
037 */
038public class Export_PDF implements PlugIn, JavaDocHelp {
039        
040//      TODO: fix current directory mechanism
041        
042        private static int MinImageWidth = 512; // used to suggest ImageUpscaleFactor
043        private static String DefaultFileExtension = ".pdf";
044        private static boolean OpenPdfAfterExport = false;
045        
046        private ImagePlus im;
047        private Parameters params;
048        
049        @Override
050        public void run(String arg) {
051                this.im = IJ.getImage();
052                if (im == null) 
053                        return;
054        
055                if (!Utils.verifyPdfLib()) {
056                        IJ.error("PDF library not found!");
057                        return;
058                }
059                
060                if (im.getStackSize() != 1) {
061                        IJ.error("Can only export single images (no stacks)!");
062                        return;
063                }
064                
065                // -------------------------------------------------
066                
067                int width = im.getWidth();
068                String filename = im.getShortTitle();
069
070                params = new Parameters();
071                params.title = im.getShortTitle();
072                params.upscaleFactor = (width >= MinImageWidth) ? 1 :
073                                        (int) Math.ceil((double)MinImageWidth / width) ;
074                params.upscaleImage = (params.upscaleFactor > 1);
075                params.includeOverlay = (im.getOverlay() != null);
076                                        
077                if (!runDialog(params)) {
078                        return;
079                }
080                
081                if (!params.upscaleImage || params.upscaleFactor < 1) {
082                        params.upscaleFactor = 1;
083                }
084                
085                if (params.upscaleImage && params.upscaleFactor > 1) {
086                        filename = filename + "-X" + params.upscaleFactor;
087                        params.title = params.title + " (" + params.upscaleFactor + "x upscaled)";
088                }
089                
090                String directory = FileUtils.getCurrentDirectory(this.getClass());
091                if (directory == null)
092                        directory = IJ.getDirectory("image");
093                
094                Path path = askForFilePath(directory, filename, "Save as PDF");
095                if (path == null) {
096                        return;
097                }
098                
099                directory = path.getParent().toString();
100                FileUtils.setCurrentDirectory(this.getClass(), path);
101                
102                // ----------------------------------------------------------------
103                PdfExporter exporter = new PdfExporter(im, params);
104                String finalPath = exporter.exportTo(path);
105                if (finalPath == null) 
106                        IJ.error("PDF export failed to " + path.toString());
107                else
108                        IJ.log("PDF exported to " + finalPath);
109                // ----------------------------------------------------------------
110                
111                if (OpenPdfAfterExport && Desktop.isDesktopSupported()) {
112                        Desktop dt = Desktop.getDesktop();
113                        try {
114                                dt.open(path.toFile());
115                        } catch (Exception ex) {
116                                IJ.error("Could not open PDF file " + finalPath);
117                        }
118                }
119        }
120
121        // ----------------------------------------------------------------------
122        
123        private boolean runDialog(Parameters params) {
124                GenericDialog gd = new GenericDialog("Export PDF");
125                gd.addHelp(getJavaDocUrl());
126                addToDialog(params, gd);
127                gd.addCheckbox("Open PDF after export", OpenPdfAfterExport);
128                
129                gd.showDialog();
130                if (gd.wasCanceled()) {
131                        return false;
132                }
133                
134                getFromDialog(params, gd);
135                OpenPdfAfterExport = gd.getNextBoolean();
136                return params.validate();
137        }
138        
139        // ----------------------------------------------------------------------
140        
141    private Path askForFilePath(String dir, String name, String title) {
142        SaveDialog od = new SaveDialog(title, dir, name, DefaultFileExtension);
143        dir  = od.getDirectory();
144        name = od.getFileName();
145        
146        if(name != null) {
147//              DefaultOutputDirectory = dir;
148                return Paths.get(dir, name);
149        }
150        else
151                return null;
152    }
153        
154}
155