# HG changeset patch # User robcast # Date 1061325108 -7200 # Node ID d87a7e2515af065b3ab896f53ae48c59f28feeae # Parent 81937cc5c7434c1b3945cad2571c4a6821b54852 Sevlet version 1.12b5 - improved scaling also for ImageLoaderDocuImage diff -r 81937cc5c743 -r d87a7e2515af client/digitallibrary/WEB-INF/lib/DigilibServlet.jar Binary file client/digitallibrary/WEB-INF/lib/DigilibServlet.jar has changed diff -r 81937cc5c743 -r d87a7e2515af servlet/src/digilib/image/ImageLoaderDocuImage.java --- 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"); diff -r 81937cc5c743 -r d87a7e2515af servlet/src/digilib/image/JAIDocuImage.java --- 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 */ diff -r 81937cc5c743 -r d87a7e2515af servlet/src/digilib/servlet/Scaler.java --- 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;