Mercurial > hg > digilib-old
comparison servlet/src/digilib/image/ImageLoaderDocuImage.java @ 144:d87a7e2515af
Sevlet version 1.12b5
- improved scaling also for ImageLoaderDocuImage
author | robcast |
---|---|
date | Tue, 19 Aug 2003 22:31:48 +0200 |
parents | c878ea574c29 |
children | d76006c12e89 |
comparison
equal
deleted
inserted
replaced
143:81937cc5c743 | 144:d87a7e2515af |
---|---|
23 import java.awt.Rectangle; | 23 import java.awt.Rectangle; |
24 import java.awt.geom.AffineTransform; | 24 import java.awt.geom.AffineTransform; |
25 import java.awt.geom.Rectangle2D; | 25 import java.awt.geom.Rectangle2D; |
26 import java.awt.image.AffineTransformOp; | 26 import java.awt.image.AffineTransformOp; |
27 import java.awt.image.BufferedImage; | 27 import java.awt.image.BufferedImage; |
28 import java.awt.image.ConvolveOp; | |
29 import java.awt.image.Kernel; | |
28 import java.awt.image.RescaleOp; | 30 import java.awt.image.RescaleOp; |
29 import java.io.File; | 31 import java.io.File; |
30 import java.io.IOException; | 32 import java.io.IOException; |
31 import java.io.OutputStream; | 33 import java.io.OutputStream; |
32 import java.io.RandomAccessFile; | 34 import java.io.RandomAccessFile; |
174 util.dprintln(2, "ERROR(writeImage): Unknown mime type " + mt); | 176 util.dprintln(2, "ERROR(writeImage): Unknown mime type " + mt); |
175 throw new FileOpException("Unknown mime type: " + mt); | 177 throw new FileOpException("Unknown mime type: " + mt); |
176 } | 178 } |
177 | 179 |
178 /* JPEG doesn't do transparency so we have to convert any RGBA image | 180 /* JPEG doesn't do transparency so we have to convert any RGBA image |
179 * to RGB :-( | 181 * to RGB :-( *Java2D BUG* |
180 */ | 182 */ |
181 if ((type == "jpeg") && (img.getColorModel().hasAlpha())) { | 183 if ((type == "jpeg") && (img.getColorModel().hasAlpha())) { |
182 util.dprintln(2, "BARF: JPEG with transparency!!"); | 184 util.dprintln(2, "BARF: JPEG with transparency!!"); |
183 int w = img.getWidth(); | 185 int w = img.getWidth(); |
184 int h = img.getHeight(); | 186 int h = img.getHeight(); |
185 // BufferedImage.TYPE_INT_RGB seems to be fastest (JDK1.4.1, OSX) | 187 // BufferedImage.TYPE_INT_RGB seems to be fastest (JDK1.4.1, OSX) |
186 BufferedImage img2; | 188 int destType = BufferedImage.TYPE_INT_RGB; |
187 img2 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); | 189 BufferedImage img2 = new BufferedImage(w, h, destType); |
188 img2.createGraphics().drawImage(img, null, 0, 0); | 190 img2.createGraphics().drawImage(img, null, 0, 0); |
189 img = img2; | 191 img = img2; |
190 } | 192 } |
191 | |
192 /* try ImageWriter.write | |
193 Iterator writers = ImageIO.getImageWritersByFormatName(type); | |
194 ImageWriter writer = (ImageWriter) writers.next(); | |
195 System.out.println("this writer: " + writer.getClass()); | |
196 while (writers.hasNext()) { | |
197 System.out.println("next writer: " + writers.next().getClass()); | |
198 } | |
199 //ImageWriteParam param = writer.getDefaultWriteParam(); | |
200 IIOImage iimg = new IIOImage(img, null, null); | |
201 ImageOutputStream iostream = new MemoryCacheImageOutputStream(ostream); | |
202 writer.setOutput(iostream); | |
203 writer.write(iimg); | |
204 */ | |
205 | 193 |
206 // render output | 194 // render output |
207 if (ImageIO.write(img, type, ostream)) { | 195 if (ImageIO.write(img, type, ostream)) { |
208 // writing was OK | 196 // writing was OK |
209 return; | 197 return; |
215 throw new FileOpException("Error writing image."); | 203 throw new FileOpException("Error writing image."); |
216 } | 204 } |
217 } | 205 } |
218 | 206 |
219 public void scale(double scale) throws ImageOpException { | 207 public void scale(double scale) throws ImageOpException { |
220 // setup scale | 208 /* |
209 * for downscaling in high quality the image is blurred first | |
210 */ | |
211 if ((scale <= 0.5) && (quality > 1)) { | |
212 int bl = (int) Math.floor(1 / scale); | |
213 blur(bl); | |
214 } | |
215 /* | |
216 * and scaled | |
217 */ | |
221 AffineTransformOp scaleOp = | 218 AffineTransformOp scaleOp = |
222 new AffineTransformOp( | 219 new AffineTransformOp( |
223 AffineTransform.getScaleInstance(scale, scale), | 220 AffineTransform.getScaleInstance(scale, scale), |
224 interpol); | 221 interpol); |
225 BufferedImage scaledImg = scaleOp.createCompatibleDestImage(img, null); | 222 BufferedImage scaledImg = null; |
226 scaleOp.filter(img, scaledImg); | 223 // enforce grey destination image for greyscale *Java2D BUG* |
227 | 224 if ((quality > 0) |
225 && ((img.getType() == BufferedImage.TYPE_BYTE_GRAY) | |
226 || (img.getType() == BufferedImage.TYPE_BYTE_BINARY) | |
227 || (img.getType() == BufferedImage.TYPE_USHORT_GRAY))) { | |
228 Rectangle2D dstBounds = scaleOp.getBounds2D(img); | |
229 scaledImg = | |
230 new BufferedImage( | |
231 (int) dstBounds.getWidth(), | |
232 (int) dstBounds.getHeight(), | |
233 img.getType()); | |
234 } | |
235 scaledImg = scaleOp.filter(img, scaledImg); | |
236 //DEBUG | |
237 util.dprintln( | |
238 3, | |
239 "SCALE: " | |
240 + scale | |
241 + " ->" | |
242 + scaledImg.getWidth() | |
243 + "x" | |
244 + scaledImg.getHeight()); | |
228 if (scaledImg == null) { | 245 if (scaledImg == null) { |
229 util.dprintln(2, "ERROR(cropAndScale): error in scale"); | 246 util.dprintln(2, "ERROR(cropAndScale): error in scale"); |
230 throw new ImageOpException("Unable to scale"); | 247 throw new ImageOpException("Unable to scale"); |
231 } | 248 } |
232 img = scaledImg; | 249 img = scaledImg; |
250 } | |
251 | |
252 public void blur(int radius) throws ImageOpException { | |
253 BufferedImage blurredImg; | |
254 //DEBUG | |
255 util.dprintln(4, "blur: " + radius); | |
256 // minimum radius is 2 | |
257 int klen = Math.max(radius, 2); | |
258 int ksize = klen * klen; | |
259 // kernel is constant 1/k | |
260 float f = 1f / ksize; | |
261 float[] kern = new float[ksize]; | |
262 for (int i = 0; i < ksize; i++) { | |
263 kern[i] = f; | |
264 } | |
265 Kernel blur = new Kernel(klen, klen, kern); | |
266 // blur with convolve operation | |
267 ConvolveOp blurOp = new ConvolveOp(blur, ConvolveOp.EDGE_NO_OP, null); | |
268 blurredImg = blurOp.filter(img, null); | |
269 if (blurredImg == null) { | |
270 util.dprintln(2, "ERROR(cropAndScale): error in scale"); | |
271 throw new ImageOpException("Unable to scale"); | |
272 } | |
273 img = blurredImg; | |
233 } | 274 } |
234 | 275 |
235 public void crop(int x_off, int y_off, int width, int height) | 276 public void crop(int x_off, int y_off, int width, int height) |
236 throws ImageOpException { | 277 throws ImageOpException { |
237 // setup Crop | 278 // setup Crop |
238 BufferedImage croppedImg = img.getSubimage(x_off, y_off, width, height); | 279 BufferedImage croppedImg = img.getSubimage(x_off, y_off, width, height); |
239 | |
240 util.dprintln( | 280 util.dprintln( |
241 3, | 281 3, |
242 "CROP:" + croppedImg.getWidth() + "x" + croppedImg.getHeight()); | 282 "CROP:" + croppedImg.getWidth() + "x" + croppedImg.getHeight()); |
243 //DEBUG | 283 //DEBUG |
244 // util.dprintln(2, " time "+(System.currentTimeMillis()-startTime)+"ms"); | 284 // util.dprintln(2, " time "+(System.currentTimeMillis()-startTime)+"ms"); |
245 | |
246 if (croppedImg == null) { | 285 if (croppedImg == null) { |
247 util.dprintln(2, "ERROR(cropAndScale): error in crop"); | 286 util.dprintln(2, "ERROR(cropAndScale): error in crop"); |
248 throw new ImageOpException("Unable to crop"); | 287 throw new ImageOpException("Unable to crop"); |
249 } | 288 } |
250 img = croppedImg; | 289 img = croppedImg; |
251 } | 290 } |
252 | 291 |
253 public void enhance(float mult, float add) throws ImageOpException { | 292 public void enhance(float mult, float add) |
254 /* Only one constant should work regardless of the number of bands | 293 throws ImageOpException { /* Only one constant should work regardless of the number of bands |
255 * according to the JDK spec. | 294 * according to the JDK spec. |
256 * Doesn't work on JDK 1.4 for OSX and Linux (at least). | 295 * Doesn't work on JDK 1.4 for OSX and Linux (at least). |
257 */ | 296 */ /* RescaleOp scaleOp = |
258 /* RescaleOp scaleOp = | 297 new RescaleOp( |
259 new RescaleOp( | 298 (float)mult, (float)add, |
260 (float)mult, (float)add, | 299 null); |
261 null); | 300 scaleOp.filter(img, img); |
262 scaleOp.filter(img, img); | 301 */ /* The number of constants must match the number of bands in the image. |
263 */ | 302 */ |
264 /* The number of constants must match the number of bands in the image. | |
265 */ | |
266 int ncol = img.getColorModel().getNumColorComponents(); | 303 int ncol = img.getColorModel().getNumColorComponents(); |
267 float[] dm = new float[ncol]; | 304 float[] dm = new float[ncol]; |
268 float[] da = new float[ncol]; | 305 float[] da = new float[ncol]; |
269 for (int i = 0; i < ncol; i++) { | 306 for (int i = 0; i < ncol; i++) { |
270 dm[i] = (float) mult; | 307 dm[i] = (float) mult; |
271 da[i] = (float) add; | 308 da[i] = (float) add; |
272 } | 309 } |
273 RescaleOp scaleOp = new RescaleOp(dm, da, null); | 310 RescaleOp scaleOp = new RescaleOp(dm, da, null); |
274 scaleOp.filter(img, img); | 311 scaleOp.filter(img, img); |
275 | |
276 } | 312 } |
277 | 313 |
278 public void enhanceRGB(float[] rgbm, float[] rgba) | 314 public void enhanceRGB(float[] rgbm, float[] rgba) |
279 throws ImageOpException { | 315 throws ImageOpException { /* The number of constants must match the number of bands in the image. |
280 /* The number of constants must match the number of bands in the image. | 316 * We do only 3 (RGB) bands. |
281 * We do only 3 (RGB) bands. | 317 */ |
282 */ | |
283 int ncol = img.getColorModel().getNumColorComponents(); | 318 int ncol = img.getColorModel().getNumColorComponents(); |
284 if ((ncol != 3) || (rgbm.length != 3) || (rgba.length != 3)) { | 319 if ((ncol != 3) || (rgbm.length != 3) || (rgba.length != 3)) { |
285 util.dprintln( | 320 util.dprintln( |
286 2, | 321 2, |
287 "ERROR(enhance): unknown number of color bands or coefficients (" | 322 "ERROR(enhance): unknown number of color bands or coefficients (" |
290 return; | 325 return; |
291 } | 326 } |
292 RescaleOp scaleOp = | 327 RescaleOp scaleOp = |
293 new RescaleOp(rgbOrdered(rgbm), rgbOrdered(rgba), null); | 328 new RescaleOp(rgbOrdered(rgbm), rgbOrdered(rgba), null); |
294 scaleOp.filter(img, img); | 329 scaleOp.filter(img, img); |
295 } | 330 } /** Ensures that the array f is in the right order to map the images RGB components. |
296 | 331 */ |
297 /** Ensures that the array f is in the right order to map the images RGB components. | |
298 */ | |
299 public float[] rgbOrdered(float[] fa) { | 332 public float[] rgbOrdered(float[] fa) { |
300 float[] fb = new float[3]; | 333 float[] fb = new float[3]; |
301 int t = img.getType(); | 334 int t = img.getType(); |
302 if ((t == BufferedImage.TYPE_3BYTE_BGR) | 335 if ((t == BufferedImage.TYPE_3BYTE_BGR) |
303 || (t == BufferedImage.TYPE_4BYTE_ABGR) | 336 || (t == BufferedImage.TYPE_4BYTE_ABGR) |
334 // transform image | 367 // transform image |
335 rotOp = new AffineTransformOp(trafo, interpol); | 368 rotOp = new AffineTransformOp(trafo, interpol); |
336 BufferedImage rotImg = rotOp.filter(img, null); | 369 BufferedImage rotImg = rotOp.filter(img, null); |
337 // calculate new bounding box | 370 // calculate new bounding box |
338 //Rectangle2D bounds = rotOp.getBounds2D(img); | 371 //Rectangle2D bounds = rotOp.getBounds2D(img); |
339 | |
340 if (rotImg == null) { | 372 if (rotImg == null) { |
341 util.dprintln(2, "ERROR: error in rotate"); | 373 util.dprintln(2, "ERROR: error in rotate"); |
342 throw new ImageOpException("Unable to rotate"); | 374 throw new ImageOpException("Unable to rotate"); |
343 } | 375 } |
344 img = rotImg; | 376 img = rotImg; |
356 // setup mirror | 388 // setup mirror |
357 double mx = 1; | 389 double mx = 1; |
358 double my = 1; | 390 double my = 1; |
359 double tx = 0; | 391 double tx = 0; |
360 double ty = 0; | 392 double ty = 0; |
361 if (Math.abs(angle - 0) < epsilon) { | 393 if (Math.abs(angle - 0) < epsilon) { // 0 degree |
362 // 0 degree | |
363 mx = -1; | 394 mx = -1; |
364 tx = getWidth(); | 395 tx = getWidth(); |
365 } else if (Math.abs(angle - 90) < epsilon) { | 396 } else if (Math.abs(angle - 90) < epsilon) { // 90 degree |
366 // 90 degree | |
367 my = -1; | 397 my = -1; |
368 ty = getHeight(); | 398 ty = getHeight(); |
369 } else if (Math.abs(angle - 180) < epsilon) { | 399 } else if (Math.abs(angle - 180) < epsilon) { // 180 degree |
370 // 180 degree | |
371 mx = -1; | 400 mx = -1; |
372 tx = getWidth(); | 401 tx = getWidth(); |
373 } else if (Math.abs(angle - 270) < epsilon) { | 402 } else if (Math.abs(angle - 270) < epsilon) { // 270 degree |
374 // 270 degree | |
375 my = -1; | 403 my = -1; |
376 ty = getHeight(); | 404 ty = getHeight(); |
377 } else if (Math.abs(angle - 360) < epsilon) { | 405 } else if (Math.abs(angle - 360) < epsilon) { // 360 degree |
378 // 360 degree | |
379 mx = -1; | 406 mx = -1; |
380 tx = getWidth(); | 407 tx = getWidth(); |
381 } | 408 } |
382 AffineTransformOp mirOp = | 409 AffineTransformOp mirOp = |
383 new AffineTransformOp( | 410 new AffineTransformOp( |
384 new AffineTransform(mx, 0, 0, my, tx, ty), | 411 new AffineTransform(mx, 0, 0, my, tx, ty), |
385 interpol); | 412 interpol); |
386 BufferedImage mirImg = mirOp.filter(img, null); | 413 BufferedImage mirImg = mirOp.filter(img, null); |
387 | |
388 if (mirImg == null) { | 414 if (mirImg == null) { |
389 util.dprintln(2, "ERROR: error in mirror"); | 415 util.dprintln(2, "ERROR: error in mirror"); |
390 throw new ImageOpException("Unable to mirror"); | 416 throw new ImageOpException("Unable to mirror"); |
391 } | 417 } |
392 img = mirImg; | 418 img = mirImg; |