Rev 1074 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
936 | dev | 1 | package ak.photoalbum.images.jiu; |
2 | |||
3 | import java.awt.Image; |
||
4 | import java.awt.image.BufferedImage; |
||
5 | import java.awt.image.PixelGrabber; |
||
6 | import java.awt.image.ImageObserver; |
||
7 | |||
8 | import org.apache.log4j.Logger; |
||
9 | |||
10 | import ak.photoalbum.images.ImageResizer; |
||
11 | |||
12 | import net.sourceforge.jiu.data.BilevelImage; |
||
13 | import net.sourceforge.jiu.data.Gray8Image; |
||
14 | import net.sourceforge.jiu.data.MemoryRGB24Image; |
||
15 | import net.sourceforge.jiu.data.Paletted8Image; |
||
16 | import net.sourceforge.jiu.data.PixelImage; |
||
17 | import net.sourceforge.jiu.data.RGB24Image; |
||
18 | import net.sourceforge.jiu.data.RGBIndex; |
||
19 | import net.sourceforge.jiu.geometry.Resample; |
||
20 | |||
21 | public class JiuResizer |
||
22 | implements ImageResizer |
||
23 | { |
||
24 | protected static final int DEFAULT_ALPHA = 0xff000000; |
||
1074 | dev | 25 | protected static final int FILTER_TYPE = Resample.FILTER_TYPE_HERMITE; |
936 | dev | 26 | /* |
27 | Possible type small, ms medium, ms quality |
||
28 | ----------------------------------------------------------- |
||
29 | FILTER_TYPE_BOX 2.4 3.5 very bad |
||
30 | FILTER_TYPE_TRIANGLE 2.9 5.2 |
||
31 | FILTER_TYPE_B_SPLINE 3.6 7.2 |
||
32 | FILTER_TYPE_BELL 3.5 6.1 |
||
33 | FILTER_TYPE_HERMITE 2.9 5.3 |
||
34 | FILTER_TYPE_LANCZOS3 4.7 9.7 the best |
||
35 | FILTER_TYPE_MITCHELL 3.6 7.1 |
||
36 | */ |
||
37 | |||
1274 | dev | 38 | private static final Logger logger = Logger.getLogger(JiuResizer.class); |
936 | dev | 39 | |
40 | public JiuResizer() |
||
41 | { |
||
42 | } |
||
43 | |||
44 | public BufferedImage resize(Image origin, int newWidth, int newHeight) |
||
45 | { |
||
1074 | dev | 46 | long timeStart = System.currentTimeMillis(); |
47 | |||
936 | dev | 48 | try { |
49 | RGB24Image image = convertImageToRGB24Image(origin); |
||
50 | Resample resample; |
||
51 | |||
52 | if(image == null) return null; |
||
53 | if(image.getWidth() == newWidth && image.getHeight() == newHeight) |
||
54 | return convertToAwtImage(image, DEFAULT_ALPHA); |
||
55 | |||
56 | resample = new Resample(); |
||
57 | resample.setInputImage(image); |
||
58 | resample.setSize(newWidth, newHeight); |
||
59 | resample.setFilter(FILTER_TYPE); |
||
60 | resample.process(); |
||
61 | |||
62 | return convertToAwtImage(resample.getOutputImage(), DEFAULT_ALPHA); |
||
63 | } |
||
64 | catch(Exception ex) { |
||
1274 | dev | 65 | logger.warn("Cannot resize image", ex); |
936 | dev | 66 | |
67 | throw new RuntimeException(ex.getMessage()); |
||
68 | } |
||
1074 | dev | 69 | finally { |
70 | if(logger.isDebugEnabled()) { |
||
71 | logger.debug("resized in " + (System.currentTimeMillis() - timeStart) + " ms"); |
||
72 | } |
||
73 | } |
||
936 | dev | 74 | } |
75 | |||
76 | protected static BufferedImage convertToAwtImage(PixelImage image, int alpha) |
||
77 | { |
||
78 | if (image == null) |
||
79 | { |
||
80 | return null; |
||
81 | } |
||
82 | if (image instanceof RGB24Image) |
||
83 | { |
||
84 | return convertToAwtImage((RGB24Image)image, alpha); |
||
85 | } |
||
86 | else |
||
87 | if (image instanceof Gray8Image) |
||
88 | { |
||
89 | return null; //convertToAwtImage((Gray8Image)image, alpha); |
||
90 | } |
||
91 | else |
||
92 | if (image instanceof Paletted8Image) |
||
93 | { |
||
94 | return null; //convertToAwtImage((Paletted8Image)image, alpha); |
||
95 | } |
||
96 | else |
||
97 | if (image instanceof BilevelImage) |
||
98 | { |
||
99 | return null; //convertToAwtImage((BilevelImage)image, alpha); |
||
100 | } |
||
101 | else |
||
102 | { |
||
103 | return null; |
||
104 | } |
||
105 | } |
||
106 | |||
107 | protected static BufferedImage convertToAwtImage(RGB24Image image, int alpha) |
||
108 | { |
||
109 | if (image == null) |
||
110 | { |
||
111 | return null; |
||
112 | } |
||
113 | |||
114 | int width = image.getWidth(); |
||
115 | int height = image.getHeight(); |
||
116 | if (width < 1 || height < 1) |
||
117 | { |
||
118 | return null; |
||
119 | } |
||
120 | |||
121 | int[] pixels = new int[width]; |
||
122 | byte[] red = new byte[width]; |
||
123 | byte[] green = new byte[width]; |
||
124 | byte[] blue = new byte[width]; |
||
125 | |||
126 | BufferedImage newImage = new BufferedImage(width, height, |
||
127 | BufferedImage.TYPE_INT_RGB); |
||
128 | |||
129 | for (int y = 0; y < height; y++) |
||
130 | { |
||
131 | image.getByteSamples(RGBIndex.INDEX_RED, 0, y, width, 1, red, 0); |
||
132 | image.getByteSamples(RGBIndex.INDEX_GREEN, 0, y, width, 1, green, 0); |
||
133 | image.getByteSamples(RGBIndex.INDEX_BLUE, 0, y, width, 1, blue, 0); |
||
134 | convertFromRGB24(red, 0, green, 0, blue, 0, alpha, pixels, 0, width); |
||
135 | |||
136 | for(int x = 0; x < width; x++) |
||
137 | newImage.setRGB(x, y, pixels[x]); |
||
138 | } |
||
139 | |||
140 | return newImage; |
||
141 | } |
||
142 | |||
143 | protected static void convertFromRGB24( |
||
144 | byte[] srcRed, int srcRedOffset, |
||
145 | byte[] srcGreen, int srcGreenOffset, |
||
146 | byte[] srcBlue, int srcBlueOffset, |
||
147 | int alpha, |
||
148 | int[] dest, int destOffset, |
||
149 | int num) |
||
150 | { |
||
151 | while (num-- > 0) |
||
152 | { |
||
153 | dest[destOffset++] = |
||
154 | alpha | |
||
155 | (srcBlue[srcBlueOffset++] & 0xff) | |
||
156 | ((srcGreen[srcGreenOffset++] & 0xff) << 8) | |
||
157 | ((srcRed[srcRedOffset++] & 0xff) << 16); |
||
158 | } |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * Creates an {@link RGB24Image} from the argument AWT image instance. |
||
163 | * @param image AWT image object to be converted to a {@link RGB24Image} |
||
164 | * @return a {@link RGB24Image} object holding the |
||
165 | * image data from the argument image |
||
166 | */ |
||
167 | protected static RGB24Image convertImageToRGB24Image(Image image) |
||
168 | { |
||
169 | if (image == null) |
||
170 | { |
||
171 | return null; |
||
172 | } |
||
173 | int width = image.getWidth(null); |
||
174 | int height = image.getHeight(null); |
||
175 | if (width < 1 || height < 1) |
||
176 | { |
||
177 | return null; |
||
178 | } |
||
179 | int[] pixels = new int[width * height]; |
||
180 | PixelGrabber pg = new PixelGrabber( |
||
181 | image, 0, 0, width, height, pixels, 0, width); |
||
182 | |||
183 | try |
||
184 | { |
||
185 | pg.grabPixels(); |
||
186 | } |
||
187 | catch (InterruptedException e) |
||
188 | { |
||
189 | return null; |
||
190 | } |
||
191 | if ((pg.getStatus() & ImageObserver.ABORT) != 0) |
||
192 | { |
||
193 | //System.err.println("image fetch aborted or errored"); |
||
194 | return null; |
||
195 | } |
||
196 | RGB24Image result = new MemoryRGB24Image(width, height); |
||
197 | int offset = 0; |
||
198 | for (int y = 0; y < height; y++) |
||
199 | { |
||
200 | for (int x = 0; x < width; x++) |
||
201 | { |
||
202 | int pixel = pixels[offset++] & 0xffffff; |
||
203 | result.putSample(RGBIndex.INDEX_RED, x, y, pixel >> 16); |
||
204 | result.putSample(RGBIndex.INDEX_GREEN, x, y, (pixel >> 8) & 0xff); |
||
205 | result.putSample(RGBIndex.INDEX_BLUE, x, y, pixel & 0xff); |
||
206 | } |
||
207 | } |
||
208 | return result; |
||
209 | } |
||
210 | } |