099bcee5eec9db266c1862b26d0fb84b03b4b934
[jalview.git] / src / jalview / util / ImageMaker.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.util;
22
23 import jalview.bin.Jalview;
24 import jalview.gui.EPSOptions;
25 import jalview.gui.IProgressIndicator;
26 import jalview.gui.SVGOptions;
27 import jalview.io.JalviewFileChooser;
28
29 import java.awt.Component;
30 import java.awt.Graphics;
31 import java.awt.Graphics2D;
32 import java.awt.RenderingHints;
33 import java.awt.image.BufferedImage;
34 import java.io.File;
35 import java.io.FileOutputStream;
36
37 import javax.imageio.ImageIO;
38
39 import org.jfree.graphics2d.svg.SVGGraphics2D;
40 import org.jfree.graphics2d.svg.SVGHints;
41 import org.jibble.epsgraphics.EpsGraphics2D;
42
43 public class ImageMaker
44 {
45   public static final String SVG_DESCRIPTION = "Scalable Vector Graphics";
46
47   public static final String SVG_EXTENSION = "svg";
48
49   public static final String EPS_DESCRIPTION = "Encapsulated Postscript";
50
51   public static final String EPS_EXTENSION = "eps";
52
53   public static final String PNG_EXTENSION = "png";
54
55   public static final String PNG_DESCRIPTION = "Portable  network graphics";
56
57   public static final String HTML_EXTENSION = "html";
58
59   public static final String HTML_DESCRIPTION = "Hypertext Markup Language";
60
61   EpsGraphics2D pg;
62
63   SVGGraphics2D g2;
64
65   Graphics graphics;
66
67   FileOutputStream out;
68
69   BufferedImage bi;
70
71   TYPE type;
72
73   private IProgressIndicator pIndicator;
74
75   private long pSessionId;
76
77   private boolean headless;
78
79   /**
80    * Image format, currently either EPS, PNG or SVG
81    */
82   public enum TYPE
83   {
84     EPS("EPS", MessageManager.getString("label.eps_file"), EPS_EXTENSION,
85             EPS_DESCRIPTION),
86     PNG("PNG", MessageManager.getString("label.png_image"),
87             PNG_EXTENSION, PNG_DESCRIPTION),
88     SVG("SVG", "SVG", SVG_EXTENSION, SVG_DESCRIPTION);
89
90     private String name;
91
92     private String label;
93
94     private String extension;
95
96     private String description;
97
98     TYPE(String name, String label, String ext, String desc)
99     {
100       this.name = name;
101       this.label = label;
102       this.extension = ext;
103       this.description = desc;
104     }
105
106     public String getName()
107     {
108       return name;
109     }
110
111     public JalviewFileChooser getFileChooser()
112     {
113       return new JalviewFileChooser(extension, description);
114     }
115
116     public String getLabel()
117     {
118       return label;
119     }
120
121   }
122
123   /**
124    * Constructor that prepares the image context for writing to. If {@code file}
125    * is null, the user is prompted to choose a file.
126    * 
127    * @param parent
128    * @param type
129    * @param title
130    * @param width
131    * @param height
132    * @param file
133    * @param fileTitle
134    * @param pIndicator
135    * @param pSessionId
136    * @param headless
137    */
138   public ImageMaker(Component parent, TYPE type, String title, int width,
139           int height, File file, String fileTitle,
140           IProgressIndicator pIndicator, long pSessionId, boolean headless)
141   {
142     this.pIndicator = pIndicator;
143     this.type = type;
144     this.pSessionId = pSessionId;
145     this.headless = headless;
146     if (file == null)
147     {
148       setProgressMessage(MessageManager.formatMessage(
149               "status.waiting_for_user_to_select_output_file", type.name));
150       JalviewFileChooser chooser;
151       chooser = type.getFileChooser();
152       chooser.setFileView(new jalview.io.JalviewFileView());
153       chooser.setDialogTitle(title);
154       chooser.setToolTipText(MessageManager.getString("action.save"));
155       int value = chooser.showSaveDialog(parent);
156
157       if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
158       {
159         jalview.bin.Cache.setProperty("LAST_DIRECTORY",
160                 chooser.getSelectedFile().getParent());
161         file = chooser.getSelectedFile();
162       }
163       else
164       {
165         setProgressMessage(MessageManager.formatMessage(
166                 "status.cancelled_image_export_operation", type.name));
167       }
168     }
169
170     if (file != null)
171     {
172       try
173       {
174         out = new FileOutputStream(file);
175         setProgressMessage(null);
176         setProgressMessage(MessageManager.formatMessage(
177                 "status.exporting_alignment_as_x_file", type.getName()));
178         if (type == TYPE.SVG)
179         {
180           setupSVG(width, height, fileTitle);
181         }
182         else if (type == TYPE.EPS)
183         {
184           setupEPS(width, height, fileTitle);
185         }
186         else if (type == TYPE.PNG)
187         {
188           setupPNG(width, height);
189         }
190
191       } catch (Exception ex)
192       {
193         System.out.println("Error creating " + type.getName() + " file.");
194
195         setProgressMessage(MessageManager
196                 .formatMessage("info.error_creating_file", type.getName()));
197       }
198     }
199   }
200
201   public Graphics getGraphics()
202   {
203     return graphics;
204   }
205
206   public void writeImage()
207   {
208     try
209     {
210       switch (type)
211       {
212       case EPS:
213         pg.flush();
214         pg.close();
215         break;
216       case SVG:
217         String svgData = ((SVGGraphics2D) getGraphics()).getSVGDocument();
218         out.write(svgData.getBytes());
219         out.flush();
220         out.close();
221         break;
222       case PNG:
223         ImageIO.write(bi, PNG_EXTENSION, out);
224         out.flush();
225         out.close();
226         break;
227       }
228     } catch (Exception ex)
229     {
230       ex.printStackTrace();
231     }
232   }
233
234   void setupEPS(int width, int height, String title)
235   {
236     boolean accurateText = true;
237
238     String renderStyle = jalview.bin.Cache.getDefault("EPS_RENDERING",
239             "Prompt each time");
240
241     // If we need to prompt, and if the GUI is visible then
242     // Prompt for EPS rendering style
243     if (renderStyle.equalsIgnoreCase("Prompt each time")
244             && !(System.getProperty("java.awt.headless") != null && System
245                     .getProperty("java.awt.headless").equals("true")))
246     {
247       EPSOptions eps = new EPSOptions();
248       renderStyle = eps.getValue();
249
250       if (renderStyle == null || eps.cancelled)
251       {
252         setProgressMessage(MessageManager.formatMessage(
253                 "status.cancelled_image_export_operation", "EPS"));
254         return;
255       }
256     }
257
258     if (renderStyle.equalsIgnoreCase("text"))
259     {
260       accurateText = false;
261     }
262
263     try
264     {
265       pg = new EpsGraphics2D(title, out, 0, 0, width, height);
266       Graphics2D ig2 = pg;
267       ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
268               RenderingHints.VALUE_ANTIALIAS_ON);
269
270       pg.setAccurateTextMode(accurateText);
271
272       graphics = pg;
273       setProgressMessage(MessageManager
274               .formatMessage("status.export_complete", type.getName()));
275     } catch (Exception ex)
276     {
277     }
278   }
279
280   void setupPNG(int width, int height)
281   {
282     bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
283     graphics = bi.getGraphics();
284     Graphics2D ig2 = (Graphics2D) graphics;
285     ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
286             RenderingHints.VALUE_ANTIALIAS_ON);
287     setProgressMessage(MessageManager
288             .formatMessage("status.export_complete", type.getName()));
289
290   }
291
292   void setupSVG(int width, int height, String title)
293   {
294
295     g2 = new SVGGraphics2D(width, height);
296     Graphics2D ig2 = g2;
297
298     String renderStyle = jalview.bin.Cache.getDefault("SVG_RENDERING",
299             "Prompt each time");
300
301     // If we need to prompt, and if the GUI is visible then
302     // Prompt for EPS rendering style
303     if (renderStyle.equalsIgnoreCase("Prompt each time")
304             && !(System.getProperty("java.awt.headless") != null && System
305                     .getProperty("java.awt.headless").equals("true")))
306     {
307       SVGOptions svgOption = new SVGOptions();
308       renderStyle = svgOption.getValue();
309
310       if (renderStyle == null || svgOption.cancelled)
311       {
312         setProgressMessage(MessageManager.formatMessage(
313                 "status.cancelled_image_export_operation", "SVG"));
314         return;
315       }
316     }
317
318     if (renderStyle.equalsIgnoreCase("Lineart"))
319     {
320       ig2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
321               SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
322     }
323
324     setProgressMessage(MessageManager
325             .formatMessage("status.export_complete", type.getName()));
326     graphics = g2;
327   }
328
329   static JalviewFileChooser getPNGChooser()
330   {
331     if (Jalview.isHeadlessMode())
332     {
333       return null;
334     }
335     return new JalviewFileChooser(PNG_EXTENSION, PNG_DESCRIPTION);
336   }
337
338   static JalviewFileChooser getEPSChooser()
339   {
340     if (Jalview.isHeadlessMode())
341     {
342       return null;
343     }
344     return new JalviewFileChooser(EPS_EXTENSION, EPS_DESCRIPTION);
345   }
346
347   private void setProgressMessage(String message)
348   {
349     if (pIndicator != null && !headless)
350     {
351       pIndicator.setProgressBar(message, pSessionId);
352     }
353   }
354
355   static JalviewFileChooser getSVGChooser()
356   {
357     if (Jalview.isHeadlessMode())
358     {
359       return null;
360     }
361     return new JalviewFileChooser(SVG_EXTENSION, SVG_DESCRIPTION);
362   }
363 }