]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/gui/ImageUtils.java
Version 19, May 2018
[GpsPrune.git] / tim / prune / gui / ImageUtils.java
1 package tim.prune.gui;
2
3 import java.awt.Dimension;
4 import java.awt.Graphics;
5 import java.awt.Graphics2D;
6 import java.awt.Image;
7 import java.awt.image.BufferedImage;
8 import java.awt.image.ConvolveOp;
9 import java.awt.image.Kernel;
10
11 import javax.swing.ImageIcon;
12
13 /**
14  * Class for providing generic image processing functions
15  */
16 public abstract class ImageUtils
17 {
18         private static final float SMOOTH_FACTOR = 0.008f;
19         private static ConvolveOp CONVOLVER = null;
20
21         /** Static block for initialization */
22         static
23         {
24                 float[] smoothMatrix = {
25                         0, SMOOTH_FACTOR, 0,
26                         SMOOTH_FACTOR, 1-(SMOOTH_FACTOR*4), SMOOTH_FACTOR,
27                         0, SMOOTH_FACTOR, 0
28                 };
29                 CONVOLVER = new ConvolveOp(new Kernel(3, 3, smoothMatrix));
30         }
31
32
33         /**
34          * Create a scaled and smoothed image according to the specified size
35          * @param inImage image to scale
36          * @param inWidth width to scale to
37          * @param inHeight height to scale to
38          * @return BufferedImage containing scaled result
39          */
40         public static BufferedImage createScaledImage(Image inImage, int inWidth, int inHeight)
41         {
42                 if (inWidth <= 0 || inHeight <= 0) {
43                         return null;
44                 }
45                 // create smaller image and force its loading
46                 Image smallerImage = inImage.getScaledInstance(inWidth, inHeight, Image.SCALE_SMOOTH);
47                 Image tempImage = new ImageIcon(smallerImage).getImage();
48                 tempImage.getWidth(null);
49
50                 // create buffered image to do transform
51                 BufferedImage buffer = new BufferedImage(inWidth, inHeight, BufferedImage.TYPE_INT_RGB);
52                 // copy scaled picture into buffer
53                 Graphics buffG = buffer.getGraphics();
54                 buffG.drawImage(smallerImage, 0, 0, inWidth, inHeight, null);
55                 buffG.dispose();
56
57                 // clear variables
58                 smallerImage = null; tempImage = null;
59                 // smooth scaled image using a normalized 3x3 matrix - taking next neighbour
60                 buffer = CONVOLVER.filter(buffer, null);
61
62                 return buffer;
63         }
64
65
66         /**
67          * Work out the max size of a thumbnail
68          * @param inOrigWidth width of original picture
69          * @param inOrigHeight height of original picture
70          * @param inMaxWidth max width of thumbnail
71          * @param inMaxHeight max height of thumbnail
72          * @return size of thumbnail as Dimension
73          */
74         public static Dimension getThumbnailSize(int inOrigWidth, int inOrigHeight, int inMaxWidth, int inMaxHeight)
75         {
76                 if (inMaxWidth <= 0 || inMaxHeight <= 0) {return new Dimension(1, 1);}
77                 // work out maximum zoom ratio available so that thumbnail isn't too big
78                 double xZoom = inMaxWidth * 1.0 / inOrigWidth;
79                 double yZoom = inMaxHeight * 1.0 / inOrigHeight;
80                 double zoom = (xZoom > yZoom?yZoom:xZoom);
81                 // Don't make thumbnail bigger than picture
82                 if (zoom > 1.0) {return new Dimension(inOrigWidth, inOrigHeight);}
83
84                 // calculate new width and height
85                 final int xSize = (int) (zoom * inOrigWidth);
86                 final int ySize = (int) (zoom * inOrigHeight);
87                 if (xSize <= 0 || ySize <= 0) {return new Dimension(1, 1);}
88                 return new Dimension (xSize, ySize);
89         }
90
91
92         /**
93          * Create a new image by rotating and scaling the given one
94          * @param inImage input image
95          * @param inMaxWidth maximum width of output image
96          * @param inMaxHeight maximum height of output image
97          * @param inRotationDegrees number of degrees to rotate clockwise (0, 90, 180 or 270)
98          * @return rotated, scaled image
99          */
100         public static BufferedImage rotateImage(Image inImage, int inMaxWidth, int inMaxHeight, int inRotationDegrees)
101         {
102                 // Create scaled image of suitable size
103                 boolean isRotated = (inRotationDegrees % 180 != 0);
104                 int origWidth = inImage.getWidth(null);
105                 int origHeight = inImage.getHeight(null);
106                 int thumbWidth = isRotated?origHeight:origWidth;
107                 int thumbHeight = isRotated?origWidth:origHeight;
108                 Dimension scaledSize = getThumbnailSize(thumbWidth, thumbHeight, inMaxWidth, inMaxHeight);
109                 BufferedImage result = new BufferedImage(scaledSize.width, scaledSize.height, BufferedImage.TYPE_INT_RGB);
110                 // Do different things according to rotation angle (a bit messy, sorry!)
111                 if (inRotationDegrees == 0)
112                 {
113                         // Not rotated, so just copy image directly
114                         result.getGraphics().drawImage(inImage, 0, 0, scaledSize.width, scaledSize.height, null);
115                 }
116                 else
117                 {
118                         // Need to use Graphics2D for rotation, not Graphics
119                         Graphics2D g2d = result.createGraphics();
120                         switch (inRotationDegrees)
121                         {
122                                 case 90:
123                                         g2d.rotate(Math.PI / 2, 0.0, 0.0);
124                                         g2d.drawImage(inImage, 0, -scaledSize.width, scaledSize.height, scaledSize.width, null);
125                                         break;
126                                 case 180:
127                                         g2d.rotate(Math.PI, scaledSize.width/2.0, scaledSize.height/2.0);
128                                         g2d.drawImage(inImage, 0, 0, scaledSize.width, scaledSize.height, null);
129                                         break;
130                                 case 270:
131                                         g2d.rotate(Math.PI * 3/2, 0.0, 0.0);
132                                         g2d.drawImage(inImage, -scaledSize.height, 0, scaledSize.height, scaledSize.width, null);
133                         }
134                         // Clear up memory
135                         g2d.dispose();
136                 }
137                 return result;
138         }
139 }