2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
23 import java.awt.Graphics;
24 import java.awt.Graphics2D;
25 import java.awt.RenderingHints;
26 import java.awt.image.BufferedImage;
28 import java.io.FileOutputStream;
29 import java.io.IOException;
31 import javax.imageio.ImageIO;
33 import org.jfree.graphics2d.svg.SVGGraphics2D;
34 import org.jfree.graphics2d.svg.SVGHints;
35 import org.jibble.epsgraphics.EpsGraphics2D;
37 import jalview.bin.Console;
38 import jalview.io.JalviewFileChooser;
39 import jalview.util.imagemaker.BitmapImageSizing;
41 public class ImageMaker
43 public static final String SVG_DESCRIPTION = "Scalable Vector Graphics";
45 public static final String SVG_EXTENSION = "svg";
47 public static final String EPS_DESCRIPTION = "Encapsulated Postscript";
49 public static final String EPS_EXTENSION = "eps";
51 public static final String PNG_EXTENSION = "png";
53 public static final String PNG_DESCRIPTION = "Portable network graphics";
67 EPS("EPS", MessageManager.getString("label.eps_file"), EPS_EXTENSION,
69 PNG("PNG", MessageManager.getString("label.png_image"), PNG_EXTENSION,
71 SVG("SVG", "SVG", SVG_EXTENSION, SVG_DESCRIPTION);
73 public final String name;
75 public final String label;
77 public final String extension;
79 public final String description;
81 TYPE(String name, String label, String ext, String desc)
86 this.description = desc;
89 public String getName()
94 public JalviewFileChooser getFileChooser()
96 return new JalviewFileChooser(extension, description);
99 public String getLabel()
107 * Constructor configures the graphics context ready for writing to
116 * @throws IOException
118 public ImageMaker(TYPE imageType, int width, int height, File file,
119 String fileTitle, boolean useLineart, BitmapImageSizing userBis)
122 this.type = imageType;
124 out = new FileOutputStream(file);
128 setupSVG(width, height, useLineart);
131 setupEPS(width, height, fileTitle, useLineart);
134 setupPNG(width, height, userBis);
140 public Graphics getGraphics()
146 * For SVG or PNG, writes the generated graphics data to the file output
147 * stream. For EPS, flushes the output graphics (which is written to file as
150 public void writeImage()
161 String svgData = ((SVGGraphics2D) getGraphics()).getSVGDocument();
162 out.write(svgData.getBytes());
167 ImageIO.write(bi, PNG_EXTENSION, out);
172 } catch (Exception ex)
174 ex.printStackTrace();
179 * Sets up a graphics object for the PNG image to be written on
185 protected void setupPNG(int width, int height, BitmapImageSizing userBis)
187 if (width == 0 || height == 0)
190 BitmapImageSizing bis = ImageMaker.getScaleWidthHeight(width, height,
192 float usescale = bis.scale();
193 int usewidth = bis.width();
194 int useheight = bis.height();
196 bi = new BufferedImage(usewidth, useheight, BufferedImage.TYPE_INT_RGB);
197 graphics = bi.getGraphics();
198 Graphics2D ig2 = (Graphics2D) graphics;
199 ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
200 RenderingHints.VALUE_ANTIALIAS_ON);
203 ig2.scale(usescale, usescale);
208 * A helper method to configure the SVG output graphics, with choice of Text
209 * or Lineart character rendering
214 * true for Lineart character rendering, false for Text
216 protected void setupSVG(int width, int height, boolean useLineart)
218 SVGGraphics2D g2 = new SVGGraphics2D(width, height);
221 g2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
222 SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
228 * A helper method that sets up the EPS graphics output with user choice of
229 * Text or Lineart character rendering
235 * true for Lineart character rendering, false for Text
236 * @throws IOException
238 protected void setupEPS(int width, int height, String title,
239 boolean useLineart) throws IOException
241 pg = new EpsGraphics2D(title, out, 0, 0, width, height);
243 ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
244 RenderingHints.VALUE_ANTIALIAS_ON);
245 pg.setAccurateTextMode(useLineart);
250 * Takes initial width and height, and suggested float scale, int width, int
251 * height and create a bounding box returned as a BitmapImageSizing object
252 * with consistent scale, width, height fields.
255 * The unscaled image width
257 * The unscaled image height
259 * The suggested scaling
261 * The suggested width
262 * @param bitmapheight
263 * The suggested height
264 * @return BitmapImageSizing A consistent scale,width and height for the final
267 public static BitmapImageSizing getScaleWidthHeight(int width, int height,
268 float scale, int bitmapwidth, int bitmapheight)
270 float usescale = 0.0f;
271 int usewidth = width;
272 int useheight = height;
274 if ((width == 0 && bitmapwidth > 0)
275 || (height == 0 && bitmapheight > 0))
277 // original image is zero sized! Avoid dividing by zero!
278 return BitmapImageSizing.nullBitmapImageSizing();
281 // use the smallest positive scale (i.e. fit in the box)
285 usewidth = Math.round(scale * width);
286 useheight = Math.round(scale * height);
290 float wscale = (float) bitmapwidth / width;
291 if (wscale > 0.0f && (usescale == 0.0f || wscale < usescale))
294 usewidth = bitmapwidth;
295 useheight = Math.round(usescale * height);
298 if (bitmapheight > 0)
300 float hscale = (float) bitmapheight / height;
301 if (hscale > 0.0f && (usescale == 0.0f || hscale < usescale))
304 usewidth = Math.round(usescale * width);
305 useheight = bitmapheight;
308 return new BitmapImageSizing(usescale, usewidth, useheight, false);
312 * Takes suggested scale, width, height as a BitmapImageSizing object and
313 * create a bounding box returned as a BitmapImageSizing object with
314 * consistent scale, width, height fields.
317 * @return BitmapImageSizing
319 public static BitmapImageSizing getScaleWidthHeight(int width, int height,
320 BitmapImageSizing bis)
322 return ImageMaker.getScaleWidthHeight(width, height, bis.scale(),
323 bis.width(), bis.height());
327 * Takes String versions of suggested float scale, int width, int height and
328 * create a bounding box returned as a BitmapImageSizing object with
329 * consistent scale, width, height fields.
334 * @return BitmapImageSizing
336 public static BitmapImageSizing parseScaleWidthHeightStrings(
337 String scaleS, String widthS, String heightS)
339 if (scaleS == null && widthS == null && heightS == null)
341 // if all items are null (i.e. not provided) we use the dynamic
342 // preferences set BIS
343 return BitmapImageSizing.defaultBitmapImageSizing();
354 scale = Float.parseFloat(scaleS);
355 } catch (NumberFormatException e)
357 Console.warn("Did not understand scale '" + scaleS
358 + "', won't be used.");
365 width = Integer.parseInt(widthS);
366 } catch (NumberFormatException e)
368 Console.warn("Did not understand width '" + widthS
369 + "', won't be used.");
376 height = Integer.parseInt(heightS);
377 } catch (NumberFormatException e)
379 Console.warn("Did not understand height '" + heightS
380 + "', won't be used.");
384 return new BitmapImageSizing(scale, width, height, false);