Statistics
| Revision:

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
}