Mercurial > hg > digilib-old
annotate servlet/src/digilib/image/ImageLoaderDocuImage.java @ 87:5d44cd2481a5
New version 1.8b4.
Utils without static debuglevel.
author | robcast |
---|---|
date | Mon, 17 Mar 2003 15:23:17 +0100 |
parents | 997ba69afb81 |
children | 6d35c945a5d6 |
rev | line source |
---|---|
1 | 1 /* ImageLoaderDocuImage -- Image class implementation using JDK 1.4 ImageLoader |
2 | |
3 Digital Image Library servlet components | |
4 | |
85 | 5 Copyright (C) 2002, 2003 Robert Casties (robcast@mail.berlios.de) |
1 | 6 |
7 This program is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2 of the License, or (at your | |
10 option) any later version. | |
11 | |
12 Please read license.txt for the full details. A copy of the GPL | |
13 may be found at http://www.gnu.org/copyleft/lgpl.html | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with this program; if not, write to the Free Software | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 */ | |
20 | |
21 package digilib.image; | |
22 | |
86 | 23 import java.awt.Dimension; |
85 | 24 import java.awt.Rectangle; |
73 | 25 import java.awt.geom.AffineTransform; |
26 import java.awt.image.AffineTransformOp; | |
27 import java.awt.image.BufferedImage; | |
85 | 28 import java.awt.image.RescaleOp; |
73 | 29 import java.io.File; |
30 import java.io.IOException; | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
31 import java.io.OutputStream; |
85 | 32 import java.util.Iterator; |
1 | 33 |
73 | 34 import javax.imageio.ImageIO; |
85 | 35 import javax.imageio.ImageReadParam; |
36 import javax.imageio.ImageReader; | |
37 import javax.imageio.stream.ImageInputStream; | |
1 | 38 |
86 | 39 import digilib.io.DocuFile; |
73 | 40 import digilib.io.FileOpException; |
86 | 41 import digilib.io.FileOps; |
1 | 42 |
73 | 43 /** Implementation of DocuImage using the ImageLoader API of Java 1.4 and Java2D. */ |
1 | 44 public class ImageLoaderDocuImage extends DocuImageImpl { |
45 | |
86 | 46 /** image object */ |
47 protected BufferedImage img; | |
48 /** interpolation type */ | |
49 protected int interpol; | |
50 /** ImageIO image reader */ | |
51 protected ImageReader reader; | |
52 /** File that was read */ | |
53 protected File imgFile; | |
85 | 54 |
55 /* loadSubimage is supported. */ | |
56 public boolean isSubimageSupported() { | |
57 return true; | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
58 } |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
59 |
85 | 60 public void setQuality(int qual) { |
61 quality = qual; | |
62 // setup interpolation quality | |
63 if (qual > 0) { | |
64 util.dprintln(4, "quality q1"); | |
65 interpol = AffineTransformOp.TYPE_BILINEAR; | |
66 } else { | |
67 util.dprintln(4, "quality q0"); | |
68 interpol = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; | |
69 } | |
70 } | |
86 | 71 |
85 | 72 public int getHeight() { |
73 int h = 0; | |
74 try { | |
75 if (img == null) { | |
76 h = reader.getHeight(0); | |
77 } else { | |
78 h = img.getHeight(); | |
79 } | |
80 } catch (IOException e) { | |
81 e.printStackTrace(); | |
82 } | |
83 return h; | |
84 } | |
85 | |
86 public int getWidth() { | |
87 int w = 0; | |
88 try { | |
89 if (img == null) { | |
90 w = reader.getWidth(0); | |
91 } else { | |
92 w = img.getWidth(); | |
93 } | |
94 } catch (IOException e) { | |
95 e.printStackTrace(); | |
96 } | |
97 return w; | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
98 } |
1 | 99 |
86 | 100 /* load image file */ |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
101 public void loadImage(File f) throws FileOpException { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
102 util.dprintln(10, "loadImage!"); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
103 System.gc(); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
104 try { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
105 img = ImageIO.read(f); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
106 if (img == null) { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
107 util.dprintln(3, "ERROR(loadImage): unable to load file"); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
108 throw new FileOpException("Unable to load File!"); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
109 } |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
110 } catch (IOException e) { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
111 throw new FileOpException("Error reading image."); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
112 } |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
113 } |
1 | 114 |
86 | 115 /** Get an ImageReader for the image file. |
116 * | |
117 */ | |
85 | 118 public void preloadImage(File f) throws FileOpException { |
119 System.gc(); | |
120 try { | |
121 ImageInputStream istream = ImageIO.createImageInputStream(f); | |
122 Iterator readers = ImageIO.getImageReaders(istream); | |
123 reader = (ImageReader) readers.next(); | |
124 reader.setInput(istream); | |
125 } catch (IOException e) { | |
126 util.dprintln(3, "ERROR(loadImage): unable to load file"); | |
127 throw new FileOpException("Unable to load File!" + e); | |
128 } | |
129 if (reader == null) { | |
130 util.dprintln(3, "ERROR(loadImage): unable to load file"); | |
131 throw new FileOpException("Unable to load File!"); | |
132 } | |
86 | 133 imgFile = f; |
85 | 134 } |
135 | |
136 /* Load an image file into the Object. */ | |
137 public void loadSubimage(File f, Rectangle region, int prescale) | |
138 throws FileOpException { | |
139 System.gc(); | |
140 try { | |
86 | 141 if ((reader == null) || (imgFile != f)) { |
85 | 142 preloadImage(f); |
143 } | |
144 // set up reader parameters | |
145 ImageReadParam readParam = reader.getDefaultReadParam(); | |
146 readParam.setSourceRegion(region); | |
147 readParam.setSourceSubsampling(prescale, prescale, 0, 0); | |
148 // read image | |
149 img = reader.read(0, readParam); | |
150 } catch (IOException e) { | |
151 util.dprintln(3, "ERROR(loadImage): unable to load file"); | |
152 throw new FileOpException("Unable to load File!"); | |
153 } | |
154 if (img == null) { | |
155 util.dprintln(3, "ERROR(loadImage): unable to load file"); | |
156 throw new FileOpException("Unable to load File!"); | |
157 } | |
158 } | |
159 | |
86 | 160 /* write image of type mt to Stream */ |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
161 public void writeImage(String mt, OutputStream ostream) |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
162 throws FileOpException { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
163 util.dprintln(10, "writeImage!"); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
164 try { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
165 // setup output |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
166 String type = "png"; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
167 if (mt == "image/jpeg") { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
168 type = "jpeg"; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
169 } else if (mt == "image/png") { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
170 type = "png"; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
171 } else { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
172 // unknown mime type |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
173 util.dprintln(2, "ERROR(writeImage): Unknown mime type " + mt); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
174 throw new FileOpException("Unknown mime type: " + mt); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
175 } |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
176 // render output |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
177 if (ImageIO.write(img, type, ostream)) { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
178 // writing was OK |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
179 return; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
180 } else { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
181 throw new FileOpException("Error writing image: Unknown image format!"); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
182 } |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
183 } catch (IOException e) { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
184 // e.printStackTrace(); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
185 throw new FileOpException("Error writing image."); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
186 } |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
187 } |
1 | 188 |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
189 public void scale(double scale) throws ImageOpException { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
190 // setup scale |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
191 AffineTransformOp scaleOp = |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
192 new AffineTransformOp( |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
193 AffineTransform.getScaleInstance(scale, scale), |
85 | 194 interpol); |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
195 BufferedImage scaledImg = scaleOp.filter(img, null); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
196 |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
197 if (scaledImg == null) { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
198 util.dprintln(2, "ERROR(cropAndScale): error in scale"); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
199 throw new ImageOpException("Unable to scale"); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
200 } |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
201 img = scaledImg; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
202 } |
1 | 203 |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
204 public void crop(int x_off, int y_off, int width, int height) |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
205 throws ImageOpException { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
206 // setup Crop |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
207 BufferedImage croppedImg = img.getSubimage(x_off, y_off, width, height); |
1 | 208 |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
209 util.dprintln( |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
210 3, |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
211 "CROP:" + croppedImg.getWidth() + "x" + croppedImg.getHeight()); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
212 //DEBUG |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
213 // util.dprintln(2, " time "+(System.currentTimeMillis()-startTime)+"ms"); |
1 | 214 |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
215 if (croppedImg == null) { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
216 util.dprintln(2, "ERROR(cropAndScale): error in crop"); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
217 throw new ImageOpException("Unable to crop"); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
218 } |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
219 img = croppedImg; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
220 } |
1 | 221 |
86 | 222 public void enhance(float mult, float add) throws ImageOpException { |
223 /* Only one constant should work regardless of the number of bands | |
224 * according to the JDK spec. | |
225 * Doesn't work on JDK 1.4 for OSX and Linux (at least). | |
85 | 226 */ |
86 | 227 /* RescaleOp scaleOp = |
228 new RescaleOp( | |
229 (float)mult, (float)add, | |
230 null); | |
231 scaleOp.filter(img, img); | |
232 */ | |
233 /* The number of constants must match the number of bands in the image. | |
234 */ | |
235 int ncol = img.getColorModel().getNumColorComponents(); | |
236 float[] dm = new float[ncol]; | |
237 float[] da = new float[ncol]; | |
238 for (int i = 0; i < ncol; i++) { | |
239 dm[i] = (float) mult; | |
240 da[i] = (float) add; | |
85 | 241 } |
86 | 242 RescaleOp scaleOp = new RescaleOp(dm, da, null); |
85 | 243 scaleOp.filter(img, img); |
244 | |
245 } | |
246 | |
86 | 247 public void enhanceRGB(float[] rgbm, float[] rgba) |
248 throws ImageOpException { | |
249 /* The number of constants must match the number of bands in the image. | |
250 * We do only 3 (RGB) bands. | |
251 */ | |
252 int ncol = img.getColorModel().getNumColorComponents(); | |
253 if ((ncol != 3) || (rgbm.length != 3) || (rgba.length != 3)) { | |
254 util.dprintln( | |
255 2, | |
256 "ERROR(enhance): unknown number of color bands or coefficients (" | |
257 + ncol | |
258 + ")"); | |
259 return; | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
260 } |
86 | 261 RescaleOp scaleOp = new RescaleOp(rgbOrdered(rgbm), rgbOrdered(rgba), null); |
262 scaleOp.filter(img, img); | |
263 } | |
264 | |
265 /** Ensures that the array f is in the right order to map the images RGB components. | |
266 */ | |
267 public float[] rgbOrdered(float[] fa) { | |
268 float[] fb = new float[3]; | |
269 int t = img.getType(); | |
270 if ((t == BufferedImage.TYPE_3BYTE_BGR) | |
271 || (t == BufferedImage.TYPE_4BYTE_ABGR) | |
272 || (t == BufferedImage.TYPE_4BYTE_ABGR_PRE)) { | |
273 // BGR Type (actually it looks like RBG...) | |
274 fb[0] = fa[0]; | |
275 fb[1] = fa[2]; | |
276 fb[2] = fa[1]; | |
277 } else { | |
278 fb = fa; | |
279 } | |
280 return fb; | |
85 | 281 } |
282 | |
86 | 283 public void rotate(double angle) throws ImageOpException { |
284 // setup rotation | |
285 double rangle = Math.toRadians(angle); | |
286 double x = getWidth() / 2; | |
287 double y = getHeight() / 2; | |
288 AffineTransformOp rotOp = | |
289 new AffineTransformOp( | |
290 AffineTransform.getRotateInstance(rangle, x, y), | |
291 interpol); | |
292 BufferedImage rotImg = rotOp.filter(img, null); | |
293 | |
294 if (rotImg == null) { | |
295 util.dprintln(2, "ERROR: error in rotate"); | |
296 throw new ImageOpException("Unable to rotate"); | |
297 } | |
298 img = rotImg; | |
299 } | |
85 | 300 |
86 | 301 public void mirror(double angle) throws ImageOpException { |
302 // setup mirror | |
303 double mx = 1; | |
304 double my = 1; | |
305 double tx = 0; | |
306 double ty = 0; | |
307 if (Math.abs(angle - 0) < epsilon) { | |
308 // 0 degree | |
309 mx = -1; | |
310 tx = getWidth(); | |
311 } else if (Math.abs(angle - 90) < epsilon) { | |
312 // 90 degree | |
313 my = -1; | |
314 ty = getHeight(); | |
315 } else if (Math.abs(angle - 180) < epsilon) { | |
316 // 180 degree | |
317 mx = -1; | |
318 tx = getWidth(); | |
319 } else if (Math.abs(angle - 270) < epsilon) { | |
320 // 270 degree | |
321 my = -1; | |
322 ty = getHeight(); | |
323 } else if (Math.abs(angle - 360) < epsilon) { | |
324 // 360 degree | |
325 mx = -1; | |
326 tx = getWidth(); | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
327 } |
86 | 328 AffineTransformOp mirOp = |
329 new AffineTransformOp( | |
330 new AffineTransform(mx, 0, 0, my, tx, ty), | |
331 interpol); | |
332 BufferedImage mirImg = mirOp.filter(img, null); | |
333 | |
334 if (mirImg == null) { | |
335 util.dprintln(2, "ERROR: error in mirror"); | |
336 throw new ImageOpException("Unable to mirror"); | |
337 } | |
338 img = mirImg; | |
339 } | |
340 | |
341 /* check image size and type and store in DocuFile f */ | |
342 public boolean checkFile(DocuFile f) throws IOException { | |
343 // see if f is already loaded | |
344 if ((reader == null) || (imgFile != f.getFile())) { | |
345 preloadImage(f.getFile()); | |
346 } | |
347 Dimension d = new Dimension(); | |
348 d.setSize(reader.getWidth(0), reader.getHeight(0)); | |
349 f.setSize(d); | |
350 // String t = reader.getFormatName(); | |
351 String t = FileOps.mimeForFile(f.getFile()); | |
352 f.setMimetype(t); | |
353 f.setChecked(true); | |
354 return true; | |
355 } | |
1 | 356 |
357 } |