changeset 144:d87a7e2515af

Sevlet version 1.12b5 - improved scaling also for ImageLoaderDocuImage
author robcast
date Tue, 19 Aug 2003 22:31:48 +0200
parents 81937cc5c743
children d76006c12e89
files client/digitallibrary/WEB-INF/lib/DigilibServlet.jar servlet/src/digilib/image/ImageLoaderDocuImage.java servlet/src/digilib/image/JAIDocuImage.java servlet/src/digilib/servlet/Scaler.java
diffstat 4 files changed, 111 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
Binary file client/digitallibrary/WEB-INF/lib/DigilibServlet.jar has changed
--- a/servlet/src/digilib/image/ImageLoaderDocuImage.java	Mon Aug 18 11:53:14 2003 +0200
+++ b/servlet/src/digilib/image/ImageLoaderDocuImage.java	Tue Aug 19 22:31:48 2003 +0200
@@ -25,6 +25,8 @@
 import java.awt.geom.Rectangle2D;
 import java.awt.image.AffineTransformOp;
 import java.awt.image.BufferedImage;
+import java.awt.image.ConvolveOp;
+import java.awt.image.Kernel;
 import java.awt.image.RescaleOp;
 import java.io.File;
 import java.io.IOException;
@@ -176,33 +178,19 @@
 			}
 
 			/* JPEG doesn't do transparency so we have to convert any RGBA image
-			 * to RGB :-(
+			 * to RGB :-( *Java2D BUG*
 			 */
 			if ((type == "jpeg") && (img.getColorModel().hasAlpha())) {
 				util.dprintln(2, "BARF: JPEG with transparency!!");
 				int w = img.getWidth();
 				int h = img.getHeight();
 				// BufferedImage.TYPE_INT_RGB seems to be fastest (JDK1.4.1, OSX)
-				BufferedImage img2;
-				img2 = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+				int destType = BufferedImage.TYPE_INT_RGB;
+				BufferedImage img2 = new BufferedImage(w, h, destType);
 				img2.createGraphics().drawImage(img, null, 0, 0);
 				img = img2;
 			}
 
-			/* try ImageWriter.write
-			Iterator writers = ImageIO.getImageWritersByFormatName(type);
-			ImageWriter writer = (ImageWriter) writers.next();
-			System.out.println("this writer: " + writer.getClass());
-			while (writers.hasNext()) {
-				System.out.println("next writer: " + writers.next().getClass());
-			}
-			//ImageWriteParam param = writer.getDefaultWriteParam();
-			IIOImage iimg = new IIOImage(img, null, null); 
-			ImageOutputStream iostream = new MemoryCacheImageOutputStream(ostream);
-			writer.setOutput(iostream);
-			writer.write(iimg);
-			*/
-
 			// render output
 			if (ImageIO.write(img, type, ostream)) {
 				// writing was OK
@@ -217,14 +205,43 @@
 	}
 
 	public void scale(double scale) throws ImageOpException {
-		// setup scale
+		/*
+		 * for downscaling in high quality the image is blurred first
+		 */
+		if ((scale <= 0.5) && (quality > 1)) {
+			int bl = (int) Math.floor(1 / scale);
+			blur(bl);
+		}
+		/*
+		 * and scaled
+		 */
 		AffineTransformOp scaleOp =
 			new AffineTransformOp(
 				AffineTransform.getScaleInstance(scale, scale),
 				interpol);
-		BufferedImage scaledImg = scaleOp.createCompatibleDestImage(img, null);
-		scaleOp.filter(img, scaledImg);
-
+		BufferedImage scaledImg = null;
+		// enforce grey destination image for greyscale *Java2D BUG*
+		if ((quality > 0)
+			&& ((img.getType() == BufferedImage.TYPE_BYTE_GRAY)
+				|| (img.getType() == BufferedImage.TYPE_BYTE_BINARY)
+				|| (img.getType() == BufferedImage.TYPE_USHORT_GRAY))) {
+			Rectangle2D dstBounds = scaleOp.getBounds2D(img);
+			scaledImg =
+				new BufferedImage(
+					(int) dstBounds.getWidth(),
+					(int) dstBounds.getHeight(),
+					img.getType());
+		}
+		scaledImg = scaleOp.filter(img, scaledImg);
+		//DEBUG
+		util.dprintln(
+			3,
+			"SCALE: "
+				+ scale
+				+ " ->"
+				+ scaledImg.getWidth()
+				+ "x"
+				+ scaledImg.getHeight());
 		if (scaledImg == null) {
 			util.dprintln(2, "ERROR(cropAndScale): error in scale");
 			throw new ImageOpException("Unable to scale");
@@ -232,17 +249,39 @@
 		img = scaledImg;
 	}
 
+	public void blur(int radius) throws ImageOpException {
+		BufferedImage blurredImg;
+		//DEBUG
+		util.dprintln(4, "blur: " + radius);
+		// minimum radius is 2
+		int klen = Math.max(radius, 2);
+		int ksize = klen * klen;
+		// kernel is constant 1/k
+		float f = 1f / ksize;
+		float[] kern = new float[ksize];
+		for (int i = 0; i < ksize; i++) {
+			kern[i] = f;
+		}
+		Kernel blur = new Kernel(klen, klen, kern);
+		// blur with convolve operation
+		ConvolveOp blurOp = new ConvolveOp(blur, ConvolveOp.EDGE_NO_OP, null);
+		blurredImg = blurOp.filter(img, null);
+		if (blurredImg == null) {
+			util.dprintln(2, "ERROR(cropAndScale): error in scale");
+			throw new ImageOpException("Unable to scale");
+		}
+		img = blurredImg;
+	}
+
 	public void crop(int x_off, int y_off, int width, int height)
 		throws ImageOpException {
 		// setup Crop
 		BufferedImage croppedImg = img.getSubimage(x_off, y_off, width, height);
-
 		util.dprintln(
 			3,
 			"CROP:" + croppedImg.getWidth() + "x" + croppedImg.getHeight());
 		//DEBUG
 		//    util.dprintln(2, "  time "+(System.currentTimeMillis()-startTime)+"ms");
-
 		if (croppedImg == null) {
 			util.dprintln(2, "ERROR(cropAndScale): error in crop");
 			throw new ImageOpException("Unable to crop");
@@ -250,19 +289,17 @@
 		img = croppedImg;
 	}
 
-	public void enhance(float mult, float add) throws ImageOpException {
-		/* Only one constant should work regardless of the number of bands 
-		 * according to the JDK spec.
-		 * Doesn't work on JDK 1.4 for OSX and Linux (at least).
-		 */
-		/*		RescaleOp scaleOp =
-					new RescaleOp(
-						(float)mult, (float)add,
-						null);
-				scaleOp.filter(img, img);
-		*/
-		/* The number of constants must match the number of bands in the image.
-		 */
+	public void enhance(float mult, float add)
+		throws ImageOpException { /* Only one constant should work regardless of the number of bands 
+			 * according to the JDK spec.
+			 * Doesn't work on JDK 1.4 for OSX and Linux (at least).
+			 */ /*		RescaleOp scaleOp =
+						new RescaleOp(
+							(float)mult, (float)add,
+							null);
+					scaleOp.filter(img, img);
+			*/ /* The number of constants must match the number of bands in the image.
+			 */
 		int ncol = img.getColorModel().getNumColorComponents();
 		float[] dm = new float[ncol];
 		float[] da = new float[ncol];
@@ -272,14 +309,12 @@
 		}
 		RescaleOp scaleOp = new RescaleOp(dm, da, null);
 		scaleOp.filter(img, img);
-
 	}
 
 	public void enhanceRGB(float[] rgbm, float[] rgba)
-		throws ImageOpException {
-		/* The number of constants must match the number of bands in the image.
-		 * We do only 3 (RGB) bands.
-		 */
+		throws ImageOpException { /* The number of constants must match the number of bands in the image.
+			 * We do only 3 (RGB) bands.
+			 */
 		int ncol = img.getColorModel().getNumColorComponents();
 		if ((ncol != 3) || (rgbm.length != 3) || (rgba.length != 3)) {
 			util.dprintln(
@@ -292,10 +327,8 @@
 		RescaleOp scaleOp =
 			new RescaleOp(rgbOrdered(rgbm), rgbOrdered(rgba), null);
 		scaleOp.filter(img, img);
-	}
-
-	/** Ensures that the array f is in the right order to map the images RGB components. 
-	 */
+	} /** Ensures that the array f is in the right order to map the images RGB components. 
+				 */
 	public float[] rgbOrdered(float[] fa) {
 		float[] fb = new float[3];
 		int t = img.getType();
@@ -336,7 +369,6 @@
 		BufferedImage rotImg = rotOp.filter(img, null);
 		// calculate new bounding box
 		//Rectangle2D bounds = rotOp.getBounds2D(img);
-
 		if (rotImg == null) {
 			util.dprintln(2, "ERROR: error in rotate");
 			throw new ImageOpException("Unable to rotate");
@@ -358,24 +390,19 @@
 		double my = 1;
 		double tx = 0;
 		double ty = 0;
-		if (Math.abs(angle - 0) < epsilon) {
-			// 0 degree
+		if (Math.abs(angle - 0) < epsilon) { // 0 degree
 			mx = -1;
 			tx = getWidth();
-		} else if (Math.abs(angle - 90) < epsilon) {
-			// 90 degree
+		} else if (Math.abs(angle - 90) < epsilon) { // 90 degree
 			my = -1;
 			ty = getHeight();
-		} else if (Math.abs(angle - 180) < epsilon) {
-			// 180 degree
+		} else if (Math.abs(angle - 180) < epsilon) { // 180 degree
 			mx = -1;
 			tx = getWidth();
-		} else if (Math.abs(angle - 270) < epsilon) {
-			// 270 degree
+		} else if (Math.abs(angle - 270) < epsilon) { // 270 degree
 			my = -1;
 			ty = getHeight();
-		} else if (Math.abs(angle - 360) < epsilon) {
-			// 360 degree
+		} else if (Math.abs(angle - 360) < epsilon) { // 360 degree
 			mx = -1;
 			tx = getWidth();
 		}
@@ -384,7 +411,6 @@
 				new AffineTransform(mx, 0, 0, my, tx, ty),
 				interpol);
 		BufferedImage mirImg = mirOp.filter(img, null);
-
 		if (mirImg == null) {
 			util.dprintln(2, "ERROR: error in mirror");
 			throw new ImageOpException("Unable to mirror");
--- a/servlet/src/digilib/image/JAIDocuImage.java	Mon Aug 18 11:53:14 2003 +0200
+++ b/servlet/src/digilib/image/JAIDocuImage.java	Tue Aug 19 22:31:48 2003 +0200
@@ -130,52 +130,40 @@
 
 	/* scales the current image */
 	public void scale(double scale) throws ImageOpException {
-		RenderedImage scaledImg = null;
 		if ((scale < 1)
 			&& (img.getColorModel().getPixelSize() == 1)
 			&& (quality > 0)) {
 			/*
 			 * "SubsampleBinaryToGray" for downscaling BW
 			 */
-			scaledImg = scaleBinary((float) scale, img);
+			scaleBinary((float) scale);
 		} else if ((scale <= 0.5) && (quality > 1)) {
 			/*
 			 * blur and "Scale" for downscaling color images
 			 */
 			int subsample = (int) Math.floor(1 / scale);
-			RenderedImage prescaledImg = img;
-			prescaledImg = blur(subsample, img);
-			scaledImg = scaleAll((float) scale, prescaledImg);
+			blur(subsample);
+			scaleAll((float) scale);
 		} else {
 			/*
 			 * "Scale" for the rest
 			 */
-			scaledImg = scaleAll((float) scale, img);
+			scaleAll((float) scale);
 		}
 
 		//DEBUG
 		util.dprintln(
 			3,
-			"SCALE: "
-				+ scale
-				+ " ->"
-				+ scaledImg.getWidth()
-				+ "x"
-				+ scaledImg.getHeight());
+			"SCALE: " + scale + " ->" + img.getWidth() + "x" + img.getHeight());
 
-		if (scaledImg == null) {
-			util.dprintln(2, "ERROR(scale): error in scale");
-			throw new ImageOpException("Unable to scale");
-		}
-		img = scaledImg;
 	}
 
-	private RenderedImage scaleAll(float scale, RenderedImage image) {
+	public void scaleAll(float scale) throws ImageOpException {
 		RenderedImage scaledImg;
 		//DEBUG
 		util.dprintln(4, "scaleAll: " + scale);
 		ParameterBlockJAI param = new ParameterBlockJAI("Scale");
-		param.addSource(image);
+		param.addSource(img);
 		param.setParameter("xScale", scale);
 		param.setParameter("yScale", scale);
 		param.setParameter("interpolation", interpol);
@@ -186,10 +174,15 @@
 				BorderExtender.createInstance(BorderExtender.BORDER_COPY));
 		// scale
 		scaledImg = JAI.create("Scale", param, hint);
-		return scaledImg;
+
+		if (scaledImg == null) {
+			util.dprintln(2, "ERROR(scale): error in scale");
+			throw new ImageOpException("Unable to scale");
+		}
+		img = scaledImg;
 	}
 
-	private RenderedImage blur(int radius, RenderedImage image) {
+	public void blur(int radius) throws ImageOpException {
 		RenderedImage blurredImg;
 		//DEBUG
 		util.dprintln(4, "blur: " + radius);
@@ -202,7 +195,7 @@
 		}
 		KernelJAI blur = new KernelJAI(klen, klen, kern);
 		ParameterBlockJAI param = new ParameterBlockJAI("Convolve");
-		param.addSource(image);
+		param.addSource(img);
 		param.setParameter("kernel", blur);
 		// hint with border extender
 		RenderingHints hint =
@@ -210,16 +203,20 @@
 				JAI.KEY_BORDER_EXTENDER,
 				BorderExtender.createInstance(BorderExtender.BORDER_COPY));
 		blurredImg = JAI.create("Convolve", param, hint);
-		return blurredImg;
+		if (blurredImg == null) {
+			util.dprintln(2, "ERROR(scale): error in scale");
+			throw new ImageOpException("Unable to scale");
+		}
+		img = blurredImg;
 	}
 
-	RenderedImage scaleBinary(float scale, RenderedImage image) {
+	public void scaleBinary(float scale) throws ImageOpException {
 		RenderedImage scaledImg;
 		//DEBUG
 		util.dprintln(4, "scaleBinary: " + scale);
 		ParameterBlockJAI param =
 			new ParameterBlockJAI("SubsampleBinaryToGray");
-		param.addSource(image);
+		param.addSource(img);
 		param.setParameter("xScale", scale);
 		param.setParameter("yScale", scale);
 		// hint with border extender
@@ -229,7 +226,11 @@
 				BorderExtender.createInstance(BorderExtender.BORDER_COPY));
 		// scale
 		scaledImg = JAI.create("SubsampleBinaryToGray", param, hint);
-		return scaledImg;
+		if (scaledImg == null) {
+			util.dprintln(2, "ERROR(scale): error in scale");
+			throw new ImageOpException("Unable to scale");
+		}
+		img = scaledImg;
 	}
 
 	/* crops the current image */
--- a/servlet/src/digilib/servlet/Scaler.java	Mon Aug 18 11:53:14 2003 +0200
+++ b/servlet/src/digilib/servlet/Scaler.java	Tue Aug 19 22:31:48 2003 +0200
@@ -58,7 +58,7 @@
 public class Scaler extends HttpServlet {
 
 	// digilib servlet version (for all components)
-	public static final String dlVersion = "1.12b3";
+	public static final String dlVersion = "1.12b5";
 
 	// Utils instance with debuglevel
 	Utils util;