JAL-629 Fix --tempfac. Hide non-working --notempfac. Add --scale, --width, --height...
[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 java.awt.Graphics;
24 import java.awt.Graphics2D;
25 import java.awt.RenderingHints;
26 import java.awt.image.BufferedImage;
27 import java.io.File;
28 import java.io.FileOutputStream;
29 import java.io.IOException;
30
31 import javax.imageio.ImageIO;
32
33 import org.jfree.graphics2d.svg.SVGGraphics2D;
34 import org.jfree.graphics2d.svg.SVGHints;
35 import org.jibble.epsgraphics.EpsGraphics2D;
36
37 import jalview.io.JalviewFileChooser;
38
39 public class ImageMaker
40 {
41   public static final String SVG_DESCRIPTION = "Scalable Vector Graphics";
42
43   public static final String SVG_EXTENSION = "svg";
44
45   public static final String EPS_DESCRIPTION = "Encapsulated Postscript";
46
47   public static final String EPS_EXTENSION = "eps";
48
49   public static final String PNG_EXTENSION = "png";
50
51   public static final String PNG_DESCRIPTION = "Portable  network graphics";
52
53   EpsGraphics2D pg;
54
55   Graphics graphics;
56
57   FileOutputStream out;
58
59   BufferedImage bi;
60
61   TYPE type;
62
63   public enum TYPE
64   {
65     EPS("EPS", MessageManager.getString("label.eps_file"), EPS_EXTENSION,
66             EPS_DESCRIPTION),
67     PNG("PNG", MessageManager.getString("label.png_image"), PNG_EXTENSION,
68             PNG_DESCRIPTION),
69     SVG("SVG", "SVG", SVG_EXTENSION, SVG_DESCRIPTION);
70
71     public final String name;
72
73     public final String label;
74
75     public final String extension;
76
77     public final String description;
78
79     TYPE(String name, String label, String ext, String desc)
80     {
81       this.name = name;
82       this.label = label;
83       this.extension = ext;
84       this.description = desc;
85     }
86
87     public String getName()
88     {
89       return name;
90     }
91
92     public JalviewFileChooser getFileChooser()
93     {
94       return new JalviewFileChooser(extension, description);
95     }
96
97     public String getLabel()
98     {
99       return label;
100     }
101
102   }
103
104   /**
105    * Constructor configures the graphics context ready for writing to
106    * 
107    * @param imageType
108    * @param width
109    * @param height
110    * @param file
111    * @param fileTitle
112    * @param useLineart
113    * @param bitmapscale
114    * @throws IOException
115    */
116   public ImageMaker(TYPE imageType, int width, int height, File file,
117           String fileTitle, boolean useLineart, float bitmapscale,
118           int bitmapwidth, int bitmapheight) throws IOException
119   {
120     this.type = imageType;
121
122     out = new FileOutputStream(file);
123     switch (imageType)
124     {
125     case SVG:
126       setupSVG(width, height, useLineart);
127       break;
128     case EPS:
129       setupEPS(width, height, fileTitle, useLineart);
130       break;
131     case PNG:
132       setupPNG(width, height, bitmapscale, bitmapwidth, bitmapheight);
133       break;
134     default:
135     }
136   }
137
138   public Graphics getGraphics()
139   {
140     return graphics;
141   }
142
143   /**
144    * For SVG or PNG, writes the generated graphics data to the file output
145    * stream. For EPS, flushes the output graphics (which is written to file as
146    * it is generated).
147    */
148   public void writeImage()
149   {
150     try
151     {
152       switch (type)
153       {
154       case EPS:
155         pg.flush();
156         pg.close();
157         break;
158       case SVG:
159         String svgData = ((SVGGraphics2D) getGraphics()).getSVGDocument();
160         out.write(svgData.getBytes());
161         out.flush();
162         out.close();
163         break;
164       case PNG:
165         ImageIO.write(bi, PNG_EXTENSION, out);
166         out.flush();
167         out.close();
168         break;
169       }
170     } catch (Exception ex)
171     {
172       ex.printStackTrace();
173     }
174   }
175
176   /**
177    * Sets up a graphics object for the PNG image to be written on
178    * 
179    * @param width
180    * @param height
181    * @param scale
182    */
183   protected void setupPNG(int width, int height, float scale,
184           int bitmapwidth, int bitmapheight)
185   {
186     if (width == 0 || height == 0)
187       return;
188
189     float usescale = 0.0f;
190     int usewidth = width;
191     int useheight = height;
192
193     // use the smallest positive scale (i.e. fit in the box)
194     if (scale > 0.0f)
195     {
196       usescale = scale;
197       usewidth = Math.round(scale * width);
198       useheight = Math.round(scale * height);
199     }
200     if (bitmapwidth > 0)
201     {
202       float wscale = (float) bitmapwidth / width;
203       if (wscale > 0.0f && (usescale == 0.0f || wscale < usescale))
204       {
205         usescale = wscale;
206         usewidth = bitmapwidth;
207         useheight = Math.round(usescale * height);
208       }
209     }
210     if (bitmapheight > 0)
211     {
212       float hscale = (float) bitmapheight / height;
213       if (hscale > 0.0f && (usescale == 0.0f || hscale < usescale))
214       {
215         usescale = hscale;
216         usewidth = Math.round(usescale * width);
217         useheight = bitmapheight;
218       }
219     }
220     bi = new BufferedImage(usewidth, useheight, BufferedImage.TYPE_INT_RGB);
221     graphics = bi.getGraphics();
222     Graphics2D ig2 = (Graphics2D) graphics;
223     ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
224             RenderingHints.VALUE_ANTIALIAS_ON);
225     if (usescale > 0.0f)
226       ig2.scale(usescale, usescale);
227   }
228
229   /**
230    * A helper method to configure the SVG output graphics, with choice of Text
231    * or Lineart character rendering
232    * 
233    * @param width
234    * @param height
235    * @param useLineart
236    *          true for Lineart character rendering, false for Text
237    */
238   protected void setupSVG(int width, int height, boolean useLineart)
239   {
240     SVGGraphics2D g2 = new SVGGraphics2D(width, height);
241     if (useLineart)
242     {
243       g2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
244               SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
245     }
246     graphics = g2;
247   }
248
249   /**
250    * A helper method that sets up the EPS graphics output with user choice of
251    * Text or Lineart character rendering
252    * 
253    * @param width
254    * @param height
255    * @param title
256    * @param useLineart
257    *          true for Lineart character rendering, false for Text
258    * @throws IOException
259    */
260   protected void setupEPS(int width, int height, String title,
261           boolean useLineart) throws IOException
262   {
263     pg = new EpsGraphics2D(title, out, 0, 0, width, height);
264     Graphics2D ig2 = pg;
265     ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
266             RenderingHints.VALUE_ANTIALIAS_ON);
267     pg.setAccurateTextMode(useLineart);
268     graphics = pg;
269   }
270 }