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