changeset 963:548988d9fad5

merge (sorry, with digilib-config.xml)
author hertzhaft
date Wed, 25 Jan 2012 16:16:59 +0100
parents e9e50df87c9a (current diff) 6d5f0c39a37f (diff)
children 0b5fa035af30
files common/src/main/java/digilib/image/JAIDocuImage.java common/src/main/java/digilib/image/JAIImageLoaderDocuImage.java webapp/src/main/webapp/WEB-INF/digilib-config.xml
diffstat 19 files changed, 1047 insertions(+), 801 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Jan 25 16:12:33 2012 +0100
+++ b/.hgignore	Wed Jan 25 16:16:59 2012 +0100
@@ -65,4 +65,20 @@
 syntax: regexp
 ^webapp/digilib-log\.txt$
 syntax: regexp
-^webapp/dl-access-log\.txt$
\ No newline at end of file
+^webapp/dl-access-log\.txt$
+syntax: regexp
+^common-jai/target$
+syntax: regexp
+^common-imagej/target$
+syntax: regexp
+^common-imagej/\.classpath$
+syntax: regexp
+^common-imagej/\.project$
+syntax: regexp
+^common-imagej/\.settings$
+syntax: regexp
+^common-jai/\.settings$
+syntax: regexp
+^common-jai/\.classpath$
+syntax: regexp
+^common-jai/\.project$
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common-imagej/pom.xml	Wed Jan 25 16:16:59 2012 +0100
@@ -0,0 +1,49 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>digilib</artifactId>
+    <groupId>digilib</groupId>
+    <version>2.1-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <artifactId>digilib-common-imagej</artifactId>
+  <name>digilib-common-imagej</name>
+  <description>digilib codec implementation using ImageJ toolkit</description>
+  <repositories>
+  	<!-- ImageJ-1 -->
+  	<repository>
+	    <id>imagej.thirdparty</id>
+	    <url>http://dev.imagejdev.org/maven2/thirdparty</url>
+  	</repository>
+    <!--  ImageJ-2 
+    <repository>
+      <id>imagej.releases</id>
+      <url>http://code.imagej.net/maven2/releases</url>
+    </repository>
+    <repository>
+      <id>imagej.snapshots</id>
+      <url>http://code.imagej.net/maven2/snapshots</url>
+    </repository> -->
+  </repositories>
+
+  <dependencies>
+    <!--  imageJ 1 -->
+	<dependency>
+   		<groupId>net.imagej</groupId>
+  		<artifactId>ij</artifactId>
+   		<version>1.45s</version>
+  		<type>jar</type>
+  		<scope>compile</scope>
+	</dependency>
+	<!--  imageJ2
+	<dependency>
+		<groupId>net.imglib2</groupId>
+		<artifactId>imglib2-io</artifactId>
+		<version>2.0-SNAPSHOT</version>
+	</dependency> -->
+	<dependency>
+		<groupId>digilib</groupId>
+		<artifactId>digilib-common</artifactId>
+	</dependency>
+  </dependencies>
+</project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common-imagej/src/main/java/digilib/image/ImageJ1DocuImage.java	Wed Jan 25 16:16:59 2012 +0100
@@ -0,0 +1,148 @@
+/**
+ * 
+ */
+package digilib.image;
+
+import ij.IJ;
+import ij.ImagePlus;
+import ij.plugin.JpegWriter;
+import ij.plugin.PNG_Writer;
+import ij.process.ImageProcessor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import digilib.io.FileOpException;
+import digilib.io.FileOps;
+import digilib.io.ImageInput;
+import digilib.util.ImageSize;
+
+/** Implementation of DocuImage using ImageJ version 1.
+ *  
+ * @author casties
+ *
+ */
+public class ImageJ1DocuImage extends ImageInfoDocuImage {
+
+	protected ImagePlus img;
+	protected ImageProcessor proc;
+
+	/* returns a list of supported image formats */
+	public Iterator<String> getSupportedFormats() {
+		String[] formats = new String[] {"JPG","PNG","TIFF"};
+		return Arrays.asList(formats).iterator();
+	}
+
+    /* Check image size and type and store in ImageInput */
+    public ImageInput identify(ImageInput input) throws IOException {
+        // try parent method first
+        ImageInput ii = super.identify(input);
+        if (ii != null) {
+        	return ii;
+        }
+        logger.debug("identifying (ImageJ1) " + input);
+        String path = input.getFile().getAbsolutePath();
+        img = IJ.openImage(path);
+        // set size
+        ImageSize d = new ImageSize(img.getWidth(), img.getHeight());
+        input.setSize(d);
+        // set mime type
+        if (input.getMimetype() == null) {
+        	String t = FileOps.mimeForFile(input.getFile());
+        	input.setMimetype(t);
+        }
+        return input;
+    }
+
+    /* (non-Javadoc)
+	 * @see digilib.image.DocuImageImpl#loadImage(digilib.io.ImageInput)
+	 */
+	@Override
+	public void loadImage(ImageInput ii) throws FileOpException {
+		this.input = ii;
+		String path = ii.getFile().getAbsolutePath();
+		img = IJ.openImage(path);
+		proc = img.getProcessor();
+	}
+
+	/* (non-Javadoc)
+	 * @see digilib.image.DocuImageImpl#crop(int, int, int, int)
+	 */
+	@Override
+	public void crop(int xoff, int yoff, int width, int height)
+			throws ImageOpException {
+		proc.setRoi(xoff, yoff, width, height);
+		ImageProcessor croppedProc = proc.crop();
+		proc = croppedProc;
+	}
+
+	/* (non-Javadoc)
+	 * @see digilib.image.DocuImageImpl#scale(double, double)
+	 */
+	@Override
+	public void scale(double scaleX, double scaleY) throws ImageOpException {
+		int newWidth = (int) Math.round(proc.getWidth() * scaleX); 
+		int newHeight = (int) Math.round(proc.getHeight() * scaleY);
+		ImageProcessor scaledProc = proc.resize(newWidth, newHeight, false);
+		proc = scaledProc;
+	}
+
+	/* (non-Javadoc)
+	 * @see digilib.image.DocuImageImpl#writeImage(java.lang.String, java.io.OutputStream)
+	 */
+	@Override
+	public void writeImage(String mt, OutputStream ostream)
+			throws ImageOpException, FileOpException {
+		File outFile;
+		String filext = ".jpg"; 
+		if (mt.equals("image/png")) {
+			filext = ".png";
+		}
+		try {
+			outFile = File.createTempFile("imgj_temp", filext);
+		} catch (IOException e) {
+			throw new FileOpException(e.toString());
+		}
+		// save image to file
+		logger.debug("writeImage: mt="+mt);
+		if (mt.equals("image/png")) {
+			PNG_Writer writer = new PNG_Writer();
+			try {
+				img = new ImagePlus("Image", proc);
+				writer.writeImage(img, outFile.getAbsolutePath(), 0);
+			} catch (Exception e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		} else {
+			img = new ImagePlus("Image", proc);
+			JpegWriter.save(img, outFile.getAbsolutePath(), 70);
+		}
+		// now send file
+        FileInputStream inFile = null;
+		try {
+            inFile = new FileInputStream(outFile);
+            byte dataBuffer[] = new byte[4096];
+            int len;
+            while ((len = inFile.read(dataBuffer)) != -1) {
+                // copy out file
+                ostream.write(dataBuffer, 0, len);
+            }
+        } catch (IOException e) {
+			throw new FileOpException(e.toString());
+		} finally {
+            try {
+                if (inFile != null) {
+                    inFile.close();
+                }
+            } catch (IOException e) {
+                // nothing to do
+            }
+        }
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common-jai/pom.xml	Wed Jan 25 16:16:59 2012 +0100
@@ -0,0 +1,40 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>digilib</artifactId>
+    <groupId>digilib</groupId>
+    <version>2.1-SNAPSHOT</version>
+    <relativePath>..</relativePath>
+  </parent>
+  <artifactId>digilib-common-jai</artifactId>
+  <name>digilib-common-jai</name>
+  <description>digilib codec implementation using JAI toolkit</description>
+  <repositories>
+  	<!-- This provides the required versions of JAI-ImageIO -->
+    <repository>
+        <id>geotools.osgeo.org</id>
+        <name>Geotools repository</name>
+        <url>http://download.osgeo.org/webdav/geotools/</url>
+    </repository>
+  </repositories>
+  <dependencies>
+    <dependency>
+      <groupId>javax.media</groupId>
+      <artifactId>jai_codec</artifactId>
+      <version>1.1.3</version>
+      <type>jar</type>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.media</groupId>
+      <artifactId>jai_core</artifactId>
+      <version>1.1.3</version>
+      <type>jar</type>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+    	<groupId>digilib</groupId>
+    	<artifactId>digilib-common</artifactId>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common-jai/src/main/java/digilib/image/JAIDocuImage.java	Wed Jan 25 16:16:59 2012 +0100
@@ -0,0 +1,481 @@
+/* JAIDocuImage -- Image class implementation using JAI (Java Advanced Imaging)
+
+ Digital Image Library servlet components
+
+ Copyright (C) 2001, 2002, 2003 Robert Casties (robcast@mail.berlios.de)
+
+ This program is free software; you can redistribute  it and/or modify it
+ under  the terms of  the GNU General  Public License as published by the
+ Free Software Foundation;  either version 2 of the  License, or (at your
+ option) any later version.
+ 
+ Please read license.txt for the full details. A copy of the GPL
+ may be found at http://www.gnu.org/copyleft/lgpl.html
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ */
+
+package digilib.image;
+
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.image.RenderedImage;
+import java.awt.image.renderable.ParameterBlock;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.media.jai.BorderExtender;
+import javax.media.jai.Interpolation;
+import javax.media.jai.JAI;
+import javax.media.jai.KernelJAI;
+import javax.media.jai.ParameterBlockJAI;
+import javax.media.jai.RenderedOp;
+import javax.media.jai.operator.TransposeDescriptor;
+import javax.media.jai.operator.TransposeType;
+
+import com.sun.media.jai.codec.ImageCodec;
+
+import digilib.io.FileOpException;
+import digilib.io.FileOps;
+import digilib.io.ImageInput;
+import digilib.util.ImageSize;
+
+/** A DocuImage implementation using Java Advanced Imaging Library. */
+/**
+ * @author casties
+ *
+ */
+public class JAIDocuImage extends ImageInfoDocuImage {
+
+	protected RenderedImage img;
+
+	protected Interpolation interpol = null;
+
+	/*
+	 * static { // we could set our own tile cache size here TileCache tc =
+	 * JAI.createTileCache(100*1024*1024);
+	 * JAI.getDefaultInstance().setTileCache(tc); }
+	 */
+
+	public boolean isSubimageSupported() {
+		return true;
+	}
+
+	/*
+	 * Real setQuality implementation. Creates the correct Interpolation.
+	 */
+	public void setQuality(int qual) {
+		quality = qual;
+		// setup interpolation quality
+		if (qual > 1) {
+			logger.debug("quality q2");
+			interpol = Interpolation.getInstance(Interpolation.INTERP_BICUBIC);
+		} else if (qual == 1) {
+			logger.debug("quality q1");
+			interpol = Interpolation.getInstance(Interpolation.INTERP_BILINEAR);
+		} else {
+			logger.debug("quality q0");
+			interpol = Interpolation.getInstance(Interpolation.INTERP_NEAREST);
+		}
+	}
+
+	/* returns a list of supported image formats */
+    @SuppressWarnings("unchecked") // ImageCodec.getCodecs() returns a naked Enumeration
+    public Iterator<String> getSupportedFormats() {
+        Enumeration<ImageCodec> codecs = ImageCodec.getCodecs();
+        List<String> formats = new ArrayList<String>();
+        for (ImageCodec codec = codecs.nextElement(); codecs.hasMoreElements(); codec = codecs
+                .nextElement()) {
+            logger.debug("known format:"+codec.getFormatName());
+            formats.add(codec.getFormatName());
+        }
+        logger.debug("tilecachesize:"
+                + JAI.getDefaultInstance().getTileCache().getMemoryCapacity());
+        return formats.iterator();
+    }
+
+	/* Check image size and type and store in ImageFile f */
+	public ImageInput identify(ImageInput input) throws IOException {
+        this.input = input;
+        // try parent method first
+	    ImageInput imf = super.identify(input);
+		if (imf != null) {
+			return imf;
+		}
+		/*
+		 * try JAI
+		 */
+		logger.debug("identifying (JAI) " + input);
+		try {
+		    RenderedOp img = null;
+		    if (input.hasFile()) {
+		        String t = FileOps.mimeForFile(input.getFile());
+		        input.setMimetype(t);
+		        img = JAI.create("fileload", input.getFile().getAbsolutePath());
+		    } else if (input.hasInputStream()) {
+                img = JAI.create("stream", input.getInputStream());
+                // FIXME: where do we get the mimetype?
+		    } else {
+	            throw new FileOpException("unable to get data for image!");
+		    }
+			ImageSize d = new ImageSize(img.getWidth(), img.getHeight());
+			input.setSize(d);
+			logger.debug("image size: " + d);
+			return input;
+		} catch (Exception e) {
+			throw new FileOpException("ERROR: unable to identify image!");
+		}
+	}
+
+	/* Load an image file into the Object. */
+	public void loadImage(ImageInput ii) throws FileOpException {
+        this.input = ii;
+        if (ii.hasFile()) {
+            img = JAI.create("fileload", ii.getFile().getAbsolutePath());
+        } else if (ii.hasInputStream()) {
+            img = JAI.create("stream", ii.getInputStream());
+        } else {
+            throw new FileOpException("unable to get data for image!");
+        }
+		if (img == null) {
+			throw new FileOpException("Unable to load File!");
+		}
+	}
+
+	/* Load an image file into the Object. */
+	public void loadSubimage(ImageInput ii, Rectangle region, int subsample) throws FileOpException {
+		logger.debug("loadSubimage");
+        this.input = ii;
+        if (ii.hasFile()) {
+            img = JAI.create("fileload", ii.getFile().getAbsolutePath());
+        } else if (ii.hasInputStream()) {
+            img = JAI.create("stream", ii.getInputStream());
+        } else {
+            throw new FileOpException("unable to get data for image!");
+        }
+		if ((region.width < img.getWidth())
+				|| (region.height < img.getHeight())) {
+			// setup Crop
+			ParameterBlock cp = new ParameterBlock();
+			cp.addSource(img);
+			cp.add((float) region.x);
+			cp.add((float) region.y);
+			cp.add((float) region.width);
+			cp.add((float) region.height);
+			logger.debug("loadSubimage: crop");
+			img = JAI.create("crop", cp);
+		}
+		if (subsample > 1) {
+			float sc = 1f / subsample;
+			ParameterBlockJAI sp = new ParameterBlockJAI("scale");
+			sp.addSource(img);
+			sp.setParameter("xScale", sc);
+			sp.setParameter("yScale", sc);
+			sp.setParameter("interpolation", Interpolation
+					.getInstance(Interpolation.INTERP_NEAREST));
+			// scale
+			logger.debug("loadSubimage: scale");
+			img = JAI.create("scale", sp);
+		}
+	}
+
+	/* Write the current image to an OutputStream. */
+	public void writeImage(String mt, OutputStream ostream) throws ImageOpException, FileOpException {
+		try {
+			// setup output
+			ParameterBlock pb3 = new ParameterBlock();
+			pb3.addSource(img);
+			pb3.add(ostream);
+			if (mt == "image/jpeg") {
+				pb3.add("JPEG");
+			} else if (mt == "image/png") {
+				pb3.add("PNG");
+			} else {
+				// unknown mime type
+				throw new ImageOpException("Unknown mime type: " + mt);
+			}
+			// render output
+			JAI.create("encode", pb3);
+
+		} catch (RuntimeException e) {
+		    // JAI likes to throw RuntimeExceptions
+			throw new FileOpException("Error writing image: "+e);
+		}
+	}
+
+    /* returns the current image size
+     * @see digilib.image.DocuImageImpl#getSize()
+     */
+    public ImageSize getSize() {
+        ImageSize is = null;
+        // TODO: do we want to cache imgSize?
+        int h = 0;
+        int w = 0;
+        if (img != null) {
+            // get size from image
+            h = img.getHeight();
+            w = img.getWidth();
+            is = new ImageSize(w, h);
+        }
+        return is;
+    }
+
+	/* scales the current image */
+	public void scale(double scale, double scaleY) throws ImageOpException {
+		logger.debug("scale");
+		if ((scale < 1) && (img.getColorModel().getPixelSize() == 1)
+				&& (quality > 0)) {
+			/*
+			 * "SubsampleBinaryToGray" for downscaling BW
+			 */
+			scaleBinary((float) scale);
+		} else if ((scale <= 0.5) && (quality > 1)) {
+			/*
+			 * blur and "Scale" for downscaling color images
+			 */
+			if ((scale <= 0.5) && (quality > 1)) {
+				int bl = (int) Math.floor(1 / scale);
+				// don't blur more than 3
+				blur(Math.min(bl, 3));
+			}
+			scaleAll((float) scale);
+		} else {
+			/*
+			 * "Scale" for the rest
+			 */
+			scaleAll((float) scale);
+		}
+
+		// DEBUG
+		logger.debug("SCALE: " + scale + " ->" + img.getWidth() + "x"
+				+ img.getHeight());
+
+	}
+
+	public void scaleAll(float scale) throws ImageOpException {
+		RenderedImage scaledImg;
+		// DEBUG
+		logger.debug("scaleAll: " + scale);
+		ParameterBlockJAI param = new ParameterBlockJAI("Scale");
+		param.addSource(img);
+		param.setParameter("xScale", scale);
+		param.setParameter("yScale", scale);
+		param.setParameter("interpolation", interpol);
+		// hint with border extender
+		RenderingHints hint = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
+				BorderExtender.createInstance(BorderExtender.BORDER_COPY));
+		// scale
+		scaledImg = JAI.create("Scale", param, hint);
+
+		if (scaledImg == null) {
+			throw new ImageOpException("Unable to scale");
+		}
+		img = scaledImg;
+	}
+
+	public void blur(int radius) throws ImageOpException {
+		RenderedImage blurredImg;
+		int klen = Math.max(radius, 2);
+		logger.debug("blur: " + klen);
+		int ksize = klen * klen;
+		float f = 1f / ksize;
+		float[] kern = new float[ksize];
+		for (int i = 0; i < ksize; i++) {
+			kern[i] = f;
+		}
+		KernelJAI blur = new KernelJAI(klen, klen, kern);
+		ParameterBlockJAI param = new ParameterBlockJAI("Convolve");
+		param.addSource(img);
+		param.setParameter("kernel", blur);
+		// hint with border extender
+		RenderingHints hint = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
+				BorderExtender.createInstance(BorderExtender.BORDER_COPY));
+		blurredImg = JAI.create("Convolve", param, hint);
+		if (blurredImg == null) {
+			throw new ImageOpException("Unable to scale");
+		}
+		img = blurredImg;
+	}
+
+	public void scaleBinary(float scale) throws ImageOpException {
+		RenderedImage scaledImg;
+		// DEBUG
+		logger.debug("scaleBinary: " + scale);
+		ParameterBlockJAI param = new ParameterBlockJAI("SubsampleBinaryToGray");
+		param.addSource(img);
+		param.setParameter("xScale", scale);
+		param.setParameter("yScale", scale);
+		// hint with border extender
+		RenderingHints hint = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
+				BorderExtender.createInstance(BorderExtender.BORDER_COPY));
+		// scale
+		scaledImg = JAI.create("SubsampleBinaryToGray", param, hint);
+		if (scaledImg == null) {
+			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 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);
+
+		logger.debug("CROP: " + x_off + "," + y_off + ", " + width + ","
+				+ height + " ->" + croppedImg.getWidth() + "x"
+				+ croppedImg.getHeight());
+		img = croppedImg;
+	}
+
+	/* rotates the current image */
+	public void rotate(double angle) throws ImageOpException {
+		RenderedImage rotImg;
+		// convert degrees to radians
+		double rangle = Math.toRadians(angle);
+		double x = img.getWidth() / 2;
+		double y = 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) x);
+			param.add((float) y);
+			param.add((float) rangle);
+			param.add(interpol);
+
+			rotImg = JAI.create("rotate", param);
+		}
+
+		logger.debug("ROTATE: " + x + "," + y + ", " + angle + " (" + rangle
+				+ ")" + " ->" + rotImg.getWidth() + "x" + rotImg.getHeight());
+		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) < 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;
+		}
+		// use Transpose operation
+		ParameterBlock param = new ParameterBlock();
+		param.addSource(img);
+		param.add(rotOp);
+		mirImg = JAI.create("transpose", param);
+
+		if (mirImg == null) {
+			throw new ImageOpException("Unable to flip");
+		}
+		img = mirImg;
+	}
+
+	/* contrast and brightness enhancement */
+	public void enhance(float mult, float 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);
+
+		logger.debug("ENHANCE: *" + mult + ", +" + add + " ->"
+				+ enhImg.getWidth() + "x" + enhImg.getHeight());
+		// DEBUG
+		img = enhImg;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see digilib.image.DocuImage#enhanceRGB(float[], float[])
+	 */
+	public void enhanceRGB(float[] rgbm, float[] rgba) throws ImageOpException {
+		RenderedImage enhImg;
+		int nb = rgbm.length;
+		double[] ma = new double[nb];
+		double[] aa = new double[nb];
+		for (int i = 0; i < nb; i++) {
+			ma[i] = rgbm[i];
+			aa[i] = rgba[i];
+		}
+		// use Rescale operation
+		ParameterBlock param = new ParameterBlock();
+		param.addSource(img);
+		param.add(ma);
+		param.add(aa);
+		enhImg = JAI.create("rescale", param);
+
+		logger.debug("ENHANCE_RGB: *" + rgbm + ", +" + rgba + " ->"
+				+ enhImg.getWidth() + "x" + enhImg.getHeight());
+		img = enhImg;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see digilib.image.DocuImage#dispose()
+	 */
+	public void dispose() {
+		img = null;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common-jai/src/main/java/digilib/image/JAIImageLoaderDocuImage.java	Wed Jan 25 16:16:59 2012 +0100
@@ -0,0 +1,218 @@
+/* JAIImageLoaderDocuImage -- Image class implementation using JAI's ImageLoader Plugin
+
+  Digital Image Library servlet components
+
+  Copyright (C) 2002, 2003 Robert Casties (robcast@mail.berlios.de)
+
+  This program is free software; you can redistribute  it and/or modify it
+  under  the terms of  the GNU General  Public License as published by the
+  Free Software Foundation;  either version 2 of the  License, or (at your
+  option) any later version.
+   
+  Please read license.txt for the full details. A copy of the GPL
+  may be found at http://www.gnu.org/copyleft/lgpl.html
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+package digilib.image;
+
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.image.renderable.ParameterBlock;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.util.Iterator;
+
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.FileImageInputStream;
+import javax.imageio.stream.ImageInputStream;
+import javax.media.jai.JAI;
+
+import digilib.io.FileOpException;
+import digilib.io.ImageInput;
+import digilib.util.ImageSize;
+
+/** DocuImage implementation using the Java Advanced Imaging API and the ImageLoader
+ * API of Java 1.4.
+ */
+public class JAIImageLoaderDocuImage extends JAIDocuImage {
+
+	/** ImageIO image reader */
+	protected ImageReader reader;
+	/** current image file */
+	protected File imgFile;
+
+	/* loadSubimage is supported. */
+	public boolean isSubimageSupported() {
+		return true;
+	}
+
+    /* returns the size of the current image */
+    public ImageSize getSize() {
+        ImageSize is = null;
+        // TODO: can we cache imageSize?
+        int h = 0;
+        int w = 0;
+        try {
+            if (img == null) {
+                // get size from ImageReader
+                h = reader.getHeight(0);
+                w = reader.getWidth(0);
+            } else {
+                // get size from image
+                h = img.getHeight();
+                w = img.getWidth();
+            }
+            is = new ImageSize(w, h);
+        } catch (IOException e) {
+            logger.debug("error in getSize:", e);
+        }
+        return is;
+    }
+
+
+	/* Load an image file into the Object. */
+	public void loadImage(ImageInput ii) throws FileOpException {
+		logger.debug("loadImage: "+ii);
+		if (ii.hasImageInputStream()) {
+			img = JAI.create("ImageRead", ii.getImageInputStream());
+		} else if (ii.hasFile()) {
+			img = JAI.create("ImageRead", ii.getFile().getAbsolutePath());
+		}
+		if (img == null) {
+			throw new FileOpException("Unable to load File!");
+		}
+	}
+
+	/* Get an ImageReader for the image file. */
+	public ImageReader getReader(ImageInput input) throws IOException {
+        logger.debug("get ImageReader for " + input);
+        if (this.reader != null) {
+            if (this.input == input) {
+                // it was the same input
+                logger.debug("reusing Reader");
+                return reader;
+            }
+            // clean up old reader
+            logger.debug("cleaning Reader!");
+            dispose();
+        }
+        this.input = input;
+        ImageInputStream istream = null;
+        if (input.hasImageInputStream()) {
+            // stream input
+            istream = input.getImageInputStream();
+        } else if (input.hasFile()) {
+            // file only input
+            RandomAccessFile rf = new RandomAccessFile(input.getFile(), "r");
+            istream = new FileImageInputStream(rf);
+        } else {
+            throw new FileOpException("Unable to get data from ImageInput");
+        }
+        Iterator<ImageReader> readers;
+        String mt = input.getMimetype();
+        if (mt == null) {
+            logger.debug("No mime-type. Trying automagic.");
+            readers = ImageIO.getImageReaders(istream);
+        } else {
+            logger.debug("File type:" + mt);
+            readers = ImageIO.getImageReadersByMIMEType(mt);
+        }
+        if (!readers.hasNext()) {
+            throw new FileOpException("Can't find Reader to load File!");
+        }
+        reader = readers.next();
+        logger.debug("ImageIO: this reader: " + reader.getClass());
+        /* are there more readers? */
+        /* while (readers.hasNext()) {
+            logger.debug("ImageIO: next reader: " + readers.next().getClass());
+        } */
+        reader.setInput(istream);
+        return reader;
+	}
+
+	/* Load an image file into the Object. */
+	public void loadSubimage(ImageInput ii, Rectangle region, int prescale)
+		throws FileOpException {
+		logger.debug("loadSubimage: "+ii.getFile());
+		//System.gc();
+		try {
+			if ((reader == null) || (imgFile != ii.getFile())) {
+				getReader(ii);
+			}
+			ImageReadParam readParam = reader.getDefaultReadParam();
+			readParam.setSourceRegion(region);
+			readParam.setSourceSubsampling(prescale, prescale, 0, 0);
+			img = reader.read(0, readParam);
+			/* JAI imageread seems to ignore the readParam :-(
+			ImageInputStream istream = (ImageInputStream) reader.getInput();
+			ParameterBlockJAI pb = new ParameterBlockJAI("imageread");
+			pb.setParameter("Input", istream);
+			pb.setParameter("ReadParam", readParam);
+			pb.setParameter("Reader", reader);
+			img = JAI.create("imageread", pb);
+			*/
+		} catch (IOException e) {
+			throw new FileOpException("Unable to load File!");
+		}
+		if (img == null) {
+			throw new FileOpException("Unable to load File!");
+		}
+		imgFile = ii.getFile();
+	}
+
+
+	/* Write the current image to an OutputStream. */
+	public void writeImage(String mt, OutputStream ostream)
+		throws ImageOpException, FileOpException {
+		logger.debug("writeImage");
+		try {
+			// setup output
+			ParameterBlock pb3 = new ParameterBlock();
+			pb3.addSource(img);
+			pb3.add(ostream);
+			if (mt == "image/jpeg") {
+				pb3.add("JPEG");
+			} else if (mt == "image/png") {
+				pb3.add("PNG");
+			} else {
+				// unknown mime type
+				throw new ImageOpException("Unknown mime type: " + mt);
+			}
+			// render output
+			JAI.create("ImageWrite", pb3);
+		} catch (RuntimeException e) {
+			throw new FileOpException("Error writing image.");
+		}
+	}
+
+	@Override
+    public Image getAwtImage() {
+        // TODO Auto-generated method stub
+        return (Image) img;
+    }
+
+    /* (non-Javadoc)
+	 * @see java.lang.Object#finalize()
+	 */
+	protected void finalize() throws Throwable {
+		dispose();
+		super.finalize();
+	}
+
+	public void dispose() {
+		// we must dispose the ImageReader because it keeps the filehandle open!
+		reader.dispose();
+		reader = null;
+		img = null;
+	}
+
+}
--- a/common/pom.xml	Wed Jan 25 16:12:33 2012 +0100
+++ b/common/pom.xml	Wed Jan 25 16:16:59 2012 +0100
@@ -5,11 +5,9 @@
   <parent>
     <artifactId>digilib</artifactId>
     <groupId>digilib</groupId>
-    <version>2.0-SNAPSHOT</version>
+    <version>2.1-SNAPSHOT</version>
   </parent>
-  <groupId>digilib</groupId>
   <artifactId>digilib-common</artifactId>
-  <version>2.0-SNAPSHOT</version>
   <name>digilib-common</name>
   <description>The Digital Image Library - common library</description>
   <url>http://digilib.berlios.de</url>
@@ -19,28 +17,26 @@
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>
 
+  <repositories>
+  	<!-- This provides the required versions of JAI-ImageIO -->
+    <repository>
+        <id>geotools.osgeo.org</id>
+        <name>Geotools repository</name>
+        <url>http://download.osgeo.org/webdav/geotools/</url>
+    </repository>
+  </repositories>
   <dependencies>
     <dependency>
       <groupId>javax.media</groupId>
       <artifactId>jai_imageio</artifactId>
         <type>jar</type>
-        <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>javax.media</groupId>
-      <artifactId>jai_codec</artifactId>
-        <type>jar</type>
-        <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>javax.media</groupId>
-      <artifactId>jai_core</artifactId>
-        <type>jar</type>
+      	<version>1.1</version>
         <scope>compile</scope>
     </dependency>
   	<dependency>
   		<groupId>org.devlib.schmidt</groupId>
   		<artifactId>imageinfo</artifactId>
+        <version>1.9</version>
   		<type>jar</type>
   		<scope>compile</scope>
   	</dependency>
--- a/common/src/main/java/digilib/image/JAIDocuImage.java	Wed Jan 25 16:12:33 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,481 +0,0 @@
-/* JAIDocuImage -- Image class implementation using JAI (Java Advanced Imaging)
-
- Digital Image Library servlet components
-
- Copyright (C) 2001, 2002, 2003 Robert Casties (robcast@mail.berlios.de)
-
- This program is free software; you can redistribute  it and/or modify it
- under  the terms of  the GNU General  Public License as published by the
- Free Software Foundation;  either version 2 of the  License, or (at your
- option) any later version.
- 
- Please read license.txt for the full details. A copy of the GPL
- may be found at http://www.gnu.org/copyleft/lgpl.html
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
- */
-
-package digilib.image;
-
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.image.RenderedImage;
-import java.awt.image.renderable.ParameterBlock;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.media.jai.BorderExtender;
-import javax.media.jai.Interpolation;
-import javax.media.jai.JAI;
-import javax.media.jai.KernelJAI;
-import javax.media.jai.ParameterBlockJAI;
-import javax.media.jai.RenderedOp;
-import javax.media.jai.operator.TransposeDescriptor;
-import javax.media.jai.operator.TransposeType;
-
-import com.sun.media.jai.codec.ImageCodec;
-
-import digilib.io.FileOpException;
-import digilib.io.FileOps;
-import digilib.io.ImageInput;
-import digilib.util.ImageSize;
-
-/** A DocuImage implementation using Java Advanced Imaging Library. */
-/**
- * @author casties
- *
- */
-public class JAIDocuImage extends ImageInfoDocuImage {
-
-	protected RenderedImage img;
-
-	protected Interpolation interpol = null;
-
-	/*
-	 * static { // we could set our own tile cache size here TileCache tc =
-	 * JAI.createTileCache(100*1024*1024);
-	 * JAI.getDefaultInstance().setTileCache(tc); }
-	 */
-
-	public boolean isSubimageSupported() {
-		return true;
-	}
-
-	/*
-	 * Real setQuality implementation. Creates the correct Interpolation.
-	 */
-	public void setQuality(int qual) {
-		quality = qual;
-		// setup interpolation quality
-		if (qual > 1) {
-			logger.debug("quality q2");
-			interpol = Interpolation.getInstance(Interpolation.INTERP_BICUBIC);
-		} else if (qual == 1) {
-			logger.debug("quality q1");
-			interpol = Interpolation.getInstance(Interpolation.INTERP_BILINEAR);
-		} else {
-			logger.debug("quality q0");
-			interpol = Interpolation.getInstance(Interpolation.INTERP_NEAREST);
-		}
-	}
-
-	/* returns a list of supported image formats */
-    @SuppressWarnings("unchecked") // ImageCodec.getCodecs() returns a naked Enumeration
-    public Iterator<String> getSupportedFormats() {
-        Enumeration<ImageCodec> codecs = ImageCodec.getCodecs();
-        List<String> formats = new ArrayList<String>();
-        for (ImageCodec codec = codecs.nextElement(); codecs.hasMoreElements(); codec = codecs
-                .nextElement()) {
-            logger.debug("known format:"+codec.getFormatName());
-            formats.add(codec.getFormatName());
-        }
-        logger.debug("tilecachesize:"
-                + JAI.getDefaultInstance().getTileCache().getMemoryCapacity());
-        return formats.iterator();
-    }
-
-	/* Check image size and type and store in ImageFile f */
-	public ImageInput identify(ImageInput input) throws IOException {
-        this.input = input;
-        // try parent method first
-	    ImageInput imf = super.identify(input);
-		if (imf != null) {
-			return imf;
-		}
-		/*
-		 * try JAI
-		 */
-		logger.debug("identifying (JAI) " + input);
-		try {
-		    RenderedOp img = null;
-		    if (input.hasFile()) {
-		        String t = FileOps.mimeForFile(input.getFile());
-		        input.setMimetype(t);
-		        img = JAI.create("fileload", input.getFile().getAbsolutePath());
-		    } else if (input.hasInputStream()) {
-                img = JAI.create("stream", input.getInputStream());
-                // FIXME: where do we get the mimetype?
-		    } else {
-	            throw new FileOpException("unable to get data for image!");
-		    }
-			ImageSize d = new ImageSize(img.getWidth(), img.getHeight());
-			input.setSize(d);
-			logger.debug("image size: " + d);
-			return input;
-		} catch (Exception e) {
-			throw new FileOpException("ERROR: unable to identify image!");
-		}
-	}
-
-	/* Load an image file into the Object. */
-	public void loadImage(ImageInput ii) throws FileOpException {
-        this.input = ii;
-        if (ii.hasFile()) {
-            img = JAI.create("fileload", ii.getFile().getAbsolutePath());
-        } else if (ii.hasInputStream()) {
-            img = JAI.create("stream", ii.getInputStream());
-        } else {
-            throw new FileOpException("unable to get data for image!");
-        }
-		if (img == null) {
-			throw new FileOpException("Unable to load File!");
-		}
-	}
-
-	/* Load an image file into the Object. */
-	public void loadSubimage(ImageInput ii, Rectangle region, int subsample) throws FileOpException {
-		logger.debug("loadSubimage");
-        this.input = ii;
-        if (ii.hasFile()) {
-            img = JAI.create("fileload", ii.getFile().getAbsolutePath());
-        } else if (ii.hasInputStream()) {
-            img = JAI.create("stream", ii.getInputStream());
-        } else {
-            throw new FileOpException("unable to get data for image!");
-        }
-		if ((region.width < img.getWidth())
-				|| (region.height < img.getHeight())) {
-			// setup Crop
-			ParameterBlock cp = new ParameterBlock();
-			cp.addSource(img);
-			cp.add((float) region.x);
-			cp.add((float) region.y);
-			cp.add((float) region.width);
-			cp.add((float) region.height);
-			logger.debug("loadSubimage: crop");
-			img = JAI.create("crop", cp);
-		}
-		if (subsample > 1) {
-			float sc = 1f / subsample;
-			ParameterBlockJAI sp = new ParameterBlockJAI("scale");
-			sp.addSource(img);
-			sp.setParameter("xScale", sc);
-			sp.setParameter("yScale", sc);
-			sp.setParameter("interpolation", Interpolation
-					.getInstance(Interpolation.INTERP_NEAREST));
-			// scale
-			logger.debug("loadSubimage: scale");
-			img = JAI.create("scale", sp);
-		}
-	}
-
-	/* Write the current image to an OutputStream. */
-	public void writeImage(String mt, OutputStream ostream) throws ImageOpException, FileOpException {
-		try {
-			// setup output
-			ParameterBlock pb3 = new ParameterBlock();
-			pb3.addSource(img);
-			pb3.add(ostream);
-			if (mt == "image/jpeg") {
-				pb3.add("JPEG");
-			} else if (mt == "image/png") {
-				pb3.add("PNG");
-			} else {
-				// unknown mime type
-				throw new ImageOpException("Unknown mime type: " + mt);
-			}
-			// render output
-			JAI.create("encode", pb3);
-
-		} catch (RuntimeException e) {
-		    // JAI likes to throw RuntimeExceptions
-			throw new FileOpException("Error writing image: "+e);
-		}
-	}
-
-    /* returns the current image size
-     * @see digilib.image.DocuImageImpl#getSize()
-     */
-    public ImageSize getSize() {
-        ImageSize is = null;
-        // TODO: do we want to cache imgSize?
-        int h = 0;
-        int w = 0;
-        if (img != null) {
-            // get size from image
-            h = img.getHeight();
-            w = img.getWidth();
-            is = new ImageSize(w, h);
-        }
-        return is;
-    }
-
-	/* scales the current image */
-	public void scale(double scale, double scaleY) throws ImageOpException {
-		logger.debug("scale");
-		if ((scale < 1) && (img.getColorModel().getPixelSize() == 1)
-				&& (quality > 0)) {
-			/*
-			 * "SubsampleBinaryToGray" for downscaling BW
-			 */
-			scaleBinary((float) scale);
-		} else if ((scale <= 0.5) && (quality > 1)) {
-			/*
-			 * blur and "Scale" for downscaling color images
-			 */
-			if ((scale <= 0.5) && (quality > 1)) {
-				int bl = (int) Math.floor(1 / scale);
-				// don't blur more than 3
-				blur(Math.min(bl, 3));
-			}
-			scaleAll((float) scale);
-		} else {
-			/*
-			 * "Scale" for the rest
-			 */
-			scaleAll((float) scale);
-		}
-
-		// DEBUG
-		logger.debug("SCALE: " + scale + " ->" + img.getWidth() + "x"
-				+ img.getHeight());
-
-	}
-
-	public void scaleAll(float scale) throws ImageOpException {
-		RenderedImage scaledImg;
-		// DEBUG
-		logger.debug("scaleAll: " + scale);
-		ParameterBlockJAI param = new ParameterBlockJAI("Scale");
-		param.addSource(img);
-		param.setParameter("xScale", scale);
-		param.setParameter("yScale", scale);
-		param.setParameter("interpolation", interpol);
-		// hint with border extender
-		RenderingHints hint = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
-				BorderExtender.createInstance(BorderExtender.BORDER_COPY));
-		// scale
-		scaledImg = JAI.create("Scale", param, hint);
-
-		if (scaledImg == null) {
-			throw new ImageOpException("Unable to scale");
-		}
-		img = scaledImg;
-	}
-
-	public void blur(int radius) throws ImageOpException {
-		RenderedImage blurredImg;
-		int klen = Math.max(radius, 2);
-		logger.debug("blur: " + klen);
-		int ksize = klen * klen;
-		float f = 1f / ksize;
-		float[] kern = new float[ksize];
-		for (int i = 0; i < ksize; i++) {
-			kern[i] = f;
-		}
-		KernelJAI blur = new KernelJAI(klen, klen, kern);
-		ParameterBlockJAI param = new ParameterBlockJAI("Convolve");
-		param.addSource(img);
-		param.setParameter("kernel", blur);
-		// hint with border extender
-		RenderingHints hint = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
-				BorderExtender.createInstance(BorderExtender.BORDER_COPY));
-		blurredImg = JAI.create("Convolve", param, hint);
-		if (blurredImg == null) {
-			throw new ImageOpException("Unable to scale");
-		}
-		img = blurredImg;
-	}
-
-	public void scaleBinary(float scale) throws ImageOpException {
-		RenderedImage scaledImg;
-		// DEBUG
-		logger.debug("scaleBinary: " + scale);
-		ParameterBlockJAI param = new ParameterBlockJAI("SubsampleBinaryToGray");
-		param.addSource(img);
-		param.setParameter("xScale", scale);
-		param.setParameter("yScale", scale);
-		// hint with border extender
-		RenderingHints hint = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
-				BorderExtender.createInstance(BorderExtender.BORDER_COPY));
-		// scale
-		scaledImg = JAI.create("SubsampleBinaryToGray", param, hint);
-		if (scaledImg == null) {
-			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 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);
-
-		logger.debug("CROP: " + x_off + "," + y_off + ", " + width + ","
-				+ height + " ->" + croppedImg.getWidth() + "x"
-				+ croppedImg.getHeight());
-		img = croppedImg;
-	}
-
-	/* rotates the current image */
-	public void rotate(double angle) throws ImageOpException {
-		RenderedImage rotImg;
-		// convert degrees to radians
-		double rangle = Math.toRadians(angle);
-		double x = img.getWidth() / 2;
-		double y = 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) x);
-			param.add((float) y);
-			param.add((float) rangle);
-			param.add(interpol);
-
-			rotImg = JAI.create("rotate", param);
-		}
-
-		logger.debug("ROTATE: " + x + "," + y + ", " + angle + " (" + rangle
-				+ ")" + " ->" + rotImg.getWidth() + "x" + rotImg.getHeight());
-		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) < 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;
-		}
-		// use Transpose operation
-		ParameterBlock param = new ParameterBlock();
-		param.addSource(img);
-		param.add(rotOp);
-		mirImg = JAI.create("transpose", param);
-
-		if (mirImg == null) {
-			throw new ImageOpException("Unable to flip");
-		}
-		img = mirImg;
-	}
-
-	/* contrast and brightness enhancement */
-	public void enhance(float mult, float 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);
-
-		logger.debug("ENHANCE: *" + mult + ", +" + add + " ->"
-				+ enhImg.getWidth() + "x" + enhImg.getHeight());
-		// DEBUG
-		img = enhImg;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see digilib.image.DocuImage#enhanceRGB(float[], float[])
-	 */
-	public void enhanceRGB(float[] rgbm, float[] rgba) throws ImageOpException {
-		RenderedImage enhImg;
-		int nb = rgbm.length;
-		double[] ma = new double[nb];
-		double[] aa = new double[nb];
-		for (int i = 0; i < nb; i++) {
-			ma[i] = rgbm[i];
-			aa[i] = rgba[i];
-		}
-		// use Rescale operation
-		ParameterBlock param = new ParameterBlock();
-		param.addSource(img);
-		param.add(ma);
-		param.add(aa);
-		enhImg = JAI.create("rescale", param);
-
-		logger.debug("ENHANCE_RGB: *" + rgbm + ", +" + rgba + " ->"
-				+ enhImg.getWidth() + "x" + enhImg.getHeight());
-		img = enhImg;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see digilib.image.DocuImage#dispose()
-	 */
-	public void dispose() {
-		img = null;
-	}
-
-}
--- a/common/src/main/java/digilib/image/JAIImageLoaderDocuImage.java	Wed Jan 25 16:12:33 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/* JAIImageLoaderDocuImage -- Image class implementation using JAI's ImageLoader Plugin
-
-  Digital Image Library servlet components
-
-  Copyright (C) 2002, 2003 Robert Casties (robcast@mail.berlios.de)
-
-  This program is free software; you can redistribute  it and/or modify it
-  under  the terms of  the GNU General  Public License as published by the
-  Free Software Foundation;  either version 2 of the  License, or (at your
-  option) any later version.
-   
-  Please read license.txt for the full details. A copy of the GPL
-  may be found at http://www.gnu.org/copyleft/lgpl.html
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-*/
-
-package digilib.image;
-
-import java.awt.Image;
-import java.awt.Rectangle;
-import java.awt.image.renderable.ParameterBlock;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.util.Iterator;
-
-import javax.imageio.ImageIO;
-import javax.imageio.ImageReadParam;
-import javax.imageio.ImageReader;
-import javax.imageio.stream.FileImageInputStream;
-import javax.imageio.stream.ImageInputStream;
-import javax.media.jai.JAI;
-
-import digilib.io.FileOpException;
-import digilib.io.ImageInput;
-import digilib.util.ImageSize;
-
-/** DocuImage implementation using the Java Advanced Imaging API and the ImageLoader
- * API of Java 1.4.
- */
-public class JAIImageLoaderDocuImage extends JAIDocuImage {
-
-	/** ImageIO image reader */
-	protected ImageReader reader;
-	/** current image file */
-	protected File imgFile;
-
-	/* loadSubimage is supported. */
-	public boolean isSubimageSupported() {
-		return true;
-	}
-
-    /* returns the size of the current image */
-    public ImageSize getSize() {
-        ImageSize is = null;
-        // TODO: can we cache imageSize?
-        int h = 0;
-        int w = 0;
-        try {
-            if (img == null) {
-                // get size from ImageReader
-                h = reader.getHeight(0);
-                w = reader.getWidth(0);
-            } else {
-                // get size from image
-                h = img.getHeight();
-                w = img.getWidth();
-            }
-            is = new ImageSize(w, h);
-        } catch (IOException e) {
-            logger.debug("error in getSize:", e);
-        }
-        return is;
-    }
-
-
-	/* Load an image file into the Object. */
-	public void loadImage(ImageInput ii) throws FileOpException {
-		logger.debug("loadImage: "+ii);
-		if (ii.hasImageInputStream()) {
-			img = JAI.create("ImageRead", ii.getImageInputStream());
-		} else if (ii.hasFile()) {
-			img = JAI.create("ImageRead", ii.getFile().getAbsolutePath());
-		}
-		if (img == null) {
-			throw new FileOpException("Unable to load File!");
-		}
-	}
-
-	/* Get an ImageReader for the image file. */
-	public ImageReader getReader(ImageInput input) throws IOException {
-        logger.debug("get ImageReader for " + input);
-        if (this.reader != null) {
-            if (this.input == input) {
-                // it was the same input
-                logger.debug("reusing Reader");
-                return reader;
-            }
-            // clean up old reader
-            logger.debug("cleaning Reader!");
-            dispose();
-        }
-        this.input = input;
-        ImageInputStream istream = null;
-        if (input.hasImageInputStream()) {
-            // stream input
-            istream = input.getImageInputStream();
-        } else if (input.hasFile()) {
-            // file only input
-            RandomAccessFile rf = new RandomAccessFile(input.getFile(), "r");
-            istream = new FileImageInputStream(rf);
-        } else {
-            throw new FileOpException("Unable to get data from ImageInput");
-        }
-        Iterator<ImageReader> readers;
-        String mt = input.getMimetype();
-        if (mt == null) {
-            logger.debug("No mime-type. Trying automagic.");
-            readers = ImageIO.getImageReaders(istream);
-        } else {
-            logger.debug("File type:" + mt);
-            readers = ImageIO.getImageReadersByMIMEType(mt);
-        }
-        if (!readers.hasNext()) {
-            throw new FileOpException("Can't find Reader to load File!");
-        }
-        reader = readers.next();
-        logger.debug("ImageIO: this reader: " + reader.getClass());
-        /* are there more readers? */
-        /* while (readers.hasNext()) {
-            logger.debug("ImageIO: next reader: " + readers.next().getClass());
-        } */
-        reader.setInput(istream);
-        return reader;
-	}
-
-	/* Load an image file into the Object. */
-	public void loadSubimage(ImageInput ii, Rectangle region, int prescale)
-		throws FileOpException {
-		logger.debug("loadSubimage: "+ii.getFile());
-		//System.gc();
-		try {
-			if ((reader == null) || (imgFile != ii.getFile())) {
-				getReader(ii);
-			}
-			ImageReadParam readParam = reader.getDefaultReadParam();
-			readParam.setSourceRegion(region);
-			readParam.setSourceSubsampling(prescale, prescale, 0, 0);
-			img = reader.read(0, readParam);
-			/* JAI imageread seems to ignore the readParam :-(
-			ImageInputStream istream = (ImageInputStream) reader.getInput();
-			ParameterBlockJAI pb = new ParameterBlockJAI("imageread");
-			pb.setParameter("Input", istream);
-			pb.setParameter("ReadParam", readParam);
-			pb.setParameter("Reader", reader);
-			img = JAI.create("imageread", pb);
-			*/
-		} catch (IOException e) {
-			throw new FileOpException("Unable to load File!");
-		}
-		if (img == null) {
-			throw new FileOpException("Unable to load File!");
-		}
-		imgFile = ii.getFile();
-	}
-
-
-	/* Write the current image to an OutputStream. */
-	public void writeImage(String mt, OutputStream ostream)
-		throws ImageOpException, FileOpException {
-		logger.debug("writeImage");
-		try {
-			// setup output
-			ParameterBlock pb3 = new ParameterBlock();
-			pb3.addSource(img);
-			pb3.add(ostream);
-			if (mt == "image/jpeg") {
-				pb3.add("JPEG");
-			} else if (mt == "image/png") {
-				pb3.add("PNG");
-			} else {
-				// unknown mime type
-				throw new ImageOpException("Unknown mime type: " + mt);
-			}
-			// render output
-			JAI.create("ImageWrite", pb3);
-		} catch (RuntimeException e) {
-			throw new FileOpException("Error writing image.");
-		}
-	}
-
-	@Override
-    public Image getAwtImage() {
-        // TODO Auto-generated method stub
-        return (Image) img;
-    }
-
-    /* (non-Javadoc)
-	 * @see java.lang.Object#finalize()
-	 */
-	protected void finalize() throws Throwable {
-		dispose();
-		super.finalize();
-	}
-
-	public void dispose() {
-		// we must dispose the ImageReader because it keeps the filehandle open!
-		reader.dispose();
-		reader = null;
-		img = null;
-	}
-
-}
--- a/pdf/pom.xml	Wed Jan 25 16:12:33 2012 +0100
+++ b/pdf/pom.xml	Wed Jan 25 16:16:59 2012 +0100
@@ -12,6 +12,13 @@
 	<name>digilib-pdf</name>
 	<description>The Digital Image Library - PDF generation servlet</description>
 	<url>http://digilib.berlios.de</url>
+	<repositories>
+    <repository>
+      <id>itextpdf.com</id>
+      <name>Maven Repository for iText</name>
+      <url>http://maven.itextpdf.com/</url>
+    </repository>
+    </repositories>
 	<dependencies>
 		<dependency>
 			<groupId>digilib</groupId>
@@ -22,6 +29,7 @@
 		<dependency>
 			<groupId>com.itextpdf</groupId>
 			<artifactId>itextpdf</artifactId>
+	        <version>5.0.4</version>
 			<type>jar</type>
 			<scope>compile</scope>
 		</dependency>
--- a/pom.xml	Wed Jan 25 16:12:33 2012 +0100
+++ b/pom.xml	Wed Jan 25 16:16:59 2012 +0100
@@ -4,7 +4,7 @@
 
   <groupId>digilib</groupId>
   <artifactId>digilib</artifactId>
-  <version>2.0-SNAPSHOT</version>
+  <version>2.1-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>digilib</name>
@@ -12,6 +12,15 @@
   <url>http://digilib.berlios.de</url>
 
   <build>
+  	<pluginManagement>
+  		<plugins>
+  			<plugin>
+  			  <groupId>org.apache.maven.plugins</groupId>
+  			  <artifactId>maven-compiler-plugin</artifactId>
+  			  <version>2.3.2</version>
+  			</plugin>
+  		</plugins>
+  	</pluginManagement>
   	<plugins>
   		<plugin>
   			<groupId>org.apache.maven.plugins</groupId>
@@ -22,15 +31,6 @@
             </configuration>
   		</plugin>
   	</plugins>
-  	<pluginManagement>
-  		<plugins>
-  			<plugin>
-  				<groupId>org.apache.maven.plugins</groupId>
-  				<artifactId>maven-war-plugin</artifactId>
-  				<version>2.1.1</version>
-  			</plugin>
-  		</plugins>
-  	</pluginManagement>
   </build>
   <profiles>
   	<profile>
@@ -38,65 +38,14 @@
   		<activation>
   			<activeByDefault>true</activeByDefault>
   		</activation>
-  		<dependencyManagement>
-  			<dependencies>
-  			</dependencies>
-  		</dependencyManagement>
-  	</profile>
-  	<profile>
-  		<id>servlet3</id>
-  		<dependencyManagement>
-  			<dependencies>
-  				<dependency>
-  					<groupId>org.mortbay.jetty</groupId>
-  					<artifactId>servlet-api</artifactId>
-  					<version>3.0.20100224</version>
-  					<type>jar</type>
-  					<scope>provided</scope>
-  				</dependency>
-  			</dependencies>
-  		</dependencyManagement>
   	</profile>
   </profiles>
   <repositories>
-    <repository>
-      <id>itextpdf.com</id>
-      <name>Maven Repository for iText</name>
-      <url>http://maven.itextpdf.com/</url>
-    </repository>
-  <!-- This provides the required versions of JAI-ImageIO -->
-    <repository>
-        <id>geotools.osgeo.org</id>
-        <name>Geotools repository</name>
-        <url>http://download.osgeo.org/webdav/geotools/</url>
-    </repository>
   </repositories>
 
   <dependencyManagement>
   	<dependencies>
     <dependency>
-      <groupId>javax.media</groupId>
-      <artifactId>jai_imageio</artifactId>
-      <version>1.1</version>
-    </dependency>
-    <dependency>
-      <groupId>javax.media</groupId>
-      <artifactId>jai_codec</artifactId>
-      <version>1.1.3</version>
-    </dependency>
-    <dependency>
-      <groupId>javax.media</groupId>
-      <artifactId>jai_core</artifactId>
-      <version>1.1.3</version>
-    </dependency>
-    <dependency>
-        <groupId>org.devlib.schmidt</groupId>
-        <artifactId>imageinfo</artifactId>
-        <version>1.9</version>
-        <type>jar</type>
-        <scope>compile</scope>
-    </dependency>
-    <dependency>
         <groupId>org.jdom</groupId>
         <artifactId>jdom</artifactId>
         <version>1.1</version>
@@ -111,50 +60,58 @@
         <scope>compile</scope>
     </dependency>
     <dependency>
-      <groupId>com.itextpdf</groupId>
-      <artifactId>itextpdf</artifactId>
-      <version>5.0.4</version>
-      <scope>compile</scope>
+    	<groupId>digilib</groupId>
+    	<artifactId>digilib-common</artifactId>
+    	<version>2.1-SNAPSHOT</version>
+    	<type>jar</type>
+    	<scope>compile</scope>
     </dependency>
     <dependency>
     	<groupId>digilib</groupId>
-    	<artifactId>digilib-common</artifactId>
-    	<version>2.0-SNAPSHOT</version>
+    	<artifactId>digilib-common-jai</artifactId>
+    	<version>2.1-SNAPSHOT</version>
+    	<type>jar</type>
+    	<scope>compile</scope>
+    </dependency>
+    <dependency>
+    	<groupId>digilib</groupId>
+    	<artifactId>digilib-common-imagej</artifactId>
+    	<version>2.1-SNAPSHOT</version>
     	<type>jar</type>
     	<scope>compile</scope>
     </dependency>
     <dependency>
     	<groupId>digilib</groupId>
     	<artifactId>digilib-pdf</artifactId>
-    	<version>2.0-SNAPSHOT</version>
+    	<version>2.1-SNAPSHOT</version>
     	<type>jar</type>
     	<scope>compile</scope>
     </dependency>
     <dependency>
     	<groupId>digilib</groupId>
     	<artifactId>digilib-text</artifactId>
-    	<version>2.0-SNAPSHOT</version>
+    	<version>2.1-SNAPSHOT</version>
     	<type>jar</type>
     	<scope>compile</scope>
     </dependency>
     <dependency>
     	<groupId>digilib</groupId>
     	<artifactId>digilib-servlet2</artifactId>
-    	<version>2.0-SNAPSHOT</version>
+    	<version>2.1-SNAPSHOT</version>
     	<type>jar</type>
     	<scope>compile</scope>
     </dependency>
     <dependency>
     	<groupId>digilib</groupId>
     	<artifactId>digilib-servlet3</artifactId>
-    	<version>2.0-SNAPSHOT</version>
+    	<version>2.1-SNAPSHOT</version>
     	<type>jar</type>
     	<scope>compile</scope>
     </dependency>
     <dependency>
     	<groupId>digilib</groupId>
     	<artifactId>digilib-webapp</artifactId>
-    	<version>2.0-SNAPSHOT</version>
+    	<version>2.1-SNAPSHOT</version>
     	<type>war</type>
     	<scope>compile</scope>
     </dependency>
@@ -197,5 +154,7 @@
     <module>servlet3</module>
     <module>pdf</module>
     <module>text</module>
+    <module>common-jai</module>
+    <module>common-imagej</module>
   </modules>
 </project>
\ No newline at end of file
--- a/servlet2/src/main/java/digilib/servlet/DigilibServletConfiguration.java	Wed Jan 25 16:12:33 2012 +0100
+++ b/servlet2/src/main/java/digilib/servlet/DigilibServletConfiguration.java	Wed Jan 25 16:16:59 2012 +0100
@@ -69,7 +69,7 @@
 		// DocuImage class instance
 		newParameter(
 			"servlet.docuimage.class",
-			digilib.image.JAIDocuImage.class,
+			digilib.image.ImageLoaderDocuImage.class,
 			null,
 			's');
 		// AuthOps instance for authentication
@@ -115,7 +115,7 @@
 		// Type of DocuImage instance
 		newParameter(
 			"docuimage-class",
-			"digilib.image.JAIDocuImage",
+			"digilib.image.ImageLoaderDocuImage",
 			null,
 			'f');
 		// part of URL used to indicate authorized access
--- a/servlet2/src/main/java/digilib/servlet/Scaler.java	Wed Jan 25 16:12:33 2012 +0100
+++ b/servlet2/src/main/java/digilib/servlet/Scaler.java	Wed Jan 25 16:16:59 2012 +0100
@@ -34,7 +34,7 @@
     private static final long serialVersionUID = -5439198888139362735L;
 
     /** digilib servlet version (for all components) */
-    public static final String version = "2.0b1 noasync";
+    public static final String version = "2.1b1 noasync";
 
     /** servlet error codes */
     public static enum Error {UNKNOWN, AUTH, FILE, IMAGE};
--- a/servlet3/pom.xml	Wed Jan 25 16:12:33 2012 +0100
+++ b/servlet3/pom.xml	Wed Jan 25 16:16:59 2012 +0100
@@ -3,11 +3,9 @@
   <parent>
     <artifactId>digilib</artifactId>
     <groupId>digilib</groupId>
-    <version>2.0-SNAPSHOT</version>
+    <version>2.1-SNAPSHOT</version>
   </parent>
-  <groupId>digilib</groupId>
   <artifactId>digilib-servlet3</artifactId>
-  <version>2.0-SNAPSHOT</version>
   <name>digilib-servlet3</name>
   <build>
   	<pluginManagement>
@@ -15,7 +13,6 @@
   			<plugin>
   				<groupId>org.apache.maven.plugins</groupId>
   				<artifactId>maven-compiler-plugin</artifactId>
-  				<version>2.3.2</version>
                 <configuration>
                     <source>1.6</source>
                     <target>1.6</target> 
--- a/servlet3/src/main/java/digilib/servlet/DigilibServletConfiguration.java	Wed Jan 25 16:12:33 2012 +0100
+++ b/servlet3/src/main/java/digilib/servlet/DigilibServletConfiguration.java	Wed Jan 25 16:16:59 2012 +0100
@@ -78,7 +78,7 @@
         newParameter("servlet.dir.cache", null, null, 's');
         // DocuImage class instance
         newParameter("servlet.docuimage.class",
-                digilib.image.JAIDocuImage.class, null, 's');
+                digilib.image.ImageLoaderDocuImage.class, null, 's');
         // AuthOps instance for authentication
         newParameter("servlet.auth.op", null, null, 's');
         // Executor for image operations
@@ -111,7 +111,7 @@
         // sending image files as-is allowed
         newParameter("sendfile-allowed", Boolean.TRUE, null, 'f');
         // Type of DocuImage instance
-        newParameter("docuimage-class", "digilib.image.JAIDocuImage", null, 'f');
+        newParameter("docuimage-class", "digilib.image.ImageLoaderDocuImage", null, 'f');
         // part of URL used to indicate authorized access
         newParameter("auth-url-path", "authenticated/", null, 'f');
         // degree of subsampling on image load
--- a/servlet3/src/main/java/digilib/servlet/Initialiser.java	Wed Jan 25 16:12:33 2012 +0100
+++ b/servlet3/src/main/java/digilib/servlet/Initialiser.java	Wed Jan 25 16:16:59 2012 +0100
@@ -23,7 +23,6 @@
 import java.io.File;
 import java.io.OutputStream;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.imageio.ImageIO;
 import javax.servlet.ServletContext;
--- a/servlet3/src/main/java/digilib/servlet/Scaler.java	Wed Jan 25 16:12:33 2012 +0100
+++ b/servlet3/src/main/java/digilib/servlet/Scaler.java	Wed Jan 25 16:16:59 2012 +0100
@@ -31,7 +31,7 @@
     private static final long serialVersionUID = 5289386646192471549L;
 
     /** digilib servlet version (for all components) */
-    public static final String version = "2.0b4 async";
+    public static final String version = "2.1b1 async";
 
     /** servlet error codes */
     public static enum Error {
--- a/webapp/pom.xml	Wed Jan 25 16:12:33 2012 +0100
+++ b/webapp/pom.xml	Wed Jan 25 16:16:59 2012 +0100
@@ -6,10 +6,9 @@
   <parent>
     <artifactId>digilib</artifactId>
     <groupId>digilib</groupId>
-    <version>2.0-SNAPSHOT</version>
+    <version>2.1-SNAPSHOT</version>
   </parent>
   <artifactId>digilib-webapp</artifactId>
-  <version>2.0-SNAPSHOT</version>
   <name>digilib-webapp</name>
   <description>The Digital Image Library - web application server and HTML and JS clients</description>
   <url>http://digilib.berlios.de</url>
@@ -19,6 +18,18 @@
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>
 
+  <build>
+	<pluginManagement>
+	  <plugins>
+      	<plugin>
+	      <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-war-plugin</artifactId>
+		  <version>2.1.1</version>
+	    </plugin>
+      </plugins>	
+	</pluginManagement>
+  </build>
+
   <profiles>
     <profile>
       <id>servlet2</id>
@@ -109,5 +120,27 @@
         </dependency>
       </dependencies>
     </profile>
+    <profile>
+      <id>codec-jai</id>
+      <dependencies>
+        <dependency>
+          <groupId>digilib</groupId>
+          <artifactId>digilib-common-jai</artifactId>
+          <type>jar</type>
+          <scope>compile</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+    <profile>
+      <id>codec-imagej</id>
+      <dependencies>
+        <dependency>
+          <groupId>digilib</groupId>
+          <artifactId>digilib-common-imagej</artifactId>
+          <type>jar</type>
+          <scope>compile</scope>
+        </dependency>
+      </dependencies>
+    </profile>
   </profiles>
 </project>
--- a/webapp/src/main/webapp/WEB-INF/digilib-config.xml	Wed Jan 25 16:12:33 2012 +0100
+++ b/webapp/src/main/webapp/WEB-INF/digilib-config.xml	Wed Jan 25 16:16:59 2012 +0100
@@ -14,10 +14,11 @@
   <!-- List of directories where images are searched.
        Directories with low-resolution images are LAST!!! in list.
 	   Use OS-specific path separators (":" for Unix, ";" for Windows) --> 
-  <parameter name="basedir-list" value="/docuserver/images:/docuserver/scaled/small:/docuserver/scaled/thumb" />
+  <parameter name="basedir-list" value="Y:\scans\quellen;Y:\scaled\small;Y:\scaled\mini;Y:\thumbs" />
 
   <!-- Java class to use for image operations -->
   <parameter name="docuimage-class" value="digilib.image.ImageLoaderDocuImage" />
+  <!-- <parameter name="docuimage-class" value="digilib.image.ImageJ1DocuImage" /> -->
 
   <!-- mimimum amount of scaling done with antialiasing -->
   <parameter name="subsample-minimum" value="2"/>