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;