# HG changeset patch
# User robcast
# Date 1055364688 -7200
# Node ID a32e8c80e2f2229c7049b43a0fc9d217aba32143
# Parent 1ac2c5c6ec0e15ef703a312029389c23c920d4c1
Servlet Version 1.10b1
- more intelligent handling of resolutions
- different handling of mo=lores
diff -r 1ac2c5c6ec0e -r a32e8c80e2f2 servlet/src/digilib/image/DocuImage.java
--- a/servlet/src/digilib/image/DocuImage.java Wed Jun 11 22:50:13 2003 +0200
+++ b/servlet/src/digilib/image/DocuImage.java Wed Jun 11 22:51:28 2003 +0200
@@ -14,7 +14,7 @@
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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -22,10 +22,8 @@
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.
@@ -66,17 +64,6 @@
public void loadSubimage(File f, Rectangle region, int subsample)
throws FileOpException;
- /** Checks the size and type of the DocuFile f.
- *
- * 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 checkFile(DocuFile f) throws IOException;
-
/** Writes the current image to a ServletResponse.
*
* The image is encoded to the mime-type mt
and sent to the output
diff -r 1ac2c5c6ec0e -r a32e8c80e2f2 servlet/src/digilib/image/DocuImageImpl.java
--- a/servlet/src/digilib/image/DocuImageImpl.java Wed Jun 11 22:50:13 2003 +0200
+++ b/servlet/src/digilib/image/DocuImageImpl.java Wed Jun 11 22:51:28 2003 +0200
@@ -20,15 +20,11 @@
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 DocuImage
interface.
*
@@ -123,19 +119,6 @@
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;
}
diff -r 1ac2c5c6ec0e -r a32e8c80e2f2 servlet/src/digilib/image/DocuInfo.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet/src/digilib/image/DocuInfo.java Wed Jun 11 22:51:28 2003 +0200
@@ -0,0 +1,44 @@
+/* DocuInfo -- General image information interface
+
+ 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.image;
+
+import java.io.IOException;
+
+import digilib.io.DocuFile;
+
+/**
+ * @author casties
+ *
+ */
+public interface DocuInfo {
+
+ /** Checks the size and type of the DocuFile f.
+ *
+ * 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 checkFile(DocuFile f) throws IOException;
+
+}
diff -r 1ac2c5c6ec0e -r a32e8c80e2f2 servlet/src/digilib/image/ImageLoaderDocuImage.java
--- a/servlet/src/digilib/image/ImageLoaderDocuImage.java Wed Jun 11 22:50:13 2003 +0200
+++ b/servlet/src/digilib/image/ImageLoaderDocuImage.java Wed Jun 11 22:51:28 2003 +0200
@@ -20,7 +20,6 @@
package digilib.image;
-import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
@@ -38,9 +37,7 @@
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 {
@@ -359,20 +356,4 @@
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();
- t = FileOps.mimeForFile(f.getFile());
- f.setMimetype(t);
- f.setChecked(true);
- return true;
- }
-
}
diff -r 1ac2c5c6ec0e -r a32e8c80e2f2 servlet/src/digilib/image/ImageLoaderDocuInfo.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet/src/digilib/image/ImageLoaderDocuInfo.java Wed Jun 11 22:51:28 2003 +0200
@@ -0,0 +1,54 @@
+/* ImageLoaderDocuInfo -- DocuInfo implementation using ImageLoader API
+
+ 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 11.06.2003
+ *
+ */
+package digilib.image;
+
+import java.awt.Dimension;
+import java.io.IOException;
+
+import digilib.io.DocuFile;
+import digilib.io.FileOps;
+
+/**
+ * @author casties
+ *
+ */
+public class ImageLoaderDocuInfo implements DocuInfo {
+
+ private ImageLoaderDocuImage img = new ImageLoaderDocuImage();
+
+ /* check image size and type and store in DocuFile f */
+ public boolean checkFile(DocuFile f) throws IOException {
+ // see if f is already loaded
+ if ((img.reader == null) || (img.imgFile != f.getFile())) {
+ img.preloadImage(f.getFile());
+ }
+ Dimension d =
+ new Dimension(img.reader.getWidth(0), img.reader.getHeight(0));
+ f.setSize(d);
+ String t = img.reader.getFormatName();
+ t = FileOps.mimeForFile(f.getFile());
+ f.setMimetype(t);
+ f.setChecked(true);
+ return true;
+ }
+
+}
diff -r 1ac2c5c6ec0e -r a32e8c80e2f2 servlet/src/digilib/io/DocuDirectory.java
--- a/servlet/src/digilib/io/DocuDirectory.java Wed Jun 11 22:50:13 2003 +0200
+++ b/servlet/src/digilib/io/DocuDirectory.java Wed Jun 11 22:51:28 2003 +0200
@@ -77,7 +77,10 @@
}
public DocuFileset get(int index) {
- return (list != null) ? (DocuFileset) list.get(index) : null;
+ if ((list == null)||(index >= list.size())) {
+ return null;
+ }
+ return (DocuFileset)list.get(index);
}
/** Read the directory and fill this object.
diff -r 1ac2c5c6ec0e -r a32e8c80e2f2 servlet/src/digilib/io/DocuFile.java
--- a/servlet/src/digilib/io/DocuFile.java Wed Jun 11 22:50:13 2003 +0200
+++ b/servlet/src/digilib/io/DocuFile.java Wed Jun 11 22:51:28 2003 +0200
@@ -23,6 +23,9 @@
import java.awt.Dimension;
import java.io.File;
+import java.io.IOException;
+
+import digilib.image.DocuInfo;
/**
* @author casties
@@ -51,6 +54,15 @@
return null;
}
+
+ public void check(DocuInfo info) {
+ try {
+ info.checkFile(this);
+ } catch (IOException e) {
+ checked = false;
+ }
+ }
+
/**
* @return File
*/
diff -r 1ac2c5c6ec0e -r a32e8c80e2f2 servlet/src/digilib/io/DocuFileset.java
--- a/servlet/src/digilib/io/DocuFileset.java Wed Jun 11 22:50:13 2003 +0200
+++ b/servlet/src/digilib/io/DocuFileset.java Wed Jun 11 22:51:28 2003 +0200
@@ -19,10 +19,14 @@
*/
package digilib.io;
+import java.awt.Dimension;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.ListIterator;
+import digilib.image.DocuInfo;
+
/**
* @author casties
*/
@@ -49,8 +53,8 @@
/** Adds a DocuFile to this Fileset.
*
- * The files should be added in the order of lower resolutions. The first
- * file is considered the hires "original".
+ * The files should be added in the order of higher to lower resolutions.
+ * The first file is considered the hires "original".
*
* @param f file to add
* @return true (always)
@@ -59,7 +63,7 @@
f.setParent(this);
return list.add(f);
}
-
+
/** The number of image files in this Fileset.
*
* @return number of image files
@@ -67,7 +71,7 @@
public int size() {
return (list != null) ? list.size() : 0;
}
-
+
/** Get the DocuFile at the index.
*
* @param index
@@ -76,8 +80,57 @@
public DocuFile get(int index) {
return (DocuFile) list.get(index);
}
-
-
+
+ /** Get the next smaller DocuFile than the given size.
+ *
+ * Returns the DocuFile from the set that has a width and height
+ * smaller or equal the given size.
+ * Returns null if there isn't any smaller image.
+ * Needs DocuInfo instance to checkFile().
+ *
+ * @param size
+ * @param info
+ * @return
+ */
+ public DocuFile getNextSmaller(Dimension size, DocuInfo info) {
+ for (Iterator i = getHiresIterator(); i.hasNext();) {
+ DocuFile f = (DocuFile) i.next();
+ if (!f.isChecked()) {
+ f.check(info);
+ }
+ if ((f.getSize().getHeight() <= size.getHeight())
+ && (f.getSize().getWidth() <= size.getWidth())) {
+ return f;
+ }
+ }
+ return null;
+ }
+
+ /** Get the next bigger DocuFile than the given size.
+ *
+ * Returns the DocuFile from the set that has a width and height
+ * bigger or equal the given size.
+ * Returns null if there isn't any bigger image.
+ * Needs DocuInfo instance to checkFile().
+ *
+ * @param size
+ * @param info
+ * @return
+ */
+ public DocuFile getNextBigger(Dimension size, DocuInfo info) {
+ for (ListIterator i = getLoresIterator(); i.hasPrevious();) {
+ DocuFile f = (DocuFile) i.previous();
+ if (!f.isChecked()) {
+ f.check(info);
+ }
+ if ((f.getSize().getHeight() >= size.getHeight())
+ && (f.getSize().getWidth() >= size.getWidth())) {
+ return f;
+ }
+ }
+ return null;
+ }
+
/** Get an Iterator for this Fileset starting at the highest resolution
* images.
*
@@ -86,7 +139,7 @@
public ListIterator getHiresIterator() {
return list.listIterator();
}
-
+
/** Get an Iterator for this Fileset starting at the lowest resolution
* images.
*
@@ -98,7 +151,7 @@
public ListIterator getLoresIterator() {
return list.listIterator(list.size());
}
-
+
/** Reads meta-data for this Fileset if there is any.
* (not yet implemented)
*/
@@ -116,7 +169,7 @@
}
return null;
}
-
+
/** Returns the parent DocuDirectory.
* @return DocuDirectory
*/
diff -r 1ac2c5c6ec0e -r a32e8c80e2f2 servlet/src/digilib/servlet/Scaler.java
--- a/servlet/src/digilib/servlet/Scaler.java Wed Jun 11 22:50:13 2003 +0200
+++ b/servlet/src/digilib/servlet/Scaler.java Wed Jun 11 22:51:28 2003 +0200
@@ -39,6 +39,8 @@
import digilib.auth.AuthOpException;
import digilib.auth.AuthOps;
import digilib.image.DocuImage;
+import digilib.image.DocuInfo;
+import digilib.image.ImageLoaderDocuInfo;
import digilib.image.ImageOpException;
import digilib.io.DocuDirCache;
import digilib.io.DocuFile;
@@ -56,7 +58,7 @@
public class Scaler extends HttpServlet {
// digilib servlet version (for all components)
- public static final String dlVersion = "1.9b3";
+ public static final String dlVersion = "1.10b1";
// Utils instance with debuglevel
Utils util;
@@ -168,12 +170,12 @@
boolean scaleToFit = true;
// scale the image by a fixed factor only
boolean absoluteScale = false;
- // crop the image if needed
- boolean cropToFit = true;
- // use heuristics (GIF?) to scale or send as is
- boolean autoScale = true;
- // try prescaled images first
- boolean preScaledFirst = true;
+ // only crop the image to fit
+ boolean cropToFit = false;
+ // try different resolution images automatically
+ boolean autoRes = true;
+ // use hires images (if autoRes == false)
+ boolean hiresOnly = false;
// interpolation to use for scaling
int scaleQual = 0;
// send html error message (or image file)
@@ -194,6 +196,13 @@
int paramDW = dlRequest.getDw();
// destination image height
int paramDH = dlRequest.getDh();
+ // dw and dh shouldn't be empty, if they are, set dw=dh
+ if (paramDW <= 0) {
+ paramDW = paramDH;
+ }
+ if (paramDH <= 0) {
+ paramDH = paramDW;
+ }
// relative area x_offset (0..1)
double paramWX = dlRequest.getWx();
// relative area y_offset
@@ -222,29 +231,29 @@
scaleToFit = false;
absoluteScale = false;
cropToFit = true;
- autoScale = false;
- preScaledFirst = false;
+ autoRes = true;
} else if (dlRequest.isOption("fit")) {
scaleToFit = true;
absoluteScale = false;
- cropToFit = true;
- autoScale = false;
+ cropToFit = false;
+ autoRes = true;
} else if (dlRequest.isOption("scale")) {
scaleToFit = false;
absoluteScale = true;
- cropToFit = true;
- autoScale = false;
- preScaledFirst = false;
+ cropToFit = false;
+ autoRes = false;
+ hiresOnly = true;
} else if (dlRequest.isOption("file")) {
scaleToFit = false;
absoluteScale = false;
if (dlConfig.isSendFileAllowed()) {
cropToFit = false;
} else {
+ // crop to fit if send file not allowed
cropToFit = true;
}
- autoScale = false;
- preScaledFirst = false;
+ autoRes = false;
+ hiresOnly = true;
}
// operation mode: "errtxt": error message in html, "errimg": error image
if (dlRequest.isOption("errtxt")) {
@@ -261,10 +270,15 @@
scaleQual = 2;
}
// operation mode: "lores": try to use scaled image, "hires": use unscaled image
+ // "autores": try best fitting resolution
if (dlRequest.isOption("lores")) {
- preScaledFirst = true;
+ autoRes = false;
+ hiresOnly = false;
} else if (dlRequest.isOption("hires")) {
- preScaledFirst = false;
+ autoRes = false;
+ hiresOnly = true;
+ } else if (dlRequest.isOption("autores")) {
+ autoRes = true;
}
//"big" try for all file/image actions
@@ -276,6 +290,9 @@
throw new ImageOpException("Unable to load DocuImage class!");
}
+ // new DocuInfo instance
+ DocuInfo docuInfo = new ImageLoaderDocuInfo();
+
// set interpolation quality
docuImage.setQuality(scaleQual);
@@ -313,7 +330,7 @@
}
}
- // find the file
+ // find the file(set)
DocuFile fileToLoad;
DocuFileset fileset =
dirCache.getFileset(loadPathName, dlRequest.getPn());
@@ -326,36 +343,69 @@
+ ") not found.");
}
- // if it's zoomed, try hires version (to be optimized...)
- if ((paramWW < 1f) || (paramWH < 1f)) {
- preScaledFirst = false;
+ /*
+ * calculate expected source image size
+ *
+ */
+ Dimension expectedSourceSize = new Dimension();
+ if (scaleToFit) {
+ double scale = (1 / Math.min(paramWW, paramWH)) * paramWS;
+ expectedSourceSize.setSize(paramDW * scale, paramDH * scale);
+ } else {
+ expectedSourceSize.setSize(
+ paramDW * paramWS,
+ paramDH * paramWS);
}
- // simplistic selection of resolution
- if (preScaledFirst) {
- // get last element
- fileToLoad = fileset.get(fileset.size() - 1);
+ /*
+ * select a resolution
+ */
+ if (autoRes) {
+ // autores: use next bigger resolution
+ fileToLoad =
+ fileset.getNextBigger(expectedSourceSize, docuInfo);
+ if (fileToLoad == null) {
+ // this is the biggest we have
+ fileToLoad = fileset.get(0);
+ }
} else {
- // get first element
- fileToLoad = fileset.get(0);
+ // enforced hires or lores
+ if (hiresOnly) {
+ // get first element
+ fileToLoad = fileset.get(0);
+ } else {
+ // enforced lores uses next smaller resolution
+ fileToLoad =
+ fileset.getNextSmaller(expectedSourceSize, docuInfo);
+ if (fileToLoad == null) {
+ // this is the smallest we have
+ fileToLoad = fileset.get(fileset.size() - 1);
+ }
+ }
}
util.dprintln(1, "Loading: " + fileToLoad.getFile());
// check the source image
- docuImage.checkFile(fileToLoad);
+ if (!fileToLoad.isChecked()) {
+ fileToLoad.check(docuInfo);
+ }
// get the source image type
mimeType = fileToLoad.getMimetype();
+ boolean imageSendable =
+ mimeType.equals("image/jpeg")
+ || mimeType.equals("image/png")
+ || mimeType.equals("image/gif");
- /* if autoScale and not zoomed and source is GIF/PNG
- * then send as is.
+ /* if not autoRes and image smaller than requested
+ * size then send as is.
* if not autoScale and not scaleToFit nor cropToFit
- * then send as is
+ * then send as is (mo=file)
*/
- if ((autoScale
- && (mimeType == "image/gif" || mimeType == "image/png")
- && (paramWW == 1f)
- && (paramWH == 1f))
- || (!autoScale && !scaleToFit && !cropToFit)) {
+ if ((!autoRes
+ && imageSendable
+ && (fileToLoad.getSize().width <= expectedSourceSize.width)
+ && (fileToLoad.getSize().height <= expectedSourceSize.height))
+ || (!autoRes && !scaleToFit && !cropToFit)) {
util.dprintln(1, "Sending File as is.");