JAL-3048 todo for export SVG/PNG/EPS
[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   public enum TYPE
80   {
81     EPS("EPS", MessageManager.getString("label.eps_file"), getEPSChooser()),
82     PNG("PNG", MessageManager.getString("label.png_image"),
83             getPNGChooser()),
84     SVG("SVG", "SVG", getSVGChooser());
85
86     private JalviewFileChooser chooser;
87
88     private String name;
89
90     private String label;
91
92     TYPE(String name, String label, JalviewFileChooser chooser)
93     {
94       this.name = name;
95       this.label = label;
96       this.chooser = chooser;
97     }
98
99     public String getName()
100     {
101       return name;
102     }
103
104     public JalviewFileChooser getChooser()
105     {
106       return chooser;
107     }
108
109     public String getLabel()
110     {
111       return label;
112     }
113
114   }
115
116   public ImageMaker(Component parent, TYPE type, String title, int width,
117           int height, File file, String fileTitle,
118           IProgressIndicator pIndicator, long pSessionId, boolean headless)
119   {
120     this.pIndicator = pIndicator;
121     this.type = type;
122     this.pSessionId = pSessionId;
123     this.headless = headless;
124     if (file == null)
125     {
126       // TODO: JAL-3048 export SVG/EPS/PNG- not required for Jalview-JS
127
128       setProgressMessage(MessageManager.formatMessage(
129               "status.waiting_for_user_to_select_output_file", type.name));
130       JalviewFileChooser chooser;
131       chooser = type.getChooser();
132       chooser.setFileView(new jalview.io.JalviewFileView());
133       chooser.setDialogTitle(title);
134       chooser.setToolTipText(MessageManager.getString("action.save"));
135       int value = chooser.showSaveDialog(parent);
136
137       if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
138       {
139         jalview.bin.Cache.setProperty("LAST_DIRECTORY",
140                 chooser.getSelectedFile().getParent());
141         file = chooser.getSelectedFile();
142       }
143       else
144       {
145         setProgressMessage(MessageManager.formatMessage(
146                 "status.cancelled_image_export_operation", type.name));
147       }
148     }
149     // TODO JAL-3048 refactor to method called by constructor or callback
150     if (file != null)
151     {
152       try
153       {
154         out = new FileOutputStream(file);
155         setProgressMessage(null);
156         setProgressMessage(MessageManager.formatMessage(
157                 "status.exporting_alignment_as_x_file", type.getName()));
158         if (type == TYPE.SVG)
159         {
160           setupSVG(width, height, fileTitle);
161         }
162         else if (type == TYPE.EPS)
163         {
164           setupEPS(width, height, fileTitle);
165         }
166         else if (type == TYPE.PNG)
167         {
168           setupPNG(width, height);
169         }
170
171       } catch (Exception ex)
172       {
173         System.out.println("Error creating " + type.getName() + " file.");
174
175         setProgressMessage(MessageManager
176                 .formatMessage("info.error_creating_file", type.getName()));
177       }
178     }
179   }
180
181   public Graphics getGraphics()
182   {
183     return graphics;
184   }
185
186   public void writeImage()
187   {
188     try
189     {
190       switch (type)
191       {
192       case EPS:
193         pg.flush();
194         pg.close();
195         break;
196       case SVG:
197         String svgData = ((SVGGraphics2D) getGraphics()).getSVGDocument();
198         out.write(svgData.getBytes());
199         out.flush();
200         out.close();
201         break;
202       case PNG:
203         ImageIO.write(bi, PNG_EXTENSION, out);
204         out.flush();
205         out.close();
206         break;
207       }
208     } catch (Exception ex)
209     {
210       ex.printStackTrace();
211     }
212   }
213
214   void setupEPS(int width, int height, String title)
215   {
216     boolean accurateText = true;
217
218     String renderStyle = jalview.bin.Cache.getDefault("EPS_RENDERING",
219             "Prompt each time");
220
221     // If we need to prompt, and if the GUI is visible then
222     // Prompt for EPS rendering style
223     if (renderStyle.equalsIgnoreCase("Prompt each time")
224             && !(System.getProperty("java.awt.headless") != null && System
225                     .getProperty("java.awt.headless").equals("true")))
226     {
227       EPSOptions eps = new EPSOptions();
228       renderStyle = eps.getValue();
229
230       if (renderStyle == null || eps.cancelled)
231       {
232         setProgressMessage(MessageManager.formatMessage(
233                 "status.cancelled_image_export_operation", "EPS"));
234         return;
235       }
236     }
237
238     if (renderStyle.equalsIgnoreCase("text"))
239     {
240       accurateText = false;
241     }
242
243     try
244     {
245       pg = new EpsGraphics2D(title, out, 0, 0, width, height);
246       Graphics2D ig2 = pg;
247       ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
248               RenderingHints.VALUE_ANTIALIAS_ON);
249
250       pg.setAccurateTextMode(accurateText);
251
252       graphics = pg;
253       setProgressMessage(MessageManager
254               .formatMessage("status.export_complete", type.getName()));
255     } catch (Exception ex)
256     {
257     }
258   }
259
260   void setupPNG(int width, int height)
261   {
262     bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
263     graphics = bi.getGraphics();
264     Graphics2D ig2 = (Graphics2D) graphics;
265     ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
266             RenderingHints.VALUE_ANTIALIAS_ON);
267     setProgressMessage(MessageManager
268             .formatMessage("status.export_complete", type.getName()));
269
270   }
271
272   void setupSVG(int width, int height, String title)
273   {
274
275     g2 = new SVGGraphics2D(width, height);
276     Graphics2D ig2 = g2;
277
278     String renderStyle = jalview.bin.Cache.getDefault("SVG_RENDERING",
279             "Prompt each time");
280
281     // If we need to prompt, and if the GUI is visible then
282     // Prompt for EPS rendering style
283     if (renderStyle.equalsIgnoreCase("Prompt each time")
284             && !(System.getProperty("java.awt.headless") != null && System
285                     .getProperty("java.awt.headless").equals("true")))
286     {
287       SVGOptions svgOption = new SVGOptions();
288       renderStyle = svgOption.getValue();
289
290       if (renderStyle == null || svgOption.cancelled)
291       {
292         setProgressMessage(MessageManager.formatMessage(
293                 "status.cancelled_image_export_operation", "SVG"));
294         return;
295       }
296     }
297
298     if (renderStyle.equalsIgnoreCase("Lineart"))
299     {
300       ig2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
301               SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
302     }
303
304     setProgressMessage(MessageManager
305             .formatMessage("status.export_complete", type.getName()));
306     graphics = g2;
307   }
308
309   static JalviewFileChooser getPNGChooser()
310   {
311     if (Jalview.isHeadlessMode())
312     {
313       return null;
314     }
315     return new JalviewFileChooser(PNG_EXTENSION, PNG_DESCRIPTION);
316   }
317
318   static JalviewFileChooser getEPSChooser()
319   {
320     if (Jalview.isHeadlessMode())
321     {
322       return null;
323     }
324     return new JalviewFileChooser(EPS_EXTENSION, EPS_DESCRIPTION);
325   }
326
327   private void setProgressMessage(String message)
328   {
329     if (pIndicator != null && !headless)
330     {
331       pIndicator.setProgressBar(message, pSessionId);
332     }
333   }
334
335   static JalviewFileChooser getSVGChooser()
336   {
337     if (Jalview.isHeadlessMode())
338     {
339       return null;
340     }
341     return new JalviewFileChooser(SVG_EXTENSION, SVG_DESCRIPTION);
342   }
343 }