Mercurial > hg > digilib-old
changeset 79:63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
* mirroring
* contrast/brightness
* rotation (not finished)
author | robcast |
---|---|
date | Mon, 03 Feb 2003 16:04:53 +0100 |
parents | e0dcac9c66fa |
children | 4d0e75042673 |
files | servlet/src/digilib/image/DocuImage.java servlet/src/digilib/image/DocuImageImpl.java servlet/src/digilib/image/ImageLoaderDocuImage.java servlet/src/digilib/image/JAIDocuImage.java servlet/src/digilib/image/JAIImageLoaderDocuImage.java servlet/src/digilib/image/JIMIDocuImage.java servlet/src/digilib/servlet/DigilibRequest.java servlet/src/digilib/servlet/DocumentBean.java servlet/src/digilib/servlet/Scaler.java |
diffstat | 9 files changed, 935 insertions(+), 590 deletions(-) [+] |
line wrap: on
line diff
--- a/servlet/src/digilib/image/DocuImage.java Fri Jan 24 22:13:49 2003 +0100 +++ b/servlet/src/digilib/image/DocuImage.java Mon Feb 03 16:04:53 2003 +0100 @@ -21,12 +21,10 @@ package digilib.image; import java.io.File; - -import javax.servlet.ServletResponse; +import java.io.OutputStream; import digilib.io.FileOpException; - /** The basic class for the representation of a digilib image. * * The actual image object is hidden in the class, only methods for loading, @@ -36,61 +34,139 @@ */ public interface DocuImage { - /** Returns the list of image file types known to the DocuImage implementation. - * - * @return List of image file types. Strings are standard file extensions. - */ - public String[] getKnownFileTypes(); + /** Returns the list of image file types known to the DocuImage implementation. + * + * @return List of image file types. Strings are standard file extensions. + */ + public String[] getKnownFileTypes(); + + /** Loads an image file into the Object. + * + * @param f Image File. + * @throws FileOpException Exception thrown if any error occurs. + */ + public void loadImage(File f) throws FileOpException; - /** Loads an image file into the Object. - * - * @param f Image File. - * @throws FileOpException Exception thrown if any error occurs. - */ - public void loadImage(File f) throws FileOpException; + /** Writes the current image to a ServletResponse. + * + * The image is encoded to the mime-type <code>mt</code> and sent to the output + * stream of the <code>ServletResponse</code> <code>res</code>. + * + * Currently only mime-types "image/jpeg" and "image/png" are supported. + * + * @param mt mime-type of the image to be sent. + * @param res ServletResponse where the image is sent. + * @throws FileOpException Exception thrown on any error. + */ + public void writeImage(String mt, OutputStream ostream) + throws FileOpException; - /** Writes the current image to a ServletResponse. - * - * The image is encoded to the mime-type <code>mt</code> and sent to the output - * stream of the <code>ServletResponse</code> <code>res</code>. - * - * Currently only mime-types "image/jpeg" and "image/png" are supported. - * - * @param mt mime-type of the image to be sent. - * @param res ServletResponse where the image is sent. - * @throws FileOpException Exception thrown on any error. - */ - public void writeImage(String mt, ServletResponse res) throws FileOpException; + /** The width of the current image in pixel. + * + * @return Image width in pixels. + */ + public int getWidth(); + + /** The height of the current image in pixel. + * + * @return Image height in pixels. + */ + public int getHeight(); + + /** Crops the current image. + * + * Cuts out a region of the size <code>width</code> x <code>height</code> at + * the offset <code>xoff</code>, <code>yoff</code> from the current image + * and replaces the current image with the result. + * + * @param xoff X offset of crop region + * @param yoff Y offset of crop region + * @param width width of crop region + * @param height height of crop region + * @throws ImageOpException + */ + public void crop(int xoff, int yoff, int width, int height) + throws ImageOpException; + + /** Scales the current image. + * + * Replaces the current image with an image scaled by the factor + * <code>scale</code>. + * + * @param scale scaling factor + * @throws ImageOpException + */ + public void scale(double scale) throws ImageOpException; - /** The width of the current image in pixel. - * - * @return Image width in pixels. - */ - public int getWidth(); - - /** The height of the current image in pixel. - * - * @return Image height in pixels. - */ - public int getHeight(); + /** Crops and scales the current image. + * + * The current image is cropped to a rectangle of <code>width</code>, + * <code>height</code> at position <code>x_off</code>, <code>y_off</code>. The + * resulting image is scaled by the factor <code>scale</code> using the + * interpolation quality <code>qual</code> (0=worst). + * + * @param x_off x offset of the crop rectangle in pixel. + * @param y_off y offset of the crop rectangle in pixel. + * @param width width of the crop rectangle in pixel. + * @param height height of the crop rectangle in pixel. + * @param scale scaling factor. + * @param qual interpolation quality (0=worst). + * @throws ImageOpException exception thrown on any error. + */ + public void cropAndScale( + int x_off, + int y_off, + int width, + int height, + double scale, + int qual) + throws ImageOpException; + + /** Rotates the current image. + * + * Replaces the current image with a rotated image. The image is rotated + * around the center by <code>angle</code> given in degrees [0, 360] + * clockwise. Image size and aspect ratio are likely to change. + * + * @param angle rotation angle in degree + */ + public void rotate(double angle) throws ImageOpException; + + /** Mirrors the current image. + * + * Replaces the current image with a mirrored image. The mirror axis goes + * through the center of the image and is rotated by <code>angle</code> + * degrees. Currently only horizontal and vertical mirroring (0 and 90 + * degree) are supported. + * + * @param angle angle of mirror axis + * @throws ImageOpException + */ + public void mirror(double angle) throws ImageOpException; + + /** Enhaces brightness and contrast of the current image. + * + * Replaces the current image with a brightness and contrast enhanced image. + * Contrast is enhanced by multiplying the pixel value with the constant + * <code>mult</code>. Brightness is enhanced by adding the constant + * <code>add</code> to the pixel value. Operation: p1 = (p0*mult)+add. + * + * @param mult multiplicative constant for contrast enhancement + * @param add additive constant for brightness enhancement + * @throws ImageOpException + */ + public void enhance(double mult, double add) throws ImageOpException; - /** Crops and scales the current image. - * - * The current image is cropped to a rectangle of <code>width</code>, - * <code>height</code> at position <code>x_off</code>, <code>y_off</code>. The - * resulting image is scaled by the factor <code>scale</code> using the - * interpolation quality <code>qual</code> (0=worst). - * - * @param x_off x offset of the crop rectangle in pixel. - * @param y_off y offset of the crop rectangle in pixel. - * @param width width of the crop rectangle in pixel. - * @param height height of the crop rectangle in pixel. - * @param scale scaling factor. - * @param qual interpolation quality (0=worst). - * @throws ImageOpException exception thrown on any error. - */ - public void cropAndScale( - int x_off, int y_off, - int width, int height, - float scale, int qual) throws ImageOpException; + /** + * Returns the interpolation quality. + * @return int + */ + public int getQuality(); + + /** + * Sets the interpolation quality. + * @param quality The quality to set + */ + public void setQuality(int quality); + }
--- a/servlet/src/digilib/image/DocuImageImpl.java Fri Jan 24 22:13:49 2003 +0100 +++ b/servlet/src/digilib/image/DocuImageImpl.java Mon Feb 03 16:04:53 2003 +0100 @@ -20,61 +20,105 @@ package digilib.image; -import java.io.*; -import javax.servlet.ServletResponse; - -import digilib.*; -import digilib.io.*; +import digilib.Utils; /** Simple abstract implementation of the <code>DocuImage</code> interface. * * This implementation provides basic functionality for the utility methods like * <code>SetUtils</code>, and <code>getKnownFileTypes</code>. Image methods like * <code>loadImage</code>, <code>writeImage</code>, <code>getWidth</code>, - * <code>getHeight</code> and <code>cropAndScale</code> must be implemented by - * derived classes. + * <code>getHeight</code>, <code>crop</code> and <code>scale</code> must be + * implemented by derived classes. */ public abstract class DocuImageImpl implements DocuImage { - /** Internal utils object. */ - protected Utils util = null; + /** Internal utils object. */ + protected Utils util = null; + + /** Interpolation quality. */ + protected int quality = 0; - /** Default constructor. */ - public DocuImageImpl() { - util = new Utils(); - } + /** Default constructor. */ + public DocuImageImpl() { + util = new Utils(); + } + + /** Contructor taking an utils object. + * + * @param u Utils object. + */ + public DocuImageImpl(Utils u) { + util = u; + } - /** Contructor taking an utils object. - * - * @param u Utils object. - */ - public DocuImageImpl(Utils u) { - util = u; - } + /** Set local Utils object. + * + * @param u Utils object. + */ + public void setUtils(Utils u) { + util = u; + } + + /** Internal knownFileTypes. */ + protected String[] knownFileTypes = { "jpg", "png", "gif", "tiff" }; + + /** Returns the list of image file types known to the DocuImage implementation. + * + * @return List of image file types. Strings are standard file extensions. + */ + public String[] getKnownFileTypes() { + return knownFileTypes; + } - /** Set local Utils object. - * - * @param u Utils object. - */ - public void setUtils(Utils u) { - util = u; - } + /** + * Returns the quality. + * @return int + */ + public int getQuality() { + return quality; + } - /** Internal knownFileTypes. */ - protected String[] knownFileTypes = {"jpg", "png", "gif", "tiff"}; + /** + * Sets the quality. + * @param quality The quality to set + */ + public void setQuality(int quality) { + this.quality = quality; + } - /** Returns the list of image file types known to the DocuImage implementation. - * - * @return List of image file types. Strings are standard file extensions. - */ - public String[] getKnownFileTypes() { - return knownFileTypes; - } + /** Crop and scale the current image. + * + * The current image is cropped to a rectangle of width, height at position + * x_off, y_off. The resulting image is scaled by the factor scale using the + * interpolation quality qual (0=worst). + * + * @param x_off X offset of the crop rectangle in pixel. + * @param y_off Y offset of the crop rectangle in pixel. + * @param width Width of the crop rectangle in pixel. + * @param height Height of the crop rectangle in pixel. + * @param scale Scaling factor. + * @param qual Interpolation quality (0=worst). + * @throws ImageOpException Exception thrown on any error. + */ + public void cropAndScale( + int x_off, int y_off, int width, int height, double scale, int qual) + throws ImageOpException { + setQuality(qual); + crop(x_off, y_off, width, height); + scale(scale); + } + + public void rotate(double angle) throws ImageOpException { + // just a do-nothing implementation + } - public abstract void loadImage(File f) throws FileOpException; - public abstract void writeImage(String mt, ServletResponse res) throws FileOpException; - public abstract int getWidth(); - public abstract int getHeight(); - public abstract void cropAndScale(int x_off, int y_off, int width, int height, float scale, int qual) throws ImageOpException; + public void mirror(double angle) throws ImageOpException { + // just a do-nothing implementation + } + + public void enhance(double mult, double add) throws ImageOpException { + // just a do-nothing implementation + } + }
--- a/servlet/src/digilib/image/ImageLoaderDocuImage.java Fri Jan 24 22:13:49 2003 +0100 +++ b/servlet/src/digilib/image/ImageLoaderDocuImage.java Mon Feb 03 16:04:53 2003 +0100 @@ -25,9 +25,9 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.io.OutputStream; import javax.imageio.ImageIO; -import javax.servlet.ServletResponse; import digilib.Utils; import digilib.io.FileOpException; @@ -35,128 +35,122 @@ /** Implementation of DocuImage using the ImageLoader API of Java 1.4 and Java2D. */ public class ImageLoaderDocuImage extends DocuImageImpl { - private BufferedImage img; + private BufferedImage img; + + private int scaleInt; + + public ImageLoaderDocuImage() { + } + + public ImageLoaderDocuImage(Utils u) { + util = u; + } - public ImageLoaderDocuImage() { - } - - public ImageLoaderDocuImage(Utils u) { - util = u; - } + /** + * load image file + */ + public void loadImage(File f) throws FileOpException { + util.dprintln(10, "loadImage!"); + System.gc(); + try { + img = ImageIO.read(f); + if (img == null) { + util.dprintln(3, "ERROR(loadImage): unable to load file"); + throw new FileOpException("Unable to load File!"); + } + } catch (IOException e) { + throw new FileOpException("Error reading image."); + } + } - /** - * load image file - */ - public void loadImage(File f) throws FileOpException { - util.dprintln(10, "loadImage!"); - System.gc(); - try { - for (int i = 0; i < ImageIO.getReaderFormatNames().length; i++) { - System.out.println("ImageLoader reader:"+ImageIO.getReaderFormatNames()[i]); - } - for (int i = 0; i < ImageIO.getWriterFormatNames().length; i++) { - System.out.println("ImageLoader writer:"+ImageIO.getWriterFormatNames()[i]); - } - img = ImageIO.read(f); - if (img == null) { - util.dprintln(3, "ERROR(loadImage): unable to load file"); - throw new FileOpException("Unable to load File!"); - } - } - catch (IOException e) { - throw new FileOpException("Error reading image."); - } - } + /** + * write image of type mt to Stream + */ + public void writeImage(String mt, OutputStream ostream) + throws FileOpException { + util.dprintln(10, "writeImage!"); + try { + // setup output + String type = "png"; + if (mt == "image/jpeg") { + type = "jpeg"; + } else if (mt == "image/png") { + type = "png"; + } else { + // unknown mime type + util.dprintln(2, "ERROR(writeImage): Unknown mime type " + mt); + throw new FileOpException("Unknown mime type: " + mt); + } + // render output + if (ImageIO.write(img, type, ostream)) { + // writing was OK + return; + } else { + throw new FileOpException("Error writing image: Unknown image format!"); + } + } catch (IOException e) { + // e.printStackTrace(); + throw new FileOpException("Error writing image."); + } + } - /** - * write image of type mt to Stream - */ - public void writeImage(String mt, ServletResponse res) - throws FileOpException { - util.dprintln(10, "writeImage!"); - try { - // setup output - String type = "png"; - if (mt == "image/jpeg") { - type = "jpeg"; - } else if (mt == "image/png") { - type = "png"; - } else { - // unknown mime type - util.dprintln(2, "ERROR(writeImage): Unknown mime type "+mt); - throw new FileOpException("Unknown mime type: "+mt); - } - res.setContentType(mt); - // render output - if (ImageIO.write(img, type, res.getOutputStream())) { - // writing was OK - return; - } else { - throw new FileOpException("Error writing image: Unknown image format!"); - } - } catch (IOException e) { - // e.printStackTrace(); - throw new FileOpException("Error writing image."); - } - } + public int getWidth() { + if (img != null) { + return img.getWidth(); + } + return 0; + } + + public int getHeight() { + if (img != null) { + return img.getHeight(); + } + return 0; + } - public int getWidth() { - if (img != null) { - return img.getWidth(); - } - return 0; - } + public void scale(double scale) throws ImageOpException { + // setup scale + AffineTransformOp scaleOp = + new AffineTransformOp( + AffineTransform.getScaleInstance(scale, scale), + scaleInt); + BufferedImage scaledImg = scaleOp.filter(img, null); + + if (scaledImg == null) { + util.dprintln(2, "ERROR(cropAndScale): error in scale"); + throw new ImageOpException("Unable to scale"); + } + img = scaledImg; + } - public int getHeight() { - if (img != null) { - return img.getHeight(); - } - return 0; - } + 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); - /** - * crop and scale image - * take rectangle width,height at position x_off,y_off - * and scale by scale - */ - public void cropAndScale(int x_off, int y_off, int width, int height, - float scale, int qual) throws ImageOpException { - util.dprintln(10, "cropAndScale!"); - - int scaleInt = 0; - // setup interpolation quality - if (qual > 0) { - util.dprintln(4, "quality q1"); - scaleInt = AffineTransformOp.TYPE_BILINEAR; - } else { - util.dprintln(4, "quality q0"); - scaleInt = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; - } + util.dprintln( + 3, + "CROP:" + croppedImg.getWidth() + "x" + croppedImg.getHeight()); + //DEBUG + // util.dprintln(2, " time "+(System.currentTimeMillis()-startTime)+"ms"); - // setup Crop - BufferedImage croppedImg = img.getSubimage(x_off, y_off, width, height); - - img = null; // free img - 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"); - } + if (croppedImg == null) { + util.dprintln(2, "ERROR(cropAndScale): error in crop"); + throw new ImageOpException("Unable to crop"); + } + img = croppedImg; + } - // setup scale - AffineTransformOp scaleOp = new AffineTransformOp( - AffineTransform.getScaleInstance(scale, scale), - scaleInt); - BufferedImage scaledImg = scaleOp.filter(croppedImg, null); - croppedImg = null; // free opCrop - - if (scaledImg == null) { - util.dprintln(2, "ERROR(cropAndScale): error in scale"); - throw new ImageOpException("Unable to scale"); - } - img = scaledImg; - } + public void setQuality(int qual) { + quality = qual; + // setup interpolation quality + if (qual > 0) { + util.dprintln(4, "quality q1"); + scaleInt = AffineTransformOp.TYPE_BILINEAR; + } else { + util.dprintln(4, "quality q0"); + scaleInt = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; + } + } }
--- a/servlet/src/digilib/image/JAIDocuImage.java Fri Jan 24 22:13:49 2003 +0100 +++ b/servlet/src/digilib/image/JAIDocuImage.java Mon Feb 03 16:04:53 2003 +0100 @@ -20,14 +20,16 @@ package digilib.image; +import java.awt.RenderingHints; import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import java.io.File; import java.io.IOException; +import java.io.OutputStream; -import javax.media.jai.Interpolation; -import javax.media.jai.JAI; -import javax.servlet.ServletResponse; +import javax.media.jai.*; +import javax.media.jai.operator.TransposeDescriptor; +import javax.media.jai.operator.TransposeType; import digilib.Utils; import digilib.io.FileOpException; @@ -35,7 +37,11 @@ /** A DocuImage implementation using Java Advanced Imaging Library. */ public class JAIDocuImage extends DocuImageImpl { - private RenderedImage img; + protected RenderedImage img; + protected Interpolation interpol = null; + + // epsilon for float comparisons + public final double epsilon = 1e-5; /** Default constructor. */ public JAIDocuImage() { @@ -48,11 +54,7 @@ util = u; } - /** Load an image file into the Object. - * - * @param f Image File. - * @throws FileOpException Exception thrown if any error occurs. - */ + /* Load an image file into the Object. */ public void loadImage(File f) throws FileOpException { System.gc(); img = JAI.create("fileload", f.getAbsolutePath()); @@ -62,23 +64,14 @@ } } - /** Write the current image to a ServletResponse. - * - * The image is encoded to the mime-type mt and sent to the output stream of the - * ServletResponse res. - * - * Currently only mime-types "image/jpeg" and "image/png" are allowed. - * @param mt mime-type of the image to be sent. - * @param res ServletResponse where the image is sent. - * @throws FileOpException Exception thrown on any error. - */ - public void writeImage(String mt, ServletResponse res) + /* Write the current image to an OutputStream. */ + public void writeImage(String mt, OutputStream ostream) throws FileOpException { try { // setup output ParameterBlock pb3 = new ParameterBlock(); pb3.addSource(img); - pb3.add(res.getOutputStream()); + pb3.add(ostream); if (mt == "image/jpeg") { pb3.add("JPEG"); } else if (mt == "image/png") { @@ -88,7 +81,6 @@ util.dprintln(2, "ERROR(writeImage): Unknown mime type " + mt); throw new FileOpException("Unknown mime type: " + mt); } - res.setContentType(mt); // render output JAI.create("encode", pb3); @@ -97,6 +89,24 @@ } } + /* Real setQuality implementation. + * Creates the correct Interpolation. + */ + public void setQuality(int qual) { + quality = qual; + // setup interpolation quality + if (qual > 1) { + util.dprintln(4, "quality q2"); + interpol = Interpolation.getInstance(Interpolation.INTERP_BICUBIC); + } else if (qual == 1) { + util.dprintln(4, "quality q1"); + interpol = Interpolation.getInstance(Interpolation.INTERP_BILINEAR); + } else { + util.dprintln(4, "quality q0"); + interpol = Interpolation.getInstance(Interpolation.INTERP_NEAREST); + } + } + /** The width of the curent image in pixel. * @return Image width in pixels. */ @@ -117,94 +127,230 @@ return 0; } - /** Crop and scale the current image. - * - * The current image is cropped to a rectangle of width, height at position - * x_off, y_off. The resulting image is scaled by the factor scale using the - * interpolation quality qual (0=worst). - * - * @param x_off X offset of the crop rectangle in pixel. - * @param y_off Y offset of the crop rectangle in pixel. - * @param width Width of the crop rectangle in pixel. - * @param height Height of the crop rectangle in pixel. - * @param scale Scaling factor. - * @param qual Interpolation quality (0=worst). - * @throws ImageOpException Exception thrown on any error. - */ - public void cropAndScale( - int x_off, - int y_off, - int width, - int height, - float scale, - int qual) - throws ImageOpException { + /* scales the current image */ + public void scale(double scale) throws ImageOpException { + float sf = (float)scale; + // setup scale + ParameterBlock param = new ParameterBlock(); + param.addSource(img); + param.add(sf); + param.add(sf); + param.add(0f); + param.add(0f); + param.add(interpol); + // hint with border extender + RenderingHints hint = + new RenderingHints( + JAI.KEY_BORDER_EXTENDER, + BorderExtender.createInstance(BorderExtender.BORDER_COPY)); + + RenderedImage scaledImg = JAI.create("scale", param, hint); - Interpolation scaleInt = null; - // setup interpolation quality - if (qual > 1) { - util.dprintln(4, "quality q2"); - scaleInt = Interpolation.getInstance(Interpolation.INTERP_BICUBIC); - } else if (qual == 1) { - util.dprintln(4, "quality q1"); - scaleInt = Interpolation.getInstance(Interpolation.INTERP_BILINEAR); - } else { - util.dprintln(4, "quality q0"); - scaleInt = Interpolation.getInstance(Interpolation.INTERP_NEAREST); + //DEBUG + util.dprintln( + 3, + "SCALE: " + + scale + + " ->" + + scaledImg.getWidth() + + "x" + + scaledImg.getHeight()); + + if (scaledImg == null) { + util.dprintln(2, "ERROR(scale): error in scale"); + throw new ImageOpException("Unable to scale"); } + img = scaledImg; + } + /* crops the current image */ + public void crop(int x_off, int y_off, int width, int height) + throws ImageOpException { // setup Crop - ParameterBlock pb1 = new ParameterBlock(); - pb1.addSource(img); - pb1.add((float) x_off); - pb1.add((float) y_off); - pb1.add((float) width); - pb1.add((float) height); - RenderedImage croppedImg = JAI.create("crop", pb1); - img = null; // free img + ParameterBlock param = new ParameterBlock(); + param.addSource(img); + param.add((float) x_off); + param.add((float) y_off); + param.add((float) width); + param.add((float) height); + RenderedImage croppedImg = JAI.create("crop", param); util.dprintln( 3, - "CROP:" + croppedImg.getWidth() + "x" + croppedImg.getHeight()); + "CROP: " + + x_off + + "," + + y_off + + ", " + + width + + "," + + height + + " ->" + + croppedImg.getWidth() + + "x" + + croppedImg.getHeight()); //DEBUG if (croppedImg == null) { - util.dprintln(2, "ERROR(cropAndScale): error in crop"); + util.dprintln(2, "ERROR(crop): error in crop"); throw new ImageOpException("Unable to crop"); } + img = croppedImg; + } + + /* rotates the current image */ + public void rotate(double angle) throws ImageOpException { + RenderedImage rotImg; + // convert degrees to radians + double rangle = Math.toRadians(angle); + // rotate about the image center + double xoff = img.getWidth() / 2; + double yoff = img.getHeight() / 2; + + // optimize rotation by right angles + TransposeType rotOp = null; + if (Math.abs(angle - 0) < epsilon) { + // 0 degree + return; + } else if (Math.abs(angle - 90) < epsilon) { + // 90 degree + rotOp = TransposeDescriptor.ROTATE_90; + } else if (Math.abs(angle - 180) < epsilon) { + // 180 degree + rotOp = TransposeDescriptor.ROTATE_180; + } else if (Math.abs(angle - 270) < epsilon) { + // 270 degree + rotOp = TransposeDescriptor.ROTATE_270; + } else if (Math.abs(angle - 360) < epsilon) { + // 360 degree + return; + } + if (rotOp != null) { + // use Transpose operation + ParameterBlock pb = new ParameterBlock(); + pb.addSource(img); + pb.add(rotOp); + rotImg = JAI.create("transpose", pb); + } else { + // setup "normal" rotation + ParameterBlock param = new ParameterBlock(); + param.addSource(img); + param.add((float) xoff); + param.add((float) yoff); + param.add((float) rangle); + param.add(interpol); + // hint with border extender + RenderingHints hint = + new RenderingHints( + JAI.KEY_BORDER_EXTENDER, + BorderExtender.createInstance(BorderExtender.BORDER_COPY)); + + rotImg = JAI.create("rotate", param, hint); + } - // setup scale - RenderedImage scaledImg; + util.dprintln( + 3, + "ROTATE: " + + xoff + + "," + + yoff + + ", " + + angle + + " (" + + rangle + + ")" + + " ->" + + rotImg.getWidth() + + "x" + + rotImg.getHeight()); + //DEBUG - if (scale != 1f) { - ParameterBlock pb2 = new ParameterBlock(); - pb2.addSource(croppedImg); - pb2.add(scale); - pb2.add(scale); - pb2.add(0f); - pb2.add(0f); - pb2.add(scaleInt); - // the following is nice but way too slow... - //if (opCrop.getColorModel().getPixelSize() < 8) { - // change color model if necessary - // util.dprintln("converting color model..."); - // BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY); - // ImageLayout lay = new ImageLayout(bi); - // rh = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, lay); - //} - scaledImg = JAI.create("scale", pb2); - croppedImg = null; // free opCrop - } else { - // no scaling - scaledImg = croppedImg; + if (rotImg == null) { + util.dprintln(2, "ERROR: error in rotate"); + throw new ImageOpException("Unable to rotate"); } - - if (scaledImg == null) { - util.dprintln(2, "ERROR(cropAndScale): error in scale"); - throw new ImageOpException("Unable to scale"); - } - - img = scaledImg; + img = rotImg; } + /* mirrors the current image + * works only horizontal and vertical + */ + public void mirror(double angle) throws ImageOpException { + RenderedImage mirImg; + + // only mirroring by right angles + TransposeType rotOp = null; + if (Math.abs(angle - 0) < epsilon) { + // 0 degree + rotOp = TransposeDescriptor.FLIP_HORIZONTAL; + } else if (Math.abs(angle - 90) < epsilon) { + // 90 degree + rotOp = TransposeDescriptor.FLIP_VERTICAL; + } else if (Math.abs(angle - 180) < epsilon) { + // 180 degree + rotOp = TransposeDescriptor.FLIP_HORIZONTAL; + } else if (Math.abs(angle - 270) < epsilon) { + // 270 degree + rotOp = TransposeDescriptor.FLIP_VERTICAL; + } else if (Math.abs(angle - 360) < epsilon) { + // 360 degree + rotOp = TransposeDescriptor.FLIP_HORIZONTAL; + } + if (rotOp != null) { + // use Transpose operation + ParameterBlock param = new ParameterBlock(); + param.addSource(img); + param.add(rotOp); + mirImg = JAI.create("transpose", param); + + util.dprintln( + 3, + "MIRROR: " + + angle + + " ->" + + mirImg.getWidth() + + "x" + + mirImg.getHeight()); + //DEBUG + + if (mirImg == null) { + util.dprintln(2, "ERROR(mirror): error in mirror"); + throw new ImageOpException("Unable to mirror"); + } + img = mirImg; + } + } + + /* contrast and brightness enhancement */ + public void enhance(double mult, double add) throws ImageOpException { + RenderedImage enhImg; + double[] ma = { mult }; + double[] aa = { add }; + // use Rescale operation + ParameterBlock param = new ParameterBlock(); + param.addSource(img); + param.add(ma); + param.add(aa); + enhImg = JAI.create("rescale", param); + + util.dprintln( + 3, + "ENHANCE: *" + + mult + + ", +" + + add + + " ->" + + enhImg.getWidth() + + "x" + + enhImg.getHeight()); + //DEBUG + + if (enhImg == null) { + util.dprintln(2, "ERROR(enhance): error in enhance"); + throw new ImageOpException("Unable to enhance"); + } + img = enhImg; + } + + }
--- a/servlet/src/digilib/image/JAIImageLoaderDocuImage.java Fri Jan 24 22:13:49 2003 +0100 +++ b/servlet/src/digilib/image/JAIImageLoaderDocuImage.java Mon Feb 03 16:04:53 2003 +0100 @@ -20,40 +20,22 @@ package digilib.image; -import java.awt.image.RenderedImage; import java.awt.image.renderable.ParameterBlock; import java.io.File; import java.io.IOException; +import java.io.OutputStream; -import javax.media.jai.Interpolation; import javax.media.jai.JAI; -import javax.servlet.ServletResponse; -import digilib.Utils; import digilib.io.FileOpException; /** DocuImage implementation using the Java Advanced Imaging API and the ImageLoader * API of Java 1.4. */ -public class JAIImageLoaderDocuImage extends DocuImageImpl { - - private RenderedImage img; - - /** Default constructor. */ - public JAIImageLoaderDocuImage() { - } +public class JAIImageLoaderDocuImage extends JAIDocuImage { - /** Constructor using an utils object. - * @param u Utils object. - */ - public JAIImageLoaderDocuImage(Utils u) { - util = u; - } - /** Load an image file into the Object. - * @param f Image file. - * @throws FileOpException Exception thrown on any error. - */ + /* Load an image file into the Object. */ public void loadImage(File f) throws FileOpException { System.gc(); img = JAI.create("ImageRead", f.getAbsolutePath()); @@ -63,23 +45,14 @@ } } - /** Write the current image to a ServletResponse. - * - * The image is encoded to the mime-type mt and sent to the output stream of the - * ServletResponse res. - * - * Currently only mime-types "image/jpeg" and "image/png" are allowed. - * @param mt mime-type of the image to be sent. - * @param res ServletResponse where the image is sent. - * @throws FileOpException Exception thrown on any error. - */ - public void writeImage(String mt, ServletResponse res) + /* Write the current image to an OutputStream. */ + public void writeImage(String mt, OutputStream ostream) throws FileOpException { try { // setup output ParameterBlock pb3 = new ParameterBlock(); pb3.addSource(img); - pb3.add(res.getOutputStream()); + pb3.add(ostream); if (mt == "image/jpeg") { pb3.add("JPEG"); } else if (mt == "image/png") { @@ -89,7 +62,6 @@ util.dprintln(2, "ERROR(writeImage): Unknown mime type " + mt); throw new FileOpException("Unknown mime type: " + mt); } - res.setContentType(mt); // render output JAI.create("ImageWrite", pb3); @@ -98,111 +70,4 @@ } } - /** The width of the curent image in pixel. - * @return Image width in pixels. - */ - public int getWidth() { - if (img != null) { - return img.getWidth(); - } - return 0; - } - - /** The height of the curent image in pixel. - * @return Image height in pixels. - */ - public int getHeight() { - if (img != null) { - return img.getHeight(); - } - return 0; - } - - /** Crop and scale the current image. - * - * The current image is cropped to a rectangle of width, height at position - * x_off, y_off. The resulting image is scaled by the factor scale using the - * interpolation quality qual (0=worst). - * @param x_off X offset of the crop rectangle in pixel. - * @param y_off Y offset of the crop rectangle in pixel. - * @param width Width of the crop rectangle in pixel. - * @param height Height of the crop rectangle in pixel. - * @param scale Scaling factor. - * @param qual Interpolation quality (0=worst). - * @throws ImageOpException Exception thrown on any error. - */ - public void cropAndScale( - int x_off, - int y_off, - int width, - int height, - float scale, - int qual) - throws ImageOpException { - - Interpolation scaleInt = null; - // setup interpolation quality - if (qual > 1) { - util.dprintln(4, "quality q2"); - scaleInt = Interpolation.getInstance(Interpolation.INTERP_BICUBIC); - } else if (qual == 1) { - util.dprintln(4, "quality q1"); - scaleInt = Interpolation.getInstance(Interpolation.INTERP_BILINEAR); - } else { - util.dprintln(4, "quality q0"); - scaleInt = Interpolation.getInstance(Interpolation.INTERP_NEAREST); - } - - // setup Crop - ParameterBlock pb1 = new ParameterBlock(); - pb1.addSource(img); - pb1.add((float) x_off); - pb1.add((float) y_off); - pb1.add((float) width); - pb1.add((float) height); - RenderedImage croppedImg = JAI.create("crop", pb1); - - util.dprintln( - 3, - "CROP:" + croppedImg.getWidth() + "x" + croppedImg.getHeight()); - //DEBUG - - if (croppedImg == null) { - util.dprintln(2, "ERROR(cropAndScale): error in crop"); - throw new ImageOpException("Unable to crop"); - } - - RenderedImage scaledImg; - - if (scale != 1f) { - // setup scale - ParameterBlock pb2 = new ParameterBlock(); - pb2.addSource(croppedImg); - pb2.add(scale); - pb2.add(scale); - pb2.add(0f); - pb2.add(0f); - pb2.add(scaleInt); - // the following is nice but way too slow... - //if (opCrop.getColorModel().getPixelSize() < 8) { - // change color model if necessary - // util.dprintln("converting color model..."); - // BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY); - // ImageLayout lay = new ImageLayout(bi); - // rh = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, lay); - //} - scaledImg = JAI.create("scale", pb2); - } else { - // no scaling - scaledImg = croppedImg; - } - - if (scaledImg == null) { - util.dprintln(2, "ERROR(cropAndScale): error in scale"); - throw new ImageOpException("Unable to scale"); - } - - img = scaledImg; - } - }
--- a/servlet/src/digilib/image/JIMIDocuImage.java Fri Jan 24 22:13:49 2003 +0100 +++ b/servlet/src/digilib/image/JIMIDocuImage.java Mon Feb 03 16:04:53 2003 +0100 @@ -20,125 +20,121 @@ package digilib.image; -import javax.servlet.*; -import javax.servlet.http.*; -import java.io.*; -import java.util.*; +import java.awt.image.FilteredImageSource; +import java.awt.image.ImageFilter; +import java.awt.image.ImageProducer; +import java.io.File; +import java.io.OutputStream; -import com.sun.jimi.core.*; -import com.sun.jimi.core.raster.*; -import com.sun.jimi.core.filters.*; +import com.sun.jimi.core.Jimi; +import com.sun.jimi.core.JimiException; +import com.sun.jimi.core.filters.AreaAverageScaleFilter; +import com.sun.jimi.core.filters.ReplicatingScaleFilter; +import com.sun.jimi.core.raster.JimiRasterImage; -import java.awt.*; -import java.awt.image.*; - -import digilib.*; -import digilib.io.*; - +import digilib.Utils; +import digilib.io.FileOpException; /** Implementation of DocuImage using the JIMI image Library. */ public class JIMIDocuImage extends DocuImageImpl { - private JimiRasterImage img; - private ImageProducer imgp; + private JimiRasterImage img; + private ImageProducer imgp; + private int imgWidth = 0; + private int imgHeight = 0; - public JIMIDocuImage() { - } + public JIMIDocuImage() { + } - public JIMIDocuImage(Utils u) { - util = u; - } + public JIMIDocuImage(Utils u) { + util = u; + } - /** - * load image file - */ - public void loadImage(File f) throws FileOpException { - System.gc(); - try { - img = Jimi.getRasterImage(f.toURL()); - } catch (java.net.MalformedURLException e) { - util.dprintln(3, "ERROR(loadImage): MalformedURLException"); - } catch (JimiException e) { - util.dprintln(3, "ERROR(loadImage): JIMIException"); - throw new FileOpException("Unable to load File!"+e); - } - if (img == null) { - util.dprintln(3, "ERROR(loadImage): unable to load file"); - throw new FileOpException("Unable to load File!"); - } - } + /** + * load image file + */ + public void loadImage(File f) throws FileOpException { + System.gc(); + try { + img = Jimi.getRasterImage(f.toURL()); + } catch (java.net.MalformedURLException e) { + util.dprintln(3, "ERROR(loadImage): MalformedURLException"); + } catch (JimiException e) { + util.dprintln(3, "ERROR(loadImage): JIMIException"); + throw new FileOpException("Unable to load File!" + e); + } + if (img == null) { + util.dprintln(3, "ERROR(loadImage): unable to load file"); + throw new FileOpException("Unable to load File!"); + } + imgp = img.getImageProducer(); + imgWidth = img.getWidth(); + imgHeight = img.getHeight(); + } - /** - * write image of type mt to Stream - */ - public void writeImage(String mt, ServletResponse res) - throws FileOpException { - try { - // setup output - res.setContentType(mt); - // render output - Jimi.putImage(mt, imgp, res.getOutputStream()); + /** + * write image of type mt to Stream + */ + public void writeImage(String mt, OutputStream ostream) + throws FileOpException { + try { + // render output + Jimi.putImage(mt, imgp, ostream); - } catch (JimiException e) { - throw new FileOpException("Error writing image!"+e); - } catch (IOException e) { - throw new FileOpException("Error writing image."+e); - } - } + } catch (JimiException e) { + throw new FileOpException("Error writing image!" + e); + } + } - public int getWidth() { - if (img != null) { - return img.getWidth(); - } - return 0; - } + public int getWidth() { + return imgWidth; + } + + public int getHeight() { + return imgHeight; + } + + public void scale(double scale) throws ImageOpException { - public int getHeight() { - if (img != null) { - return img.getHeight(); - } - return 0; - } - + ImageFilter scaleFilter; + int destWidth = (int) (scale * (float) imgWidth); + int destHeight = (int) (scale * (float) imgHeight); - /** - * crop and scale image - * take rectangle width,height at position x_off,y_off - * and scale by scale - */ - public void cropAndScale(int x_off, int y_off, int width, int height, - float scale, int qual) throws ImageOpException { + // setup scale and interpolation quality + if (quality > 0) { + util.dprintln(4, "quality q1"); + scaleFilter = new AreaAverageScaleFilter(destWidth, destHeight); + } else { + util.dprintln(4, "quality q0"); + scaleFilter = new ReplicatingScaleFilter(destWidth, destHeight); + } - ImageFilter scaleFilter; - int destWidth = (int)(scale * (float)width); - int destHeight = (int)(scale * (float)height); + ImageProducer scaledImg = new FilteredImageSource(imgp, scaleFilter); - // setup Crop - ImageProducer croppedImg = img.getCroppedImageProducer(x_off, y_off, width, height); - //util.dprintln(3, "CROP:"+croppedImg.getWidth()+"x"+croppedImg.getHeight()); //DEBUG + if (scaledImg == null) { + util.dprintln(2, "ERROR(cropAndScale): error in scale"); + throw new ImageOpException("Unable to scale"); + } - if (croppedImg == null) { - util.dprintln(2, "ERROR(cropAndScale): error in crop"); - throw new ImageOpException("Unable to crop"); - } + imgp = scaledImg; + imgWidth = destWidth; + imgHeight = destHeight; + } - // setup scale and interpolation quality - if (qual > 0) { - util.dprintln(4, "quality q1"); - scaleFilter = new AreaAverageScaleFilter(destWidth, destHeight); - } else { - util.dprintln(4, "quality q0"); - scaleFilter = new ReplicatingScaleFilter(destWidth, destHeight); - } + public void crop(int x_off, int y_off, int width, int height) + throws ImageOpException { + // setup Crop + ImageProducer croppedImg = + img.getCroppedImageProducer(x_off, y_off, width, height); + //util.dprintln(3, "CROP:"+croppedImg.getWidth()+"x"+croppedImg.getHeight()); //DEBUG - ImageProducer scaledImg = new FilteredImageSource(croppedImg, scaleFilter); - - if (scaledImg == null) { - util.dprintln(2, "ERROR(cropAndScale): error in scale"); - throw new ImageOpException("Unable to scale"); - } - - imgp = scaledImg; - } + if (croppedImg == null) { + util.dprintln(2, "ERROR(cropAndScale): error in crop"); + throw new ImageOpException("Unable to crop"); + } + imgp = croppedImg; + imgWidth = width; + imgHeight = height; + } }
--- a/servlet/src/digilib/servlet/DigilibRequest.java Fri Jan 24 22:13:49 2003 +0100 +++ b/servlet/src/digilib/servlet/DigilibRequest.java Mon Feb 03 16:04:53 2003 +0100 @@ -72,6 +72,13 @@ private int pt; // total number of pages (generated by sevlet) private String pt_s; private String baseURL; // base URL (from http:// to below /servlet) + private float rot; // rotation angle in degrees + private String rot_s; + private float cont; // contrast enhancement factor + private String cont_s; + private float brgt; // brightness enhancement factor + private String brgt_s; + private DocuImage image; // internal DocuImage instance for this request private ServletRequest servletRequest; // internal ServletRequest @@ -91,6 +98,11 @@ setWithRequest(request); } + /** Populate the request object with data from a ServletRequest. + * + * + * @param request + */ public void setWithRequest(ServletRequest request) { servletRequest = request; // decide if it's old-style or new-style @@ -292,6 +304,15 @@ if (mk != null) { s += "&mk=" + mk; } + if (rot_s != null) { + s += "&rot=" + rot_s; + } + if (cont_s != null) { + s += "&cont=" + cont_s; + } + if (brgt_s != null) { + s += "&brgt=" + brgt_s; + } if (pt_s != null) { s += "&pt=" + pt_s; } @@ -368,6 +389,18 @@ if (s != null) { setDh(s); } + s = request.getParameter("rot"); + if (s != null) { + setRot(s); + } + s = request.getParameter("cont"); + if (s != null) { + setCont(s); + } + s = request.getParameter("brgt"); + if (s != null) { + setBrgt(s); + } s = request.getParameter("pt"); if (s != null) { setPt(s); @@ -402,6 +435,12 @@ mk = null; // marks pt = 0; // total number of pages pt_s = null; + rot = 0; + rot_s = null; + cont = 0; + cont_s = null; + brgt = 0; + brgt_s = null; baseURL = null; image = null; servletRequest = null; @@ -431,6 +470,12 @@ mk = ""; // marks pt = 0; // total number of pages pt_s = null; + rot = 0; + rot_s = null; + cont = 0; + cont_s = null; + brgt = 0; + brgt_s = null; baseURL = null; image = null; servletRequest = null; @@ -822,4 +867,81 @@ this.servletRequest = servletRequest; } + /** + * Returns the rot. + * @return float + */ + public float getRot() { + return rot; + } + + /** + * Sets the rot. + * @param rot The rot to set + */ + public void setRot(float rot) { + this.rot = rot; + rot_s = Float.toString(rot); + } + public void setRot(String rot) { + try { + float f = Float.parseFloat(rot); + this.rot = f; + this.rot_s = rot; + } catch (Exception e) { + //util.dprintln(4, "trytoGetParam(int) failed on param "+s); + } + } + + /** + * Returns the rot. + * @return float + */ + public float getCont() { + return cont; + } + + /** + * Sets the rot. + * @param rot The rot to set + */ + public void setCont(float cont) { + this.cont = cont; + rot_s = Float.toString(cont); + } + public void setCont(String cont) { + try { + float f = Float.parseFloat(cont); + this.cont = f; + this.cont_s = cont; + } catch (Exception e) { + //util.dprintln(4, "trytoGetParam(int) failed on param "+s); + } + } + + /** + * Returns the brgt. + * @return float + */ + public float getBrgt() { + return brgt; + } + + /** + * Sets the brgt. + * @param brgt The brgt to set + */ + public void setBrgt(float brgt) { + this.brgt = brgt; + brgt_s = Float.toString(brgt); + } + public void setBrgt(String brgt) { + try { + float f = Float.parseFloat(brgt); + this.brgt = f; + this.brgt_s = brgt; + } catch (Exception e) { + //util.dprintln(4, "trytoGetParam(int) failed on param "+s); + } + } }
--- a/servlet/src/digilib/servlet/DocumentBean.java Fri Jan 24 22:13:49 2003 +0100 +++ b/servlet/src/digilib/servlet/DocumentBean.java Mon Feb 03 16:04:53 2003 +0100 @@ -130,6 +130,10 @@ HttpServletResponse response) throws Exception { util.dprintln(10, "doAuthentication"); + if (! useAuthentication) { + // shortcut if no authentication + return true; + } // check if we are already authenticated if (((HttpServletRequest) request.getServletRequest()).getRemoteUser() == null) {
--- a/servlet/src/digilib/servlet/Scaler.java Fri Jan 24 22:13:49 2003 +0100 +++ b/servlet/src/digilib/servlet/Scaler.java Mon Feb 03 16:04:53 2003 +0100 @@ -20,15 +20,27 @@ package digilib.servlet; -import javax.servlet.*; -import javax.servlet.http.*; -import java.io.*; -import java.util.*; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.io.File; +import java.io.IOException; +import java.util.List; -import digilib.*; -import digilib.io.*; -import digilib.image.*; -import digilib.auth.*; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import digilib.Utils; +import digilib.auth.AuthOpException; +import digilib.auth.AuthOps; +import digilib.image.DocuImage; +import digilib.image.ImageOpException; +import digilib.io.FileOpException; +import digilib.io.FileOps; //import tilecachetool.*; @@ -40,8 +52,8 @@ public class Scaler extends HttpServlet { // digilib servlet version (for all components) - public static final String dlVersion = "1.5b"; - + public static final String dlVersion = "1.6b"; + // Utils instance with debuglevel Utils util; // FileOps instance @@ -103,9 +115,7 @@ // set with request parameters dlReq.setWithRequest(request); // add DigilibRequest to ServletRequest - request.setAttribute( - "digilib.servlet.request", - dlReq); + request.setAttribute("digilib.servlet.request", dlReq); // do the processing processRequest(request, response); } @@ -121,9 +131,7 @@ // set with request parameters dlReq.setWithRequest(request); // add DigilibRequest to ServletRequest - request.setAttribute( - "digilib.servlet.request", - dlReq); + request.setAttribute("digilib.servlet.request", dlReq); // do the processing processRequest(request, response); } @@ -155,6 +163,10 @@ int scaleQual = 0; // send html error message (or image file) boolean errorMsgHtml = false; + // mirror the image + boolean doMirror = false; + // angle of mirror axis + double mirrorAngle = 0; /* * request parameters @@ -168,15 +180,21 @@ // destination image height int paramDH = dlRequest.getDh(); // relative area x_offset (0..1) - float paramWX = dlRequest.getWx(); + double paramWX = dlRequest.getWx(); // relative area y_offset - float paramWY = dlRequest.getWy(); + double paramWY = dlRequest.getWy(); // relative area width (0..1) - float paramWW = dlRequest.getWw(); + double paramWW = dlRequest.getWw(); // relative area height - float paramWH = dlRequest.getWh(); + double paramWH = dlRequest.getWh(); // scale factor (additional to dw/width, dh/height) - float paramWS = dlRequest.getWs(); + double paramWS = dlRequest.getWs(); + // rotation angle + double paramROT = dlRequest.getRot(); + // contrast enhancement + double paramCONT = dlRequest.getCont(); + // brightness enhancement + double paramBRGT = dlRequest.getBrgt(); /* operation mode: "fit": always fit to page, * "clip": send original resolution cropped, "file": send whole file (if @@ -219,6 +237,14 @@ } else if (dlRequest.isOption("hires")) { preScaledFirst = false; } + // operation mode: "hmir": mirror horizontally, "vmir": mirror vertically + if (dlRequest.isOption("hmir")) { + doMirror = true; + mirrorAngle = 0; + } else if (dlRequest.isOption("vmir")) { + doMirror = true; + mirrorAngle = 90; + } //"big" try for all file/image actions try { @@ -228,10 +254,9 @@ if (docuImage == null) { throw new ImageOpException("Unable to load DocuImage class!"); } - //DocuImage docuImage = new JAIDocuImage(util); - //DocuImage docuImage = new JIMIDocuImage(util); - //DocuImage docuImage = new ImageLoaderDocuImage(util); - //DocuImage docuImage = new JAIImageLoaderDocuImage(util); + + // set interpolation quality + docuImage.setQuality(scaleQual); /* * find the file to load/send @@ -243,7 +268,7 @@ if ((paramWW < 1f) || (paramWH < 1f)) { preScaledFirst = false; } - + /* * check permissions */ @@ -312,7 +337,7 @@ * crop and scale the image */ - // get size + // get image size int imgWidth = docuImage.getWidth(); int imgHeight = docuImage.getHeight(); @@ -321,14 +346,30 @@ 2, "time " + (System.currentTimeMillis() - startTime) + "ms"); + // coordinates using Java2D + // image size + Rectangle2D imgBounds = new Rectangle2D.Double(0, 0, imgWidth, imgHeight); + // user window area in 4-point form (ul, ur, ll, lr) + Point2D[] userAreaC = { + new Point2D.Double(paramWX, paramWY), + new Point2D.Double(paramWX + paramWW, paramWY), + new Point2D.Double(paramWX, paramWY + paramWH), + new Point2D.Double(paramWX + paramWW, paramWY + paramWH) + }; + // transformation from relative [0,1] to image coordinates. + AffineTransform imgTrafo = new AffineTransform(); + imgTrafo.scale(imgWidth, imgHeight); + // rotate coordinates + //imgTrafo.rotate(Math.toRadians(-paramROT)); + // coordinates and scaling - float areaXoff; - float areaYoff; - float areaWidth; - float areaHeight; - float scaleX; - float scaleY; - float scaleXY; + double areaXoff; + double areaYoff; + double areaWidth; + double areaHeight; + double scaleX; + double scaleY; + double scaleXY; if (scaleToFit) { // calculate absolute from relative coordinates @@ -370,8 +411,44 @@ + "x" + areaHeight); + // Java2D + Point2D[] imgAreaC = { null, null, null, null }; + + imgTrafo.transform(userAreaC, 0, imgAreaC, 0, 4); + areaXoff = imgAreaC[0].getX(); + areaYoff = imgAreaC[0].getY(); + areaWidth = imgAreaC[0].distance(imgAreaC[1]); + areaHeight = imgAreaC[0].distance(imgAreaC[2]); + Rectangle2D imgArea = + new Rectangle2D.Double( + areaXoff, + areaYoff, + areaWidth, + areaHeight); + // calculate scaling factors + scaleX = paramDW / areaWidth * paramWS; + scaleY = paramDH / areaHeight * paramWS; + scaleXY = (scaleX > scaleY) ? scaleY : scaleX; + + util.dprintln( + 1, + "Scale " + + scaleXY + + "(" + + scaleX + + "," + + scaleY + + ") on " + + areaXoff + + "," + + areaYoff + + " " + + areaWidth + + "x" + + areaHeight); + // clip area at the image border - areaWidth = + /* areaWidth = (areaXoff + areaWidth > imgWidth) ? imgWidth - areaXoff : areaWidth; @@ -379,6 +456,10 @@ (areaYoff + areaHeight > imgHeight) ? imgHeight - areaYoff : areaHeight; + */ + imgArea = imgArea.createIntersection(imgBounds); + areaWidth = imgArea.getWidth(); + areaHeight = imgArea.getHeight(); util.dprintln( 2, @@ -401,13 +482,29 @@ } // crop and scale image - docuImage.cropAndScale( + docuImage.crop( (int) areaXoff, (int) areaYoff, (int) areaWidth, - (int) areaHeight, - scaleXY, - scaleQual); + (int) areaHeight); + + docuImage.scale(scaleXY); + + // mirror image + if (doMirror) { + docuImage.mirror(mirrorAngle); + } + + // rotate image (first shot :-) + if (paramROT != 0) { + docuImage.rotate(paramROT); + } + + // contrast and brightness enhancement + if ((paramCONT != 0) || (paramBRGT != 0)) { + double mult = Math.pow(2, paramCONT); + docuImage.enhance(mult, paramBRGT); + } util.dprintln( 2, @@ -421,9 +518,10 @@ if (mimeType != "image/jpeg") { mimeType = "image/png"; } + response.setContentType(mimeType); // write the image - docuImage.writeImage(mimeType, response); + docuImage.writeImage(mimeType, response.getOutputStream()); util.dprintln( 1,