Clover icon

Coverage Report

  1. Project Clover database Mon Nov 18 2024 09:38:20 GMT
  2. Package jalview.util

File ImageMaker.java

 

Coverage histogram

../../img/srcFileCovDistChart6.png
27% of files have more coverage

Code metrics

26
101
13
2
386
240
46
0.46
7.77
6.5
3.54

Classes

Class Line # Actions
ImageMaker 41 94 42
0.5348837453.5%
ImageMaker.TYPE 65 7 4
0.636363663.6%
 

Contributing tests

This file is covered by 7 tests. .

Source view

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.bin.Console;
38    import jalview.io.JalviewFileChooser;
39    import jalview.util.imagemaker.BitmapImageSizing;
40   
 
41    public class ImageMaker
42    {
43    public static final String SVG_DESCRIPTION = "Scalable Vector Graphics";
44   
45    public static final String SVG_EXTENSION = "svg";
46   
47    public static final String EPS_DESCRIPTION = "Encapsulated Postscript";
48   
49    public static final String EPS_EXTENSION = "eps";
50   
51    public static final String PNG_EXTENSION = "png";
52   
53    public static final String PNG_DESCRIPTION = "Portable network graphics";
54   
55    EpsGraphics2D pg;
56   
57    Graphics graphics;
58   
59    FileOutputStream out;
60   
61    BufferedImage bi;
62   
63    TYPE type;
64   
 
65    public enum TYPE
66    {
67    EPS("EPS", MessageManager.getString("label.eps_file"), EPS_EXTENSION,
68    EPS_DESCRIPTION),
69    PNG("PNG", MessageManager.getString("label.png_image"), PNG_EXTENSION,
70    PNG_DESCRIPTION),
71    SVG("SVG", "SVG", SVG_EXTENSION, SVG_DESCRIPTION);
72   
73    public final String name;
74   
75    public final String label;
76   
77    public final String extension;
78   
79    public final String description;
80   
 
81  3 toggle TYPE(String name, String label, String ext, String desc)
82    {
83  3 this.name = name;
84  3 this.label = label;
85  3 this.extension = ext;
86  3 this.description = desc;
87    }
88   
 
89  24 toggle public String getName()
90    {
91  24 return name;
92    }
93   
 
94  0 toggle public JalviewFileChooser getFileChooser()
95    {
96  0 return new JalviewFileChooser(extension, description);
97    }
98   
 
99  0 toggle public String getLabel()
100    {
101  0 return label;
102    }
103   
104    }
105   
106    /**
107    * Constructor configures the graphics context ready for writing to
108    *
109    * @param imageType
110    * @param width
111    * @param height
112    * @param file
113    * @param fileTitle
114    * @param useLineart
115    * @param bitmapscale
116    * @throws IOException
117    */
 
118  12 toggle public ImageMaker(TYPE imageType, int width, int height, File file,
119    String fileTitle, boolean useLineart, BitmapImageSizing userBis)
120    throws IOException
121    {
122  12 this.type = imageType;
123   
124  12 out = new FileOutputStream(file);
125  12 switch (imageType)
126    {
127  0 case SVG:
128  0 setupSVG(width, height, useLineart);
129  0 break;
130  0 case EPS:
131  0 setupEPS(width, height, fileTitle, useLineart);
132  0 break;
133  12 case PNG:
134  12 setupPNG(width, height, userBis);
135  12 break;
136  0 default:
137    }
138    }
139   
 
140  12 toggle public Graphics getGraphics()
141    {
142  12 return graphics;
143    }
144   
145    /**
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
148    * it is generated).
149    */
 
150  12 toggle public void writeImage()
151    {
152  12 try
153    {
154  12 switch (type)
155    {
156  0 case EPS:
157  0 pg.flush();
158  0 pg.close();
159  0 break;
160  0 case SVG:
161  0 String svgData = ((SVGGraphics2D) getGraphics()).getSVGDocument();
162  0 out.write(svgData.getBytes());
163  0 out.flush();
164  0 out.close();
165  0 break;
166  12 case PNG:
167  12 ImageIO.write(bi, PNG_EXTENSION, out);
168  12 out.flush();
169  12 out.close();
170  12 break;
171    }
172    } catch (Exception ex)
173    {
174  0 ex.printStackTrace();
175    }
176    }
177   
178    /**
179    * Sets up a graphics object for the PNG image to be written on
180    *
181    * @param width
182    * @param height
183    * @param scale
184    */
 
185  12 toggle protected void setupPNG(int width, int height, BitmapImageSizing userBis)
186    {
187  12 if (width == 0 || height == 0)
188  0 return;
189   
190  12 BitmapImageSizing bis = ImageMaker.getScaleWidthHeight(width, height,
191    userBis);
192  12 float usescale = bis.scale();
193  12 int usewidth = bis.width();
194  12 int useheight = bis.height();
195   
196  12 bi = new BufferedImage(usewidth, useheight, BufferedImage.TYPE_INT_RGB);
197  12 graphics = bi.getGraphics();
198  12 Graphics2D ig2 = (Graphics2D) graphics;
199  12 ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
200    RenderingHints.VALUE_ANTIALIAS_ON);
201  12 if (usescale > 0.0f)
202    {
203  0 ig2.scale(usescale, usescale);
204    }
205    }
206   
207    /**
208    * A helper method to configure the SVG output graphics, with choice of Text
209    * or Lineart character rendering
210    *
211    * @param width
212    * @param height
213    * @param useLineart
214    * true for Lineart character rendering, false for Text
215    */
 
216  0 toggle protected void setupSVG(int width, int height, boolean useLineart)
217    {
218  0 SVGGraphics2D g2 = new SVGGraphics2D(width, height);
219  0 if (useLineart)
220    {
221  0 g2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
222    SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
223    }
224  0 graphics = g2;
225    }
226   
227    /**
228    * A helper method that sets up the EPS graphics output with user choice of
229    * Text or Lineart character rendering
230    *
231    * @param width
232    * @param height
233    * @param title
234    * @param useLineart
235    * true for Lineart character rendering, false for Text
236    * @throws IOException
237    */
 
238  0 toggle protected void setupEPS(int width, int height, String title,
239    boolean useLineart) throws IOException
240    {
241  0 pg = new EpsGraphics2D(title, out, 0, 0, width, height);
242  0 Graphics2D ig2 = pg;
243  0 ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
244    RenderingHints.VALUE_ANTIALIAS_ON);
245  0 pg.setAccurateTextMode(useLineart);
246  0 graphics = pg;
247    }
248   
249    /**
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.
253    *
254    * @param width
255    * The unscaled image width
256    * @param height
257    * The unscaled image height
258    * @param scale
259    * The suggested scaling
260    * @param bitmapwidth
261    * The suggested width
262    * @param bitmapheight
263    * The suggested height
264    * @return BitmapImageSizing A consistent scale,width and height for the final
265    * image
266    */
 
267  12 toggle public static BitmapImageSizing getScaleWidthHeight(int width, int height,
268    float scale, int bitmapwidth, int bitmapheight)
269    {
270  12 float usescale = 0.0f;
271  12 int usewidth = width;
272  12 int useheight = height;
273   
274  12 if ((width == 0 && bitmapwidth > 0)
275    || (height == 0 && bitmapheight > 0))
276    {
277    // original image is zero sized! Avoid dividing by zero!
278  0 return BitmapImageSizing.nullBitmapImageSizing();
279    }
280   
281    // use the smallest positive scale (i.e. fit in the box)
282  12 if (scale > 0.0f)
283    {
284  0 usescale = scale;
285  0 usewidth = Math.round(scale * width);
286  0 useheight = Math.round(scale * height);
287    }
288  12 if (bitmapwidth > 0)
289    {
290  0 float wscale = (float) bitmapwidth / width;
291  0 if (wscale > 0.0f && (usescale == 0.0f || wscale < usescale))
292    {
293  0 usescale = wscale;
294  0 usewidth = bitmapwidth;
295  0 useheight = Math.round(usescale * height);
296    }
297    }
298  12 if (bitmapheight > 0)
299    {
300  0 float hscale = (float) bitmapheight / height;
301  0 if (hscale > 0.0f && (usescale == 0.0f || hscale < usescale))
302    {
303  0 usescale = hscale;
304  0 usewidth = Math.round(usescale * width);
305  0 useheight = bitmapheight;
306    }
307    }
308  12 return new BitmapImageSizing(usescale, usewidth, useheight, false);
309    }
310   
311    /**
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.
315    *
316    * @param bis
317    * @return BitmapImageSizing
318    */
 
319  12 toggle public static BitmapImageSizing getScaleWidthHeight(int width, int height,
320    BitmapImageSizing bis)
321    {
322  12 return ImageMaker.getScaleWidthHeight(width, height, bis.scale(),
323    bis.width(), bis.height());
324    }
325   
326    /**
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.
330    *
331    * @param scaleS
332    * @param widthS
333    * @param heightS
334    * @return BitmapImageSizing
335    */
 
336  20 toggle public static BitmapImageSizing parseScaleWidthHeightStrings(
337    String scaleS, String widthS, String heightS)
338    {
339  20 if (scaleS == null && widthS == null && heightS == null)
340    {
341    // if all items are null (i.e. not provided) we use the dynamic
342    // preferences set BIS
343  14 return BitmapImageSizing.defaultBitmapImageSizing();
344    }
345   
346  6 float scale = 0.0f;
347  6 int width = 0;
348  6 int height = 0;
349   
350  6 if (scaleS != null)
351    {
352  4 try
353    {
354  4 scale = Float.parseFloat(scaleS);
355    } catch (NumberFormatException e)
356    {
357  0 Console.warn("Did not understand scale '" + scaleS
358    + "', won't be used.");
359    }
360    }
361  6 if (widthS != null)
362    {
363  3 try
364    {
365  3 width = Integer.parseInt(widthS);
366    } catch (NumberFormatException e)
367    {
368  0 Console.warn("Did not understand width '" + widthS
369    + "', won't be used.");
370    }
371    }
372  6 if (heightS != null)
373    {
374  3 try
375    {
376  3 height = Integer.parseInt(heightS);
377    } catch (NumberFormatException e)
378    {
379  0 Console.warn("Did not understand height '" + heightS
380    + "', won't be used.");
381    }
382    }
383   
384  6 return new BitmapImageSizing(scale, width, height, false);
385    }
386    }