Mercurial > hg > digilib-old
changeset 86:997ba69afb81
New version 1.8b1.
With directory and file information cache.
With enhanceRGB method for color correction.
author | robcast |
---|---|
date | Sun, 09 Mar 2003 21:37:27 +0100 |
parents | 4e6757e8ccd4 |
children | 5d44cd2481a5 |
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/io/DocuDirCache.java servlet/src/digilib/io/DocuDirectory.java servlet/src/digilib/io/DocuFile.java servlet/src/digilib/io/DocuFileset.java servlet/src/digilib/io/FileOps.java servlet/src/digilib/servlet/DigilibConfiguration.java servlet/src/digilib/servlet/DigilibRequest.java servlet/src/digilib/servlet/DocumentBean.java servlet/src/digilib/servlet/Scaler.java |
diffstat | 13 files changed, 1123 insertions(+), 193 deletions(-) [+] |
line wrap: on
line diff
--- a/servlet/src/digilib/image/DocuImage.java Thu Feb 27 15:07:29 2003 +0100 +++ b/servlet/src/digilib/image/DocuImage.java Sun Mar 09 21:37:27 2003 +0100 @@ -22,8 +22,10 @@ import java.awt.Rectangle; import java.io.File; +import java.io.IOException; import java.io.OutputStream; +import digilib.io.DocuFile; import digilib.io.FileOpException; /** The basic class for the representation of a digilib image. @@ -64,18 +66,16 @@ public void loadSubimage(File f, Rectangle region, int subsample) throws FileOpException; - /** This DocuImage support the preloadImage operation for getWidth/getHeight. + /** Checks the size and type of the DocuFile f. * - * @return boolean + * The image size and type of the DocuFile f is determined and stored in + * the DocuFile object. Returns true if successfull. + * + * @param f DocuFile to be checked. + * @return boolean true if check was successfull. + * @throws FileOpException Exception thrown on error. */ - public boolean isPreloadSupported(); - - /** Preload image file into a state to use getWidth/getHeight. - * - * @param f - * @throws FileOpException - */ - public void preloadImage(File f) throws FileOpException; + public boolean checkFile(DocuFile f) throws IOException; /** Writes the current image to a ServletResponse. * @@ -103,6 +103,12 @@ */ public int getHeight(); + /** The mime-type of the current image. + * + * @return String the mime-type of this image. + */ + public String getMimetype(); + /** Crops the current image. * * Cuts out a region of the size <code>width</code> x <code>height</code> at @@ -175,7 +181,7 @@ */ public void mirror(double angle) throws ImageOpException; - /** Enhaces brightness and contrast of the current image. + /** Enhances 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 @@ -186,7 +192,22 @@ * @param add additive constant for brightness enhancement * @throws ImageOpException */ - public void enhance(double mult, double add) throws ImageOpException; + public void enhance(float mult, float add) throws ImageOpException; + + /** Manipulates the colors of the current image. + * + * Replaces the current image with a color modified image. + * For the red, green and blue color channels all pixel values are multiplied + * by the constant + * <code>m</code> and added to the constant + * <code>a</code>. Operation: p1 = (p0*m)+a. + * + * @param rgbm multiplicative constants for red, green, blue + * @param rgba additive constant for red, green, blue + * @throws ImageOpException + */ + public void enhanceRGB(float[] rgbm, float[] rgba) + throws ImageOpException; /** * Returns the interpolation quality.
--- a/servlet/src/digilib/image/DocuImageImpl.java Thu Feb 27 15:07:29 2003 +0100 +++ b/servlet/src/digilib/image/DocuImageImpl.java Sun Mar 09 21:37:27 2003 +0100 @@ -20,11 +20,15 @@ package digilib.image; +import java.awt.Dimension; import java.awt.Rectangle; import java.io.File; +import java.io.IOException; import digilib.Utils; +import digilib.io.DocuFile; import digilib.io.FileOpException; +import digilib.io.FileOps; /** Simple abstract implementation of the <code>DocuImage</code> interface. * @@ -42,8 +46,11 @@ /** Interpolation quality. */ protected int quality = 0; - // epsilon for float comparisons + /** epsilon for float comparisons. */ public final double epsilon = 1e-5; + + /** image mime-type */ + protected String mimeType = null; /** Default constructor. */ public DocuImageImpl() { @@ -116,6 +123,23 @@ scale(scale); } + /* this is a rather stupid implementation, eventually loading the whole file. */ + public boolean checkFile(DocuFile f) throws IOException { + loadImage(f.getFile()); + int w = getWidth(); + int h = getHeight(); + Dimension s = new Dimension(w, h); + f.setSize(s); + String m = FileOps.mimeForFile(f.getFile()); + mimeType = m; + f.setMimetype(m); + return true; + } + + public String getMimetype() { + return mimeType; + } + public void rotate(double angle) throws ImageOpException { // just a do-nothing implementation } @@ -124,21 +148,12 @@ // just a do-nothing implementation } - public void enhance(double mult, double add) throws ImageOpException { - // just a do-nothing implementation - } - - public void preloadImage(File f) throws FileOpException { + public void enhance(float mult, float add) throws ImageOpException { // just a do-nothing implementation } - public boolean isPreloadSupported() { - // preload per default not supported - return false; - } - public boolean isSubimageSupported() { - // partial loading per default not supported + // partial loading not supported per default return false; } @@ -147,4 +162,9 @@ // empty implementation } + public void enhanceRGB(float[] rgbm, float[] rgba) + throws ImageOpException { + // emtpy implementation + } + }
--- a/servlet/src/digilib/image/ImageLoaderDocuImage.java Thu Feb 27 15:07:29 2003 +0100 +++ b/servlet/src/digilib/image/ImageLoaderDocuImage.java Sun Mar 09 21:37:27 2003 +0100 @@ -20,6 +20,7 @@ package digilib.image; +import java.awt.Dimension; import java.awt.Rectangle; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; @@ -35,22 +36,21 @@ import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; +import digilib.io.DocuFile; import digilib.io.FileOpException; +import digilib.io.FileOps; /** Implementation of DocuImage using the ImageLoader API of Java 1.4 and Java2D. */ public class ImageLoaderDocuImage extends DocuImageImpl { - private BufferedImage img; - - private int interpol; - - // ImageIO image reader - ImageReader reader; - - /* preload is supported. */ - public boolean isPreloadSupported() { - return true; - } + /** image object */ + protected BufferedImage img; + /** interpolation type */ + protected int interpol; + /** ImageIO image reader */ + protected ImageReader reader; + /** File that was read */ + protected File imgFile; /* loadSubimage is supported. */ public boolean isSubimageSupported() { @@ -68,7 +68,7 @@ interpol = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; } } - + public int getHeight() { int h = 0; try { @@ -97,9 +97,7 @@ return w; } - /** - * load image file - */ + /* load image file */ public void loadImage(File f) throws FileOpException { util.dprintln(10, "loadImage!"); System.gc(); @@ -114,7 +112,9 @@ } } - /* Get an ImageReader for the image file. */ + /** Get an ImageReader for the image file. + * + */ public void preloadImage(File f) throws FileOpException { System.gc(); try { @@ -130,6 +130,7 @@ util.dprintln(3, "ERROR(loadImage): unable to load file"); throw new FileOpException("Unable to load File!"); } + imgFile = f; } /* Load an image file into the Object. */ @@ -137,7 +138,7 @@ throws FileOpException { System.gc(); try { - if (reader == null) { + if ((reader == null) || (imgFile != f)) { preloadImage(f); } // set up reader parameters @@ -156,9 +157,7 @@ } } - /** - * write image of type mt to Stream - */ + /* write image of type mt to Stream */ public void writeImage(String mt, OutputStream ostream) throws FileOpException { util.dprintln(10, "writeImage!"); @@ -220,102 +219,139 @@ img = croppedImg; } - public void enhance(double mult, double add) throws ImageOpException { - /* The number of constants must match the number of bands in the image. - * We only handle 1 (greyscale) or 3 (RGB) bands. + public void enhance(float mult, float add) throws ImageOpException { + /* Only one constant should work regardless of the number of bands + * according to the JDK spec. + * Doesn't work on JDK 1.4 for OSX and Linux (at least). */ - float[] dm; - float[] da; - int ncol = img.getColorModel().getNumColorComponents(); - if (ncol == 3) { - float[] f1 = {(float)mult, (float)mult, (float)mult}; - dm = f1; - float[] f2 = {(float)add, (float)add, (float)add}; - da = f2; - } else if (ncol == 1) { - float[] f1 = {(float)mult}; - dm = f1; - float[] f2 = {(float)add}; - da = f2; - } else { - util.dprintln(2, "ERROR(enhance): unknown number of color bands ("+ncol+")"); - return; + /* RescaleOp scaleOp = + new RescaleOp( + (float)mult, (float)add, + null); + scaleOp.filter(img, img); + */ + /* The number of constants must match the number of bands in the image. + */ + int ncol = img.getColorModel().getNumColorComponents(); + float[] dm = new float[ncol]; + float[] da = new float[ncol]; + for (int i = 0; i < ncol; i++) { + dm[i] = (float) mult; + da[i] = (float) add; } - RescaleOp scaleOp = - new RescaleOp( - dm, da, - null); + RescaleOp scaleOp = new RescaleOp(dm, da, null); scaleOp.filter(img, img); - /* Operation with only one constant should work regardless of the number of bands - * according to the JDK spec. - * Doesn't work on JDK 1.4 for OSX PR10 (at least). - */ - /* - RescaleOp scaleOp = - new RescaleOp( - (float)mult, (float)add, - null); - scaleOp.filter(img, img); - */ } - - public void rotate(double angle) throws ImageOpException { - // setup rotation - double rangle = Math.toRadians(angle); - double x = getWidth()/2; - double y = getHeight()/2; - AffineTransformOp rotOp = - new AffineTransformOp( - AffineTransform.getRotateInstance(rangle, x, y), - interpol); - BufferedImage rotImg = rotOp.filter(img, null); - if (rotImg == null) { - util.dprintln(2, "ERROR: error in rotate"); - throw new ImageOpException("Unable to rotate"); + public void enhanceRGB(float[] rgbm, float[] rgba) + throws ImageOpException { + /* The number of constants must match the number of bands in the image. + * We do only 3 (RGB) bands. + */ + int ncol = img.getColorModel().getNumColorComponents(); + if ((ncol != 3) || (rgbm.length != 3) || (rgba.length != 3)) { + util.dprintln( + 2, + "ERROR(enhance): unknown number of color bands or coefficients (" + + ncol + + ")"); + return; } - img = rotImg; + RescaleOp scaleOp = new RescaleOp(rgbOrdered(rgbm), rgbOrdered(rgba), null); + scaleOp.filter(img, img); + } + + /** Ensures that the array f is in the right order to map the images RGB components. + */ + public float[] rgbOrdered(float[] fa) { + float[] fb = new float[3]; + int t = img.getType(); + if ((t == BufferedImage.TYPE_3BYTE_BGR) + || (t == BufferedImage.TYPE_4BYTE_ABGR) + || (t == BufferedImage.TYPE_4BYTE_ABGR_PRE)) { + // BGR Type (actually it looks like RBG...) + fb[0] = fa[0]; + fb[1] = fa[2]; + fb[2] = fa[1]; + } else { + fb = fa; + } + return fb; } - public void mirror(double angle) throws ImageOpException { - // setup mirror - double mx = 1; - double my = 1; - double tx = 0; - double ty = 0; - if (Math.abs(angle - 0) < epsilon) { - // 0 degree - mx = -1; - tx = getWidth(); - } else if (Math.abs(angle - 90) < epsilon) { - // 90 degree - my = -1; - ty = getHeight(); - } else if (Math.abs(angle - 180) < epsilon) { - // 180 degree - mx = -1; - tx = getWidth(); - } else if (Math.abs(angle - 270) < epsilon) { - // 270 degree - my = -1; - ty = getHeight(); - } else if (Math.abs(angle - 360) < epsilon) { - // 360 degree - mx = -1; - tx = getWidth(); - } - AffineTransformOp mirOp = - new AffineTransformOp( - new AffineTransform(mx, 0 , 0, my, tx, ty), - interpol); - BufferedImage mirImg = mirOp.filter(img, null); +public void rotate(double angle) throws ImageOpException { + // setup rotation + double rangle = Math.toRadians(angle); + double x = getWidth() / 2; + double y = getHeight() / 2; + AffineTransformOp rotOp = + new AffineTransformOp( + AffineTransform.getRotateInstance(rangle, x, y), + interpol); + BufferedImage rotImg = rotOp.filter(img, null); + + if (rotImg == null) { + util.dprintln(2, "ERROR: error in rotate"); + throw new ImageOpException("Unable to rotate"); + } + img = rotImg; +} - if (mirImg == null) { - util.dprintln(2, "ERROR: error in mirror"); - throw new ImageOpException("Unable to mirror"); - } - img = mirImg; +public void mirror(double angle) throws ImageOpException { + // setup mirror + double mx = 1; + double my = 1; + double tx = 0; + double ty = 0; + if (Math.abs(angle - 0) < epsilon) { + // 0 degree + mx = -1; + tx = getWidth(); + } else if (Math.abs(angle - 90) < epsilon) { + // 90 degree + my = -1; + ty = getHeight(); + } else if (Math.abs(angle - 180) < epsilon) { + // 180 degree + mx = -1; + tx = getWidth(); + } else if (Math.abs(angle - 270) < epsilon) { + // 270 degree + my = -1; + ty = getHeight(); + } else if (Math.abs(angle - 360) < epsilon) { + // 360 degree + mx = -1; + tx = getWidth(); } + AffineTransformOp mirOp = + new AffineTransformOp( + new AffineTransform(mx, 0, 0, my, tx, ty), + interpol); + BufferedImage mirImg = mirOp.filter(img, null); + + if (mirImg == null) { + util.dprintln(2, "ERROR: error in mirror"); + throw new ImageOpException("Unable to mirror"); + } + img = mirImg; +} + +/* check image size and type and store in DocuFile f */ +public boolean checkFile(DocuFile f) throws IOException { + // see if f is already loaded + if ((reader == null) || (imgFile != f.getFile())) { + preloadImage(f.getFile()); + } + Dimension d = new Dimension(); + d.setSize(reader.getWidth(0), reader.getHeight(0)); + f.setSize(d); +// String t = reader.getFormatName(); + String t = FileOps.mimeForFile(f.getFile()); + f.setMimetype(t); + f.setChecked(true); + return true; +} }
--- a/servlet/src/digilib/image/JAIDocuImage.java Thu Feb 27 15:07:29 2003 +0100 +++ b/servlet/src/digilib/image/JAIDocuImage.java Sun Mar 09 21:37:27 2003 +0100 @@ -318,7 +318,7 @@ } /* contrast and brightness enhancement */ - public void enhance(double mult, double add) throws ImageOpException { + public void enhance(float mult, float add) throws ImageOpException { RenderedImage enhImg; double[] ma = { mult }; double[] aa = { add };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/DocuDirCache.java Sun Mar 09 21:37:27 2003 +0100 @@ -0,0 +1,214 @@ +/* DocuDirCache.java + + Digital Image Library servlet components + + Copyright (C) 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 + + * Created on 03.03.2003 + */ + +package digilib.io; + +import java.io.File; +import java.util.Hashtable; + +/** + * @author casties + */ +public class DocuDirCache extends Hashtable { + + // names of base directories + private String[] baseDirNames = null; + // number of files in the whole cache (not reliable) + private long numFiles = 0; + // number of cache hits + private long hits = 0; + // number of cache misses + private long misses = 0; + + /* + * inherited constructors + */ + public DocuDirCache(int initialCapacity, float loadFactor) { + super(initialCapacity, loadFactor); + } + + public DocuDirCache(int initialCapacity) { + super(initialCapacity); + } + + public DocuDirCache() { + super(); + } + + /* + * new and exiting stuff + */ + + /** Constructor with array of base directory names. + * + * @param bd base directory names + */ + public DocuDirCache(String[] bd) { + super(); + baseDirNames = bd; + } + + /** Add a DocuDirectory to the cache. + * + * @param newdir + */ + public void put(DocuDirectory newdir) { + String s = newdir.getDirName(); + if (containsKey(s)) { + System.out.println("Baah, duplicate key in DocuDirectory.put!"); + } else { + super.put(s, newdir); + numFiles += newdir.size(); + } + } + + public DocuFileset getFileset(String fn, int in) { + DocuDirectory dd; + // file number is 1-based, vector index is 0-based + int n = in - 1; + // first, assume fn is a directory and look in the cache + dd = (DocuDirectory) get(fn); + if (dd == null) { + // cache miss + misses++; + // see if it's a directory + File f = new File(baseDirNames[0] + fn); + if (f.isDirectory()) { + dd = new DocuDirectory(fn, baseDirNames); + if (dd.isValid()) { + // add to the cache + put(dd); + } + } else { + // maybe it's a file + if (f.canRead()) { + // try the parent directory in the cache + dd = (DocuDirectory) get(f.getParent()); + if (dd == null) { + // try to read from disk + dd = new DocuDirectory(f.getParent(), baseDirNames); + if (dd.isValid()) { + // add to the cache + put(dd); + } else { + // invalid path + return null; + } + } + // get the file's index + n = dd.indexOf(f.getName()); + } + } + } else { + // cache hit + hits++; + } + dd.refresh(); + if (dd.isValid()) { + try { + return (DocuFileset) dd.elementAt(n); + } catch (ArrayIndexOutOfBoundsException e) { + } + } + return null; + } + + public DocuDirectory getDirectory(String fn) { + DocuDirectory dd; + // first, assume fn is a directory and look in the cache + dd = (DocuDirectory) get(fn); + if (dd == null) { + // cache miss + misses++; + // see if it's a directory + File f = new File(baseDirNames[0] + fn); + if (f.isDirectory()) { + dd = new DocuDirectory(fn, baseDirNames); + if (dd.isValid()) { + // add to the cache + put(dd); + } + } else { + // maybe it's a file + if (f.canRead()) { + // try the parent directory in the cache + dd = (DocuDirectory) get(f.getParent()); + if (dd == null) { + // try to read from disk + dd = new DocuDirectory(f.getParent(), baseDirNames); + if (dd.isValid()) { + // add to the cache + put(dd); + } else { + // invalid path + return null; + } + } + } + } + } else { + // cache hit + hits++; + } + dd.refresh(); + if (dd.isValid()) { + return dd; + } + return null; + } + + /** + * @return String[] + */ + public String[] getBaseDirNames() { + return baseDirNames; + } + + /** + * @return long + */ + public long getNumFiles() { + return numFiles; + } + + /** + * Sets the baseDirNames. + * @param baseDirNames The baseDirNames to set + */ + public void setBaseDirNames(String[] baseDirNames) { + this.baseDirNames = baseDirNames; + } + + /** + * @return long + */ + public long getHits() { + return hits; + } + + /** + * @return long + */ + public long getMisses() { + return misses; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/DocuDirectory.java Sun Mar 09 21:37:27 2003 +0100 @@ -0,0 +1,263 @@ +/* DocuDirectory -- Directory of DocuFilesets. + + Digital Image Library servlet components + + Copyright (C) 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 + + * Created on 25.02.2003 + */ + +package digilib.io; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Hashtable; +import java.util.Vector; + +/** + * @author casties + */ +public class DocuDirectory extends Vector { + + // directory object is valid (has been read) + private boolean isValid = false; + // names of base directories + private String[] baseDirNames = null; + // directory name (digilib canonical form) + private String dirName = null; + // default/hires directory + private File dir = null; + // directory metadata + private Hashtable dirMeta = null; + // time of last access of this object (not the filesystem) + private long objectATime = 0; + // time the file system directory was last modified + private long dirMTime = 0; + + /* + * inherited stuff + */ + + public DocuDirectory(int initialCapacity, int capacityIncrement) { + super(initialCapacity, capacityIncrement); + } + + public DocuDirectory(int initialCapacity) { + super(initialCapacity); + } + + public DocuDirectory(Collection c) { + super(c); + } + + /* + * new stuff + */ + + /** Constructor with directory path and set of base directories. + * + * Reads the directory at the given path appended to the base directories. + * + * @see readDir + * + * @param path digilib directory path name + * @param bd array of base directory names + */ + public DocuDirectory(String path, String[] bd) { + super(); + dirName = path; + baseDirNames = bd; + readDir(); + } + + /** Read the directory and fill this object. + * + * Clears the Vector and (re)reads all files. + * + * @return boolean the directory exists + */ + public boolean readDir() { + // clear directory first + clear(); + isValid = false; + // number of base dirs + int nb = baseDirNames.length; + // array of base dirs + File[] dirs = new File[nb]; + // the first directory has to exist + dir = new File(baseDirNames[0] + dirName); + + if (dir.isDirectory()) { + // fill array with the remaining directories + for (int j = 1; j < nb; j++) { + File d = new File(baseDirNames[j] + dirName); + if (d.isDirectory()) { + dirs[j] = d; + } + } + + File[] fl = dir.listFiles(new FileOps.ImageFileFilter()); + if (fl == null) { + // not a directory + return false; + } + // number of image files + int nf = fl.length; + if (nf > 0) { + // resize Vector + this.ensureCapacity(nf); + + // sort the file names alphabetically and iterate the list + Arrays.sort(fl); + for (int i = 0; i < nf; i++) { + String fn = fl[i].getName(); + // add the first DocuFile to a new DocuFileset + DocuFileset fs = new DocuFileset(nb); + fs.add(new DocuFile(fl[i])); + // iterate the remaining base directories + for (int j = 1; j < nb; j++) { + if (dirs[j] == null) { + continue; + } + File f = new File(dirs[j], fn); + // if the file exists, add to the DocuFileset + if (f.canRead()) { + fs.add(new DocuFile(f)); + } + } + // add the fileset to our Vector + add(fs); + fs.setParent(this); + } + } + dirMTime = dir.lastModified(); + isValid = true; + } + return isValid; + + } + + /** Check to see if the directory has been modified and reread if necessary. + * + * @return boolean the directory is valid + */ + public boolean refresh() { + if (isValid) { + if (dir.lastModified() > dirMTime) { + // on-disk modification time is more recent + readDir(); + } + touch(); + } + return isValid; + } + + /** Read directory metadata. + * + */ + public void readMeta() { + // check for directory metadata... + } + + /** Update access time. + * + * @return long time of last access. + */ + public long touch() { + long t = objectATime; + objectATime = System.currentTimeMillis(); + return t; + } + + /** Searches for the file with the name <code>fn</code>. + * + * Searches the directory for the file with the name <code>fn</code> and returns + * its index. Returns -1 if the file cannot be found. + * + * @param fn filename + * @return int index of file <code>fn</code> + */ + public int indexOf(String fn) { + // linear search -> worst performance + for (int i = 0; i < elementCount; i++) { + DocuFileset fs = (DocuFileset) get(i); + if (fs.getName().equals(fn)) { + return i; + } + } + return -1; + } + + /** Finds the DocuFileset with the name <code>fn</code>. + * + * Searches the directory for the DocuFileset with the name <code>fn</code> and returns + * it. Returns null if the file cannot be found. + * + * @param fn filename + * @return DocuFileset + */ + public DocuFileset find(String fn) { + int i = indexOf(fn); + if (i >= 0) { + return (DocuFileset) get(i); + } + return null; + } + + /** + * @return String + */ + public String getDirName() { + return dirName; + } + + /** + * @return boolean + */ + public boolean isValid() { + return isValid; + } + + /** + * @return long + */ + public long getAccessTime() { + return objectATime; + } + + /** + * @return Hashtable + */ + public Hashtable getDirMeta() { + return dirMeta; + } + + /** + * @return long + */ + public long getDirMTime() { + return dirMTime; + } + + /** + * Sets the dirMeta. + * @param dirMeta The dirMeta to set + */ + public void setDirMeta(Hashtable dirMeta) { + this.dirMeta = dirMeta; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/DocuFile.java Sun Mar 09 21:37:27 2003 +0100 @@ -0,0 +1,130 @@ +/* DocuFile.java -- digilib image file class. + + Digital Image Library servlet components + + Copyright (C) 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 + + * Created on 25.02.2003 + */ + +package digilib.io; + +import java.awt.Dimension; +import java.io.File; + +/** + * @author casties + */ +public class DocuFile { + + // file object + private File file = null; + // parent DocuFileset + private DocuFileset parent = null; + // mime file type + private String mimetype = null; + // image size in pixels + private Dimension pixelSize = null; + // image size and type are valid + private boolean checked = false; + + public DocuFile(File f) { + file = f; + } + + public String getName() { + if (file != null) { + return file.getName(); + } + return null; + } + + /** + * @return File + */ + public File getFile() { + return file; + } + + /** + * @return Dimension + */ + public Dimension getSize() { + return pixelSize; + } + + /** + * @return String + */ + public String getMimetype() { + return mimetype; + } + + /** + * Sets the file. + * @param file The file to set + */ + public void setFile(File f) { + this.file = f; + mimetype = FileOps.mimeForFile(f); + } + + /** + * Sets the imageSize. + * @param imageSize The imageSize to set + */ + public void setSize(Dimension imageSize) { + this.pixelSize = imageSize; + } + + /** + * Sets the mimetype. + * @param mimetype The mimetype to set + */ + public void setMimetype(String mimetype) { + this.mimetype = mimetype; + } + + /** + * @return DocuFileset + */ + public DocuFileset getParent() { + return parent; + } + + /** + * Sets the parent. + * @param parent The parent to set + */ + public void setParent(DocuFileset parent) { + this.parent = parent; + } + + /** + * @return boolean + */ + public boolean isChecked() { + return checked; + } + + /** + * Sets the checked. + * @param checked The checked to set + */ + public void setChecked(boolean checked) { + this.checked = checked; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/DocuFileset.java Sun Mar 09 21:37:27 2003 +0100 @@ -0,0 +1,85 @@ +/* DocuFileset -- digilib image file info class. + + Digital Image Library servlet components + + Copyright (C) 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.io; + +import java.util.Collection; +import java.util.Hashtable; +import java.util.Vector; + +/** + * @author casties + */ +public class DocuFileset extends Vector { + + // metadata + private Hashtable fileMeta = null; + // parent directory + private DocuDirectory parent = null; + + public DocuFileset(int initialCapacity, int capacityIncrement) { + super(initialCapacity, capacityIncrement); + } + + public DocuFileset(int initialCapacity) { + super(initialCapacity); + } + + public DocuFileset() { + super(); + } + + public DocuFileset(Collection c) { + super(c); + } + + /* (non-Javadoc) + * @see java.util.Collection#add(java.lang.Object) + */ + public synchronized boolean add(DocuFile f) { + f.setParent(this); + return super.add(f); + } + + public void readMeta() { + // check for file metadata... + } + + public String getName() { + if (this.elementCount > 0) { + return ((DocuFile) firstElement()).getName(); + } + return null; + } + /** + * @return DocuDirectory + */ + public DocuDirectory getParent() { + return parent; + } + + /** + * Sets the parent. + * @param parent The parent to set + */ + public void setParent(DocuDirectory parent) { + this.parent = parent; + } + +}
--- a/servlet/src/digilib/io/FileOps.java Thu Feb 27 15:07:29 2003 +0100 +++ b/servlet/src/digilib/io/FileOps.java Sun Mar 09 21:37:27 2003 +0100 @@ -78,7 +78,7 @@ } // if fn is a directory name then open directory if (f.isDirectory()) { - File[] fl = f.listFiles(new ImgFileFilter()); + File[] fl = f.listFiles(new ImageFileFilter()); Arrays.sort(fl); if ((n > 0) && (n <= fl.length)) { return fl[n - 1]; @@ -102,7 +102,7 @@ } // if fn is a directory name then return the number of files if (f.isDirectory()) { - return f.listFiles(new ImgFileFilter()).length; + return f.listFiles(new ImageFileFilter()).length; } // then fn must be something strange... return 0; @@ -161,7 +161,7 @@ /** * FileFilter for image types (helper class for getFile) */ - private class ImgFileFilter implements FileFilter { + static class ImageFileFilter implements FileFilter { public boolean accept(File f) { if (f.isFile()) {
--- a/servlet/src/digilib/servlet/DigilibConfiguration.java Thu Feb 27 15:07:29 2003 +0100 +++ b/servlet/src/digilib/servlet/DigilibConfiguration.java Sun Mar 09 21:37:27 2003 +0100 @@ -20,13 +20,20 @@ package digilib.servlet; -import digilib.auth.*; -import digilib.image.*; -import digilib.io.XMLListLoader; +import java.io.File; +import java.util.Hashtable; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + import digilib.Utils; -import javax.servlet.*; -import java.util.*; -import java.io.*; +import digilib.auth.AuthOps; +import digilib.auth.XMLAuthOps; +import digilib.image.DocuImage; +import digilib.image.DocuImageImpl; +import digilib.io.DocuDirCache; +import digilib.io.XMLListLoader; /** Class to hold the digilib servlet configuration parameters. * The parameters can be read from the digilib-config file and be passed to @@ -54,12 +61,9 @@ // image file to send if access is denied private String denyImgFileName = "/docuserver/images/icons/denied.gif"; private String denyImgParam = "denied-image"; - // base directories in order of preference (prescaled versions first) + // base directories in order of preference (prescaled versions last) private String[] baseDirs = - { - "/docuserver/scaled/small", - "/docuserver/images", - "/docuserver/scans/quellen" }; + { "/docuserver/images", "/docuserver/scaled/small" }; private String baseDirParam = "basedir-list"; // use authentication information private boolean useAuthentication = true; @@ -89,6 +93,8 @@ // degree of subsampling on image load private float subsampleDistance = 0; private String subsampleDistanceParam = "subsample-distance"; + // DocuDirCache instance + private DocuDirCache dirCache = null; /** Constructor taking a ServletConfig. * Reads the config file location from an init parameter and loads the @@ -125,7 +131,7 @@ /* * read parameters */ - + // debugLevel debugLevel = tryToGetInitParam(debugLevelParam, debugLevel); util.setDebugLevel(debugLevel); @@ -142,10 +148,12 @@ String baseDirList = tryToGetInitParam( baseDirParam, - "/docuserver/scaled/small:/docuserver/images:/docuserver/scans/quellen"); + "/docuserver/images/:/docuserver/scaled/small/"); // split list into directories String[] sa = splitPathArray(baseDirList); baseDirs = (sa != null) ? sa : baseDirs; + // directory cache + dirCache = new DocuDirCache(baseDirs); // useAuthentication useAuthentication = tryToGetInitParam(useAuthParam, useAuthentication); if (useAuthentication) { @@ -156,7 +164,8 @@ authOp = new XMLAuthOps(util, authConfPath); } // subsampleDistance - subsampleDistance = tryToGetInitParam(subsampleDistanceParam, subsampleDistance); + subsampleDistance = + tryToGetInitParam(subsampleDistanceParam, subsampleDistance); } /** @@ -174,7 +183,13 @@ // add directories into array String[] pathArray = new String[n]; for (int i = 0; i < n; i++) { - pathArray[i] = dirs.nextToken(); + String s = dirs.nextToken(); + // make shure the dir name ends with a directory separator + if (s.endsWith(File.separator)) { + pathArray[i] = s; + } else { + pathArray[i] = s + File.separator; + } } return pathArray; } @@ -336,7 +351,7 @@ String s = ""; java.util.Iterator i = java.util.Arrays.asList(baseDirs).iterator(); while (i.hasNext()) { - s += ( i.next() + "; "); + s += (i.next() + "; "); } return s; } @@ -347,6 +362,7 @@ */ public void setBaseDirs(String[] baseDirs) { this.baseDirs = baseDirs; + dirCache = new DocuDirCache(baseDirs); } /** @@ -476,4 +492,19 @@ this.subsampleDistance = subsampleDistance; } + /** + * @return DocuDirCache + */ + public DocuDirCache getDirCache() { + return dirCache; + } + + /** + * Sets the dirCache. + * @param dirCache The dirCache to set + */ + public void setDirCache(DocuDirCache dirCache) { + this.dirCache = dirCache; + } + }
--- a/servlet/src/digilib/servlet/DigilibRequest.java Thu Feb 27 15:07:29 2003 +0100 +++ b/servlet/src/digilib/servlet/DigilibRequest.java Sun Mar 09 21:37:27 2003 +0100 @@ -26,6 +26,7 @@ package digilib.servlet; +import java.io.File; import java.util.StringTokenizer; import javax.servlet.ServletRequest; @@ -73,12 +74,16 @@ 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 String rot_s; private float cont; // contrast enhancement factor - private String cont_s; + private String cont_s; private float brgt; // brightness enhancement factor - private String brgt_s; - + private String brgt_s; + private float[] rgbm; // color multiplicative factors + private String rgbm_s; + private float[] rgba; // color additive factors + private String rgba_s; + private DocuImage image; // internal DocuImage instance for this request private ServletRequest servletRequest; // internal ServletRequest @@ -109,7 +114,7 @@ String qs = ((HttpServletRequest) request).getQueryString(); if (request.getParameter("fn") != null) { setWithParamRequest(request); - } else if ((qs != null)&&(qs.indexOf("&") > -1)) { + } else if ((qs != null) && (qs.indexOf("&") > -1)) { setWithParamRequest(request); } else { setWithOldString(qs); @@ -313,6 +318,12 @@ if (brgt_s != null) { s += "&brgt=" + brgt_s; } + if (rgbm_s != null) { + s += "&rgbm=" + rgbm_s; + } + if (rgba_s != null) { + s += "&reda=" + rgba_s; + } if (pt_s != null) { s += "&pt=" + pt_s; } @@ -401,6 +412,14 @@ if (s != null) { setBrgt(s); } + s = request.getParameter("rgbm"); + if (s != null) { + setRgbm(s); + } + s = request.getParameter("rgba"); + if (s != null) { + setRgba(s); + } s = request.getParameter("pt"); if (s != null) { setPt(s); @@ -441,6 +460,10 @@ cont_s = null; brgt = 0; brgt_s = null; + rgbm = null; + rgbm_s = null; + rgba = null; + rgba_s = null; baseURL = null; image = null; servletRequest = null; @@ -476,6 +499,9 @@ cont_s = null; brgt = 0; brgt_s = null; + rgbm = null; + rgbm_s = null; + rgba = null; baseURL = null; image = null; servletRequest = null; @@ -498,14 +524,18 @@ /** The image file path to be accessed. * * The mage file path is assembled from the servlets RequestPath and - * Parameter fn. + * Parameter fn. The file path never starts with a directory separator. * - * @return String the effektive filepath. + * @return String the effective filepath. */ public String getFilePath() { String s = getRequestPath(); s += getFn(); - return s; + if (s.startsWith(File.separator)) { + return s.substring(1); + } else { + return s; + } } /* Property getter and setter */ @@ -918,7 +948,7 @@ //util.dprintln(4, "trytoGetParam(int) failed on param "+s); } } - + /** * Returns the brgt. * @return float @@ -944,4 +974,63 @@ //util.dprintln(4, "trytoGetParam(int) failed on param "+s); } } + + /** + * @return float[] + */ + public float[] getRgba() { + return rgba; + } + + /** + * @return float[] + */ + public float[] getRgbm() { + return rgbm; + } + + /** + * Sets the rgba. + * @param rgba The rgba to set + */ + public void setRgba(float[] rgba) { + this.rgba = rgba; + } + public void setRgba(String s) { + try { + String[] sa = s.split("/"); + float[] fa = new float[3]; + for (int i = 0; i < 3; i++) { + float f = Float.parseFloat(sa[i]); + fa[i] = f; + } + this.rgba_s = s; + this.rgba = fa; + } catch (Exception e) { + //util.dprintln(4, "trytoGetParam(int) failed on param "+s); + } + } + + /** + * Sets the rgbm. + * @param rgbm The rgbm to set + */ + public void setRgbm(float[] rgbm) { + this.rgbm = rgbm; + } + public void setRgbm(String s) { + try { + String[] sa = s.split("/"); + float[] fa = new float[3]; + for (int i = 0; i < 3; i++) { + float f = Float.parseFloat(sa[i]); + fa[i] = f; + } + this.rgbm_s = s; + this.rgbm = fa; + } catch (Exception e) { + //util.dprintln(4, "trytoGetParam(int) failed on param "+s); + } + } + }
--- a/servlet/src/digilib/servlet/DocumentBean.java Thu Feb 27 15:07:29 2003 +0100 +++ b/servlet/src/digilib/servlet/DocumentBean.java Sun Mar 09 21:37:27 2003 +0100 @@ -38,6 +38,8 @@ private FileOps fileOp = new FileOps(util); // use authorization database private boolean useAuthentication = true; + // DocuDirCache + private DocuDirCache dirCache = null; // DigilibConfiguration object private DigilibConfiguration dlConfig; @@ -77,6 +79,8 @@ // get util util = dlConfig.getUtil(); + // get cache + dirCache = dlConfig.getDirCache(); /* * authentication @@ -130,7 +134,7 @@ HttpServletResponse response) throws Exception { util.dprintln(10, "doAuthentication"); - if (! useAuthentication) { + if (!useAuthentication) { // shortcut if no authentication return true; } @@ -168,10 +172,11 @@ */ public int getNumPages(DigilibRequest request) throws Exception { util.dprintln(10, "getNumPages"); - return fileOp.getNumFilesVariant( - dlConfig.getBaseDirs(), - "/" + request.getFilePath(), - true); + DocuDirectory dd = dirCache.getDirectory(request.getFilePath()); + if (dd != null) { + return dd.size(); + } + return 0; } /**
--- a/servlet/src/digilib/servlet/Scaler.java Thu Feb 27 15:07:29 2003 +0100 +++ b/servlet/src/digilib/servlet/Scaler.java Sun Mar 09 21:37:27 2003 +0100 @@ -20,6 +20,7 @@ package digilib.servlet; +import java.awt.Dimension; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; @@ -39,6 +40,9 @@ import digilib.auth.AuthOps; import digilib.image.DocuImage; import digilib.image.ImageOpException; +import digilib.io.DocuDirCache; +import digilib.io.DocuFile; +import digilib.io.DocuFileset; import digilib.io.FileOpException; import digilib.io.FileOps; @@ -52,7 +56,7 @@ public class Scaler extends HttpServlet { // digilib servlet version (for all components) - public static final String dlVersion = "1.6b3"; + public static final String dlVersion = "1.8b1"; // Utils instance with debuglevel Utils util; @@ -62,6 +66,8 @@ AuthOps authOp; // ServletOps instance ServletOps servletOp; + // DocuDirCache instance + DocuDirCache dirCache; // DigilibParameters instance DigilibConfiguration dlConfig; @@ -84,11 +90,12 @@ // see if there is a Configuration instance dlConfig = (DigilibConfiguration) context.getAttribute( - "digilib.servlet.parameters"); + "digilib.servlet.configuration"); if (dlConfig == null) { // create new Configuration try { dlConfig = new DigilibConfiguration(config); + context.setAttribute("digilib.servlet.configuration", dlConfig); } catch (Exception e) { throw new ServletException(e); } @@ -104,6 +111,8 @@ fileOp = new FileOps(util); // AuthOps instance servletOp = new ServletOps(util); + // DocuDirCache instance + dirCache = dlConfig.getDirCache(); } /** Process the HTTP Get request*/ @@ -192,9 +201,12 @@ // rotation angle double paramROT = dlRequest.getRot(); // contrast enhancement - double paramCONT = dlRequest.getCont(); + float paramCONT = dlRequest.getCont(); // brightness enhancement - double paramBRGT = dlRequest.getBrgt(); + float paramBRGT = dlRequest.getBrgt(); + // color modification + float[] paramRGBM = dlRequest.getRgbm(); + float[] paramRGBA = dlRequest.getRgba(); /* operation mode: "fit": always fit to page, * "clip": send original resolution cropped, "file": send whole file (if @@ -249,7 +261,7 @@ //"big" try for all file/image actions try { - // DocuImage instance + // new DocuImage instance DocuImage docuImage = dlConfig.getDocuImageInstance(); if (docuImage == null) { throw new ImageOpException("Unable to load DocuImage class!"); @@ -297,17 +309,20 @@ } // find the file - File fileToLoad = - fileOp.getFileVariant( - dlConfig.getBaseDirs(), - loadPathName, - dlRequest.getPn(), - preScaledFirst); + DocuFile fileToLoad; + DocuFileset fileset = dirCache.getFileset(loadPathName, dlRequest.getPn()); + // simplistic selection of resolution + if (preScaledFirst) { + fileToLoad = (DocuFile)fileset.lastElement(); + } else { + fileToLoad = (DocuFile)fileset.firstElement(); + } + util.dprintln(1, "Loading: " + fileToLoad.getFile()); - util.dprintln(1, "Loading: " + fileToLoad); - - // get the source image type (if it's known) - mimeType = FileOps.mimeForFile(fileToLoad); + // check the source image + docuImage.checkFile(fileToLoad); + // get the source image type + mimeType = fileToLoad.getMimetype(); /* if autoScale and not zoomed and source is GIF/PNG * then send as is. @@ -320,7 +335,7 @@ util.dprintln(1, "Sending File as is."); - servletOp.sendFile(fileToLoad, response); + servletOp.sendFile(fileToLoad.getFile(), response); util.dprintln( 1, @@ -330,22 +345,24 @@ return; } - // finally load the file - if (docuImage.isPreloadSupported()) { - // only preload if supported - docuImage.preloadImage(fileToLoad); - } else { - docuImage.loadImage(fileToLoad); - } - /* * crop and scale the image */ + int imgWidth = 0; + int imgHeight = 0; // get image size - int imgWidth = docuImage.getWidth(); - int imgHeight = docuImage.getHeight(); - + if (fileToLoad.getSize() == null) { + // size unknown so far + imgWidth = docuImage.getWidth(); + imgHeight = docuImage.getHeight(); + // remember size + fileToLoad.setSize(new Dimension(imgWidth, imgHeight)); + } else { + imgWidth = fileToLoad.getSize().width; + imgHeight = fileToLoad.getSize().height; + } + util.dprintln(2, "IMG: " + imgWidth + "x" + imgHeight); util.dprintln( 2, @@ -520,7 +537,7 @@ } docuImage.loadSubimage( - fileToLoad, + fileToLoad.getFile(), imgArea.getBounds(), (int) subsamp); @@ -535,6 +552,8 @@ docuImage.scale(scaleXY); } else { + // else load the whole file + docuImage.loadImage(fileToLoad.getFile()); docuImage.crop( (int) areaXoff, (int) areaYoff, @@ -558,9 +577,26 @@ // contrast and brightness enhancement if ((paramCONT != 0) || (paramBRGT != 0)) { double mult = Math.pow(2, paramCONT); - docuImage.enhance(mult, paramBRGT); + docuImage.enhance((float)mult, (float)paramBRGT); } + // color modification + if ((paramRGBM != null) || (paramRGBA != null)) { + // make shure we actually have two arrays + if (paramRGBM == null) { + paramRGBM = new float[3]; + } + if (paramRGBA == null) { + paramRGBA = new float[3]; + } + // calculate "contrast" values + float[] mult = new float[3]; + for (int i = 0; i < 3; i++) { + mult[i] = (float)Math.pow(2, (double)paramRGBM[i]); + } + docuImage.enhanceRGB(mult, paramRGBA); + } + util.dprintln( 2, "time " + (System.currentTimeMillis() - startTime) + "ms");