gvsig-tools / org.gvsig.tools / library / trunk / org.gvsig.tools / org.gvsig.tools.swing / org.gvsig.tools.swing.impl / src / main / java / org / gvsig / tools / swing / impl / DefaultSimpleImage.java @ 2747
History | View | Annotate | Download (15 KB)
1 |
package org.gvsig.tools.swing.impl; |
---|---|
2 |
|
3 |
import java.awt.Dimension; |
4 |
import java.awt.Graphics2D; |
5 |
import java.awt.Image; |
6 |
import java.awt.MediaTracker; |
7 |
import java.awt.RenderingHints; |
8 |
import java.awt.geom.AffineTransform; |
9 |
import java.awt.image.BufferedImage; |
10 |
import java.io.ByteArrayInputStream; |
11 |
import java.io.ByteArrayOutputStream; |
12 |
import java.io.File; |
13 |
import java.io.FileInputStream; |
14 |
import java.io.IOException; |
15 |
import java.io.InputStream; |
16 |
import java.io.OutputStream; |
17 |
import java.net.URL; |
18 |
import java.util.Iterator; |
19 |
import javax.imageio.ImageIO; |
20 |
import javax.imageio.ImageReader; |
21 |
import javax.imageio.stream.ImageInputStream; |
22 |
import javax.swing.ImageIcon; |
23 |
import org.apache.commons.codec.DecoderException; |
24 |
import org.apache.commons.codec.binary.Base64; |
25 |
import org.apache.commons.codec.binary.Hex; |
26 |
import org.apache.commons.io.IOUtils; |
27 |
import org.apache.commons.lang3.ArrayUtils; |
28 |
import org.apache.commons.lang3.NotImplementedException; |
29 |
import org.apache.commons.lang3.StringUtils; |
30 |
import org.apache.commons.lang3.mutable.MutableObject; |
31 |
import org.gvsig.tools.swing.api.SimpleImage; |
32 |
|
33 |
/**
|
34 |
*
|
35 |
* @author jjdelcerro
|
36 |
*/
|
37 |
@SuppressWarnings("UseSpecificCatch") |
38 |
public class DefaultSimpleImage implements SimpleImage { |
39 |
|
40 |
private BufferedImage image; |
41 |
private Object source; |
42 |
private Dimension dimensions; |
43 |
private String formatName; |
44 |
|
45 |
public static BufferedImage toBufferedImage(Image img) { |
46 |
if( img == null ) { |
47 |
throw new IllegalArgumentException("null image."); |
48 |
} |
49 |
if (img instanceof BufferedImage) { |
50 |
return (BufferedImage) img; |
51 |
} |
52 |
// Create a buffered image with transparency
|
53 |
BufferedImage bimage = new BufferedImage( |
54 |
img.getWidth(null),
|
55 |
img.getHeight(null),
|
56 |
BufferedImage.TYPE_INT_ARGB
|
57 |
); |
58 |
// Draw the image on to the buffered image
|
59 |
Graphics2D bGr = bimage.createGraphics();
|
60 |
bGr.drawImage(img, 0, 0, null); |
61 |
bGr.dispose(); |
62 |
return bimage;
|
63 |
} |
64 |
|
65 |
public DefaultSimpleImage() {
|
66 |
this.image = null; |
67 |
this.dimensions = null; |
68 |
this.source = null; |
69 |
this.formatName = null; |
70 |
} |
71 |
|
72 |
private DefaultSimpleImage(BufferedImage image, DefaultSimpleImage other) { |
73 |
this();
|
74 |
this.image = image;
|
75 |
this.source = other.source;
|
76 |
this.formatName = other.formatName;
|
77 |
} |
78 |
|
79 |
public DefaultSimpleImage(BufferedImage image) { |
80 |
this();
|
81 |
this.image = image;
|
82 |
this.source = image;
|
83 |
} |
84 |
|
85 |
public DefaultSimpleImage(Object source) { |
86 |
this();
|
87 |
this.source = source;
|
88 |
} |
89 |
|
90 |
public void clean() { |
91 |
this.image = null; |
92 |
this.dimensions = null; |
93 |
this.source = null; |
94 |
this.formatName = null; |
95 |
} |
96 |
|
97 |
@Override
|
98 |
public BufferedImage getBufferedImage() { |
99 |
if( this.image == null ) { |
100 |
if( this.source!=null ) { |
101 |
Dimension dim = new Dimension(); |
102 |
MutableObject<String> theFormatName = new MutableObject<>(null); |
103 |
this.image = this.load(source, dim, theFormatName); |
104 |
this.dimensions = dim;
|
105 |
this.formatName = theFormatName.getValue();
|
106 |
} |
107 |
} |
108 |
return this.image; |
109 |
} |
110 |
|
111 |
public BufferedImage getBufferedImage(int page) { |
112 |
if(page == 0){ |
113 |
return getBufferedImage();
|
114 |
} |
115 |
throw new NotImplementedException("Can't support multipage images"); |
116 |
} |
117 |
|
118 |
public int getCountPages() { |
119 |
return 1; |
120 |
} |
121 |
|
122 |
@Override
|
123 |
public String getFormatName() { |
124 |
return this.formatName; |
125 |
} |
126 |
|
127 |
@Override
|
128 |
public boolean isEmpty() { |
129 |
return this.image == null && this.source==null ; |
130 |
} |
131 |
|
132 |
@Override
|
133 |
public void set(BufferedImage image) { |
134 |
this.image = image;
|
135 |
this.source = image;
|
136 |
} |
137 |
|
138 |
@Override
|
139 |
public void set(Object source) { |
140 |
this.image = null; |
141 |
this.source = source;
|
142 |
} |
143 |
|
144 |
private BufferedImage load(Object source, Dimension dimensions, MutableObject<String> formatName) { |
145 |
BufferedImage theImage = null; |
146 |
if( formatName!=null ) { |
147 |
formatName.setValue(null);
|
148 |
} |
149 |
try {
|
150 |
if (source instanceof BufferedImage) { |
151 |
theImage = (BufferedImage) source;
|
152 |
|
153 |
} else if (source instanceof ImageIcon ) { |
154 |
ImageIcon icon = (ImageIcon)source; |
155 |
int loadStatus = icon.getImageLoadStatus();
|
156 |
if( loadStatus != MediaTracker.COMPLETE ) { |
157 |
icon.getDescription(); |
158 |
} |
159 |
theImage = toBufferedImage(icon.getImage()); |
160 |
|
161 |
} else if (source instanceof Image) { |
162 |
theImage = toBufferedImage((Image) source);
|
163 |
|
164 |
} else if (source instanceof byte[]) { |
165 |
ByteArrayInputStream is = new ByteArrayInputStream((byte[]) source); |
166 |
theImage = ImageIO.read(is);
|
167 |
if( formatName!=null ) { |
168 |
formatName.setValue(this.getFormatName(source));
|
169 |
} |
170 |
|
171 |
} else if (source instanceof File) { |
172 |
theImage = ImageIO.read((File) source); |
173 |
if( formatName!=null ) { |
174 |
formatName.setValue(this.getFormatName(source));
|
175 |
} |
176 |
|
177 |
} else if (source instanceof URL) { |
178 |
theImage = ImageIO.read((URL) source); |
179 |
if( formatName!=null ) { |
180 |
formatName.setValue(this.getFormatName(source));
|
181 |
} |
182 |
|
183 |
} else if (source instanceof String) { |
184 |
InputStream is;
|
185 |
String s = (String) source; |
186 |
File f = new File(s); |
187 |
byte[] data = null; |
188 |
if (f.exists()) {
|
189 |
is = new FileInputStream(f); |
190 |
} else {
|
191 |
try {
|
192 |
URL url = new URL(s); |
193 |
is = url.openStream(); |
194 |
is.available(); // Force exception if is null
|
195 |
} catch (Exception ex) { |
196 |
try {
|
197 |
data = Hex.decodeHex(s.toCharArray()); |
198 |
is = new ByteArrayInputStream(data); |
199 |
} catch (DecoderException ex2) {
|
200 |
try {
|
201 |
data = Base64.decodeBase64(s); |
202 |
is = new ByteArrayInputStream(data); |
203 |
} catch (Exception ex3) { |
204 |
return null; |
205 |
} |
206 |
} |
207 |
} |
208 |
} |
209 |
theImage = ImageIO.read(is);
|
210 |
IOUtils.closeQuietly(is); |
211 |
if( formatName!=null && data!=null ) { |
212 |
formatName.setValue(this.getFormatName(data));
|
213 |
} |
214 |
} |
215 |
} catch (IOException ex) { |
216 |
return null; |
217 |
} |
218 |
if( theImage!=null && dimensions!=null ) { |
219 |
dimensions.width = theImage.getWidth(); |
220 |
dimensions.height = theImage.getHeight(); |
221 |
} |
222 |
return theImage;
|
223 |
} |
224 |
|
225 |
private String getFormatName(Object source) { |
226 |
try {
|
227 |
ImageInputStream in = ImageIO.createImageInputStream(source); |
228 |
if (in==null) { |
229 |
return null; |
230 |
} |
231 |
Iterator<ImageReader> readers = ImageIO.getImageReaders(in); |
232 |
if (readers!=null && readers.hasNext()) { |
233 |
ImageReader reader = readers.next();
|
234 |
try {
|
235 |
reader.setInput(in); |
236 |
return reader.getFormatName();
|
237 |
} finally {
|
238 |
reader.dispose(); |
239 |
} |
240 |
} |
241 |
return null; |
242 |
} catch (Exception ex) { |
243 |
throw new RuntimeException("Can't determine format name of the image.", ex); |
244 |
} |
245 |
} |
246 |
|
247 |
private Dimension loadDimensions(Object source) { |
248 |
try {
|
249 |
ImageInputStream in = ImageIO.createImageInputStream(source); |
250 |
Iterator<ImageReader> readers = ImageIO.getImageReaders(in); |
251 |
if (readers!=null && readers.hasNext()) { |
252 |
ImageReader reader = readers.next();
|
253 |
try {
|
254 |
reader.setInput(in); |
255 |
return new Dimension(reader.getWidth(0), reader.getHeight(0)); |
256 |
} finally {
|
257 |
reader.dispose(); |
258 |
} |
259 |
} |
260 |
Dimension dim = new Dimension(); |
261 |
this.image = this.load(source, dim, null); |
262 |
return dim;
|
263 |
} catch (IOException ex) { |
264 |
throw new RuntimeException("Can't load dimensions of the image.", ex); |
265 |
} |
266 |
} |
267 |
|
268 |
@Override
|
269 |
public int getWidth() { |
270 |
if( this.dimensions == null ) { |
271 |
this.dimensions = this.loadDimensions(source); |
272 |
} |
273 |
return this.dimensions.width; |
274 |
} |
275 |
|
276 |
@Override
|
277 |
public int getHeight() { |
278 |
if( this.dimensions == null ) { |
279 |
this.dimensions = this.loadDimensions(source); |
280 |
} |
281 |
return this.dimensions.height; |
282 |
} |
283 |
|
284 |
@Override
|
285 |
public DefaultSimpleImage resize(double factor) { |
286 |
BufferedImage theImage = this.getBufferedImage(); |
287 |
int w = theImage.getWidth();
|
288 |
int h = theImage.getHeight();
|
289 |
int width = (int) (w * factor); |
290 |
int height = (int) (h * factor); |
291 |
BufferedImage newImage = new BufferedImage(width, height, theImage.getType()); |
292 |
Graphics2D g = newImage.createGraphics();
|
293 |
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); |
294 |
g.drawImage(theImage, 0, 0, width, height, 0, 0, w, h, null); |
295 |
g.dispose(); |
296 |
return new DefaultSimpleImage(newImage, this); |
297 |
} |
298 |
|
299 |
@Override
|
300 |
public DefaultSimpleImage resize(int width, int height) { |
301 |
BufferedImage theImage = this.getBufferedImage(); |
302 |
int w = theImage.getWidth();
|
303 |
int h = theImage.getHeight();
|
304 |
BufferedImage newImage = new BufferedImage(width, height, theImage.getType()); |
305 |
Graphics2D g = newImage.createGraphics();
|
306 |
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); |
307 |
g.drawImage(theImage, 0, 0, width, height, 0, 0, w, h, null); |
308 |
g.dispose(); |
309 |
return new DefaultSimpleImage(newImage, this); |
310 |
} |
311 |
|
312 |
@Override
|
313 |
public DefaultSimpleImage rotate(int angle) { |
314 |
BufferedImage theImage = this.getBufferedImage(); |
315 |
int w = theImage.getWidth();
|
316 |
int h = theImage.getHeight();
|
317 |
BufferedImage newImage = new BufferedImage(w, h, theImage.getType()); |
318 |
Graphics2D g = newImage.createGraphics();
|
319 |
g.rotate(Math.toRadians(angle), w / 2, h / 2); |
320 |
g.drawImage(theImage, null, 0, 0); |
321 |
g.dispose(); |
322 |
return new DefaultSimpleImage(newImage, this); |
323 |
} |
324 |
|
325 |
@Override
|
326 |
public DefaultSimpleImage horizontalflip() {
|
327 |
BufferedImage img = this.getBufferedImage(); |
328 |
int w = img.getWidth();
|
329 |
int h = img.getHeight();
|
330 |
BufferedImage newImage = new BufferedImage(w, h, img.getType()); |
331 |
Graphics2D g = newImage.createGraphics();
|
332 |
g.drawImage(img, 0, 0, w, h, w, 0, 0, h, null); |
333 |
g.dispose(); |
334 |
return new DefaultSimpleImage(newImage, this); |
335 |
} |
336 |
|
337 |
@Override
|
338 |
public DefaultSimpleImage verticalflip() {
|
339 |
BufferedImage img = this.getBufferedImage(); |
340 |
int w = img.getWidth();
|
341 |
int h = img.getHeight();
|
342 |
BufferedImage newImage = new BufferedImage(w, h, img.getColorModel().getTransparency()); |
343 |
Graphics2D g = newImage.createGraphics();
|
344 |
g.drawImage(img, 0, 0, w, h, 0, h, w, 0, null); |
345 |
g.dispose(); |
346 |
return new DefaultSimpleImage(newImage, this); |
347 |
} |
348 |
|
349 |
@Override
|
350 |
public DefaultSimpleImage transform(AffineTransform transform, int width, int height) { |
351 |
BufferedImage img = this.getBufferedImage(); |
352 |
BufferedImage newImage = new BufferedImage(width, height, img.getColorModel().getTransparency()); |
353 |
Graphics2D g = newImage.createGraphics();
|
354 |
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); |
355 |
g.setTransform(transform); |
356 |
g.drawImage(img, 0, 0, null); |
357 |
g.dispose(); |
358 |
return new DefaultSimpleImage(newImage, this); |
359 |
} |
360 |
|
361 |
@Override
|
362 |
public DefaultSimpleImage transform(AffineTransform transform) { |
363 |
BufferedImage img = this.getBufferedImage(); |
364 |
int w = img.getWidth();
|
365 |
int h = img.getHeight();
|
366 |
BufferedImage newImage = new BufferedImage(w, h, img.getColorModel().getTransparency()); |
367 |
Graphics2D g = newImage.createGraphics();
|
368 |
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); |
369 |
g.setTransform(transform); |
370 |
g.drawImage(img, 0, 0, null); |
371 |
g.dispose(); |
372 |
return new DefaultSimpleImage(newImage, this); |
373 |
} |
374 |
|
375 |
private String bytearray_hex(byte[] data) { |
376 |
StringBuilder builder = new StringBuilder(); |
377 |
for (byte abyte : data) { |
378 |
int v = abyte & 0xff; |
379 |
builder.append(String.format("%02x", v)); |
380 |
} |
381 |
return builder.toString();
|
382 |
} |
383 |
|
384 |
@Override
|
385 |
public byte[] toBytearray() { |
386 |
return toBytearray(null); |
387 |
} |
388 |
|
389 |
@Override
|
390 |
public byte[] toBytearray(String format) { |
391 |
try {
|
392 |
if( this.getBufferedImage()==null ) { |
393 |
return null; |
394 |
} |
395 |
if( StringUtils.isBlank(format) ) {
|
396 |
format = this.formatName==null?"png":this.formatName; |
397 |
} |
398 |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
399 |
ImageIO.write( this.getBufferedImage(), format, baos ); |
400 |
baos.flush(); |
401 |
byte[] imageInByte = baos.toByteArray(); |
402 |
baos.close(); |
403 |
return imageInByte;
|
404 |
} catch (IOException ex) { |
405 |
return null; |
406 |
} |
407 |
} |
408 |
|
409 |
@Override
|
410 |
public String toString() { |
411 |
byte[] data = this.toBytearray(); |
412 |
return bytearray_hex(data);
|
413 |
} |
414 |
|
415 |
@Override
|
416 |
public String toString(String format) { |
417 |
byte[] data = this.toBytearray(format); |
418 |
return bytearray_hex(data);
|
419 |
} |
420 |
|
421 |
@Override
|
422 |
public void save(File output, String formatName) throws IOException { |
423 |
if( StringUtils.isBlank(formatName) ) {
|
424 |
formatName = this.formatName==null?"png":this.formatName; |
425 |
} |
426 |
ImageIO.write(this.getBufferedImage(), formatName, output); |
427 |
} |
428 |
|
429 |
@Override
|
430 |
public void save(OutputStream output, String formatName) throws IOException { |
431 |
if( StringUtils.isBlank(formatName) ) {
|
432 |
formatName = this.formatName==null?"png":this.formatName; |
433 |
} |
434 |
ImageIO.write(this.getBufferedImage(), formatName, output); |
435 |
} |
436 |
|
437 |
@Override
|
438 |
public boolean equals(Object obj) { |
439 |
if( !(obj instanceof SimpleImage) ) { |
440 |
return false; |
441 |
} |
442 |
SimpleImage other = (SimpleImage) obj; |
443 |
return this.hashCode() == other.hashCode(); |
444 |
} |
445 |
|
446 |
@Override
|
447 |
public int hashCode() { |
448 |
if( this.isEmpty() ) { |
449 |
return 0; |
450 |
} |
451 |
byte[] bytes = this.toBytearray(); |
452 |
int hash = ArrayUtils.hashCode(bytes);
|
453 |
return hash;
|
454 |
} |
455 |
|
456 |
} |