View Javadoc

1   /* ============================================================
2    * JRobin : Pure java implementation of RRDTool's functionality
3    * ============================================================
4    *
5    * Project Info:  http://www.jrobin.org
6    * Project Lead:  Sasa Markovic (saxon@jrobin.org)
7    *
8    * Developers:    Sasa Markovic (saxon@jrobin.org)
9    *
10   *
11   * (C) Copyright 2003-2005, by Sasa Markovic.
12   *
13   * This library is free software; you can redistribute it and/or modify it under the terms
14   * of the GNU Lesser General Public License as published by the Free Software Foundation;
15   * either version 2.1 of the License, or (at your option) any later version.
16   *
17   * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18   * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19   * See the GNU Lesser General Public License for more details.
20   *
21   * You should have received a copy of the GNU Lesser General Public License along with this
22   * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23   * Boston, MA 02111-1307, USA.
24   */
25  package org.jrobin.graph;
26  
27  import com.sun.image.codec.jpeg.JPEGCodec;
28  import com.sun.image.codec.jpeg.JPEGEncodeParam;
29  import com.sun.image.codec.jpeg.JPEGImageEncoder;
30  
31  import javax.imageio.ImageIO;
32  import java.awt.*;
33  import java.awt.font.LineMetrics;
34  import java.awt.geom.AffineTransform;
35  import java.awt.image.BufferedImage;
36  import java.io.*;
37  
38  class ImageWorker {
39  	private static final String DUMMY_TEXT = "Dummy";
40  
41  	private BufferedImage img;
42  	private Graphics2D gd;
43  	private int imgWidth, imgHeight;
44  	private AffineTransform aftInitial;
45  
46  	ImageWorker(int width, int height) {
47  		resize(width, height);
48  	}
49  
50  	void resize(int width, int height) {
51  		if (gd != null) {
52  			gd.dispose();
53  		}
54  		this.imgWidth = width;
55  		this.imgHeight = height;
56  		this.img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
57  		this.gd = img.createGraphics();
58  		this.aftInitial = gd.getTransform();
59  		this.setAntiAliasing(false);
60  	}
61  
62  	void clip(int x, int y, int width, int height) {
63  		gd.setClip(x, y, width, height);
64  	}
65  
66  	void transform(int x, int y, double angle) {
67  		gd.translate(x, y);
68  		gd.rotate(angle);
69  	}
70  
71  	void reset() {
72  		gd.setTransform(aftInitial);
73  		gd.setClip(0, 0, imgWidth, imgHeight);
74  	}
75  
76  	void fillRect(int x, int y, int width, int height, Paint paint) {
77  		gd.setPaint(paint);
78  		gd.fillRect(x, y, width, height);
79  	}
80  
81  	void fillPolygon(int[] x, int[] y, Paint paint) {
82  		gd.setPaint(paint);
83  		gd.fillPolygon(x, y, x.length);
84  	}
85  
86  	void fillPolygon(double[] x, double yBottom, double[] yTop, Paint paint) {
87  		gd.setPaint(paint);
88  		PathIterator path = new PathIterator(yTop);
89  		for (int[] pos = path.getNextPath(); pos != null; pos = path.getNextPath()) {
90  			int start = pos[0], end = pos[1], n = end - start;
91  			int[] xDev = new int[n + 2], yDev = new int[n + 2];
92  			for (int i = start; i < end; i++) {
93  				xDev[i - start] = (int) x[i];
94  				yDev[i - start] = (int) yTop[i];
95  			}
96  			xDev[n] = xDev[n - 1];
97  			xDev[n + 1] = xDev[0];
98  			yDev[n] = yDev[n + 1] = (int) yBottom;
99  			gd.fillPolygon(xDev, yDev, xDev.length);
100 			gd.drawPolygon(xDev, yDev, xDev.length);
101 		}
102 	}
103 
104 	void fillPolygon(double[] x, double[] yBottom, double[] yTop, Paint paint) {
105 		gd.setPaint(paint);
106 		PathIterator path = new PathIterator(yTop);
107 		for (int[] pos = path.getNextPath(); pos != null; pos = path.getNextPath()) {
108 			int start = pos[0], end = pos[1], n = end - start;
109 			int[] xDev = new int[n * 2], yDev = new int[n * 2];
110 			for (int i = start; i < end; i++) {
111 				int ix1 = i - start, ix2 = n * 2 - 1 - i + start;
112 				xDev[ix1] = xDev[ix2] = (int) x[i];
113 				yDev[ix1] = (int) yTop[i];
114 				yDev[ix2] = (int) yBottom[i];
115 			}
116 			gd.fillPolygon(xDev, yDev, xDev.length);
117 			gd.drawPolygon(xDev, yDev, xDev.length);
118 		}
119 	}
120 
121 
122 	void drawLine(int x1, int y1, int x2, int y2, Paint paint, Stroke stroke) {
123 		gd.setStroke(stroke);
124 		gd.setPaint(paint);
125 		gd.drawLine(x1, y1, x2, y2);
126 	}
127 
128 	void drawPolyline(int[] x, int[] y, Paint paint, Stroke stroke) {
129 		gd.setStroke(stroke);
130 		gd.setPaint(paint);
131 		gd.drawPolyline(x, y, x.length);
132 	}
133 
134 	void drawPolyline(double[] x, double[] y, Paint paint, Stroke stroke) {
135 		gd.setPaint(paint);
136 		gd.setStroke(stroke);
137 		PathIterator path = new PathIterator(y);
138 		for (int[] pos = path.getNextPath(); pos != null; pos = path.getNextPath()) {
139 			int start = pos[0], end = pos[1];
140 			int[] xDev = new int[end - start], yDev = new int[end - start];
141 			for (int i = start; i < end; i++) {
142 				xDev[i - start] = (int) x[i];
143 				yDev[i - start] = (int) y[i];
144 			}
145 			gd.drawPolyline(xDev, yDev, xDev.length);
146 		}
147 	}
148 
149 	void drawString(String text, int x, int y, Font font, Paint paint) {
150 		gd.setFont(font);
151 		gd.setPaint(paint);
152 		gd.drawString(text, x, y);
153 	}
154 
155 	double getFontAscent(Font font) {
156 		LineMetrics lm = font.getLineMetrics(DUMMY_TEXT, gd.getFontRenderContext());
157 		return lm.getAscent();
158 	}
159 
160 	double getFontHeight(Font font) {
161 		LineMetrics lm = font.getLineMetrics(DUMMY_TEXT, gd.getFontRenderContext());
162 		return lm.getAscent() + lm.getDescent();
163 	}
164 
165 	double getStringWidth(String text, Font font) {
166 		return font.getStringBounds(text, 0, text.length(), gd.getFontRenderContext()).getBounds().getWidth();
167 	}
168 
169 	void setAntiAliasing(boolean enable) {
170 		gd.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
171 				enable ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF);
172 		gd.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
173 		gd.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
174 	}
175 
176 	void dispose() {
177 		gd.dispose();
178 	}
179 
180 	void saveImage(OutputStream stream, String type, float quality) throws IOException {
181 		if (type.equalsIgnoreCase("png")) {
182 			ImageIO.write(img, "png", stream);
183 		}
184 		else if (type.equalsIgnoreCase("gif")) {
185 			GifEncoder gifEncoder = new GifEncoder(img);
186 			gifEncoder.encode(stream);
187 		}
188 		else if (type.equalsIgnoreCase("jpg") || type.equalsIgnoreCase("jpeg")) {
189 			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(stream);
190 			JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(img);
191 			param.setQuality(quality, false);
192 			encoder.setJPEGEncodeParam(param);
193 			encoder.encode(img);
194 		}
195 		else {
196 			throw new IOException("Unsupported image format: " + type);
197 		}
198 		stream.flush();
199 	}
200 
201 	byte[] saveImage(String path, String type, float quality) throws IOException {
202 		byte[] bytes = getImageBytes(type, quality);
203 		RandomAccessFile f = new RandomAccessFile(path, "rw");
204 		try {
205 			f.write(bytes);
206 			return bytes;
207 		}
208 		finally {
209 			f.close();
210 		}
211 	}
212 
213 	byte[] getImageBytes(String type, float quality) throws IOException {
214 		ByteArrayOutputStream stream = new ByteArrayOutputStream();
215 		try {
216 			saveImage(stream, type, quality);
217 			return stream.toByteArray();
218 		}
219 		finally {
220 			stream.close();
221 		}
222 	}
223 
224 	public void loadImage(String imageFile) throws IOException {
225 		BufferedImage wpImage = ImageIO.read(new File(imageFile));
226 		TexturePaint paint = new TexturePaint(wpImage, new Rectangle(0, 0, wpImage.getWidth(), wpImage.getHeight()));
227 		gd.setPaint(paint);
228 		gd.fillRect(0, 0, wpImage.getWidth(), wpImage.getHeight());
229 	}
230 }