# HG changeset patch
# User robcast
# Date 1374253719 -7200
# Node ID a6532856dae1325873df073647a0e4bf5d6b4bb7
# Parent 5d0eeccca1d97d3830303f464fc7202b2bb3cea7
IIIF region in pixel units works now.
small cleanups.
diff -r 5d0eeccca1d9 -r a6532856dae1 common/src/main/java/digilib/conf/DigilibRequest.java
--- a/common/src/main/java/digilib/conf/DigilibRequest.java Fri Jul 19 14:08:29 2013 +0200
+++ b/common/src/main/java/digilib/conf/DigilibRequest.java Fri Jul 19 19:08:39 2013 +0200
@@ -55,7 +55,7 @@
* wh: height of image area(float from 0 to 1).
* ws: scale factor.
* mo: special options like 'fit'.
- * ...et alii
+ * ...et al
*
* @author casties
*
@@ -88,8 +88,7 @@
}
/**
- * set up parameters.
- *
+ * Define and set up parameters with default values.
*/
protected void initParams() {
/*
@@ -266,7 +265,7 @@
}
/**
- * Populate a request from a string with an IIIF Image API path.
+ * Populate a request from a string with an IIIF image API path.
*
* path should be non-URL-decoded and have no leading slash.
*
@@ -285,7 +284,9 @@
// enable passing of delimiter to get empty parameters
StringTokenizer query = new StringTokenizer(path, "/", true);
String token;
- // first parameter prefix
+ /*
+ * first parameter prefix
+ */
if (query.hasMoreTokens()) {
token = query.nextToken();
if (!token.equals(iiifPrefix)) {
@@ -297,7 +298,9 @@
query.nextToken();
}
}
- // second parameter FN (encoded)
+ /*
+ * second parameter FN (encoded)
+ */
if (query.hasMoreTokens()) {
token = query.nextToken();
if (!token.equals("/")) {
@@ -312,7 +315,9 @@
}
}
}
- // third parameter region
+ /*
+ * third parameter region
+ */
if (query.hasMoreTokens()) {
token = query.nextToken();
if (!token.equals("/")) {
@@ -323,7 +328,7 @@
} else if (token.equals("full")) {
// full region -- default
} else if (token.startsWith("pct:")){
- // region in % of original image
+ // pct:x,y,w,h -- region in % of original image
String[] parms = token.substring(4).split(",");
try {
float x = Float.parseFloat(parms[0]);
@@ -338,8 +343,17 @@
logger.error("Error parsing range parameter in IIIF path!", e);
}
} else {
- // region in pixel of original image :-(
- logger.error("pixel region not yet implemented");
+ // x,y,w,h -- region in pixel of original image :-(
+ String[] parms = token.split(",");
+ if (parms.length != 4) {
+ logger.error("Error parsing range parameter in IIIF path!");
+ } else {
+ options.setOption("pxarea");
+ setValueFromString("wx", parms[0]);
+ setValueFromString("wy", parms[1]);
+ setValueFromString("ww", parms[2]);
+ setValueFromString("wh", parms[3]);
+ }
}
// skip /
if (query.hasMoreTokens()) {
@@ -351,7 +365,9 @@
options.setOption("info");
return;
}
- // fourth parameter size
+ /*
+ * fourth parameter size
+ */
if (query.hasMoreTokens()) {
token = query.nextToken();
if (!token.equals("/")) {
@@ -401,7 +417,9 @@
setValue("scale", 1f);
return;
}
- // fifth parameter rotation
+ /*
+ * fifth parameter rotation
+ */
if (query.hasMoreTokens()) {
token = query.nextToken();
if (!token.equals("/")) {
@@ -412,7 +430,9 @@
}
}
}
- // sixth parameter quality.format
+ /*
+ * sixth parameter quality.format
+ */
if (query.hasMoreTokens()) {
token = query.nextToken();
// quality.format -- color depth and output format
diff -r 5d0eeccca1d9 -r a6532856dae1 common/src/main/java/digilib/image/ImageJobDescription.java
--- a/common/src/main/java/digilib/image/ImageJobDescription.java Fri Jul 19 14:08:29 2013 +0200
+++ b/common/src/main/java/digilib/image/ImageJobDescription.java Fri Jul 19 19:08:39 2013 +0200
@@ -47,7 +47,7 @@
import digilib.util.ParameterMap;
/**
- * A class for storing the set of parameters necessary for scaling images
+ * A class for storing the set of parameters necessary for scaling images
* with an ImageWorker.
*
* This contains the functionality formerly found in Scaler.processRequest(),
@@ -58,107 +58,119 @@
*/
public class ImageJobDescription extends ParameterMap {
-
- DigilibConfiguration dlConfig = null;
- protected static Logger logger = Logger.getLogger("digilib.servlet");
+
+ DigilibConfiguration dlConfig = null;
+ protected static Logger logger = Logger.getLogger("digilib.servlet");
- ImageInput input = null;
- ImageSet imageSet = null;
- DocuDirectory fileDir = null;
- DocuImage docuImage = null;
- String filePath = null;
- ImageSize expectedSourceSize = null;
- Float scaleXY = null;
- Rectangle2D userImgArea = null;
- Rectangle2D outerUserImgArea = null;
- Boolean imageSendable = null;
- String mimeType = null;
- Integer paramDW = null;
- Integer paramDH = null;
+ /*
+ * variables for caching values
+ */
+ ImageInput input = null;
+ ImageSet imageSet = null;
+ DocuDirectory fileDir = null;
+ DocuImage docuImage = null;
+ String filePath = null;
+ ImageSize expectedSourceSize = null;
+ Float scaleXY = null;
+ Rectangle2D userImgArea = null;
+ Rectangle2D outerUserImgArea = null;
+ Boolean imageSendable = null;
+ String mimeType = null;
+ Integer paramDW = null;
+ Integer paramDH = null;
- /** create empty ImageJobDescription.
- * @param dlcfg
- */
- public ImageJobDescription(DigilibConfiguration dlcfg) {
- super(30);
- dlConfig = dlcfg;
- }
-
+ /**
+ * create empty ImageJobDescription.
+ *
+ * @param dlcfg
+ */
+ public ImageJobDescription(DigilibConfiguration dlcfg) {
+ super(30);
+ dlConfig = dlcfg;
+ }
- /** set up Parameters
- * @see digilib.util.ParameterMap#initParams()
- */
- @Override
- protected void initParams() {
- // url of the page/document (second part)
- newParameter("fn", "", null, 's');
- // page number
- newParameter("pn", new Integer(1), null, 's');
- // width of client in pixels
- newParameter("dw", new Integer(0), null, 's');
- // height of client in pixels
- newParameter("dh", new Integer(0), null, 's');
- // left edge of image (float from 0 to 1)
- newParameter("wx", new Float(0), null, 's');
- // top edge in image (float from 0 to 1)
- newParameter("wy", new Float(0), null, 's');
- // width of image (float from 0 to 1)
- newParameter("ww", new Float(1), null, 's');
- // height of image (float from 0 to 1)
- newParameter("wh", new Float(1), null, 's');
- // scale factor
- newParameter("ws", new Float(1), null, 's');
- // special options like 'fit' for gifs
- newParameter("mo", this.options, null, 's');
- // rotation angle (degree)
- newParameter("rot", new Float(0), null, 's');
- // contrast enhancement factor
- newParameter("cont", new Float(0), null, 's');
- // brightness enhancement factor
- newParameter("brgt", new Float(0), null, 's');
- // color multiplicative factors
- newParameter("rgbm", "0/0/0", null, 's');
- // color additive factors
- newParameter("rgba", "0/0/0", null, 's');
- // display dpi resolution (total)
- newParameter("ddpi", new Float(0), null, 's');
- // display dpi X resolution
- newParameter("ddpix", new Float(0), null, 's');
- // display dpi Y resolution
- newParameter("ddpiy", new Float(0), null, 's');
- // scale factor for mo=ascale
- newParameter("scale", new Float(1), null, 's');
- // color conversion operation
- newParameter("colop", "", null, 's');
- }
+ /**
+ * set up Parameters
+ *
+ * @see digilib.util.ParameterMap#initParams()
+ */
+ @Override
+ protected void initParams() {
+ // url of the page/document (second part)
+ newParameter("fn", "", null, 's');
+ // page number
+ newParameter("pn", new Integer(1), null, 's');
+ // width of client in pixels
+ newParameter("dw", new Integer(0), null, 's');
+ // height of client in pixels
+ newParameter("dh", new Integer(0), null, 's');
+ // left edge of image (float from 0 to 1)
+ newParameter("wx", new Float(0), null, 's');
+ // top edge in image (float from 0 to 1)
+ newParameter("wy", new Float(0), null, 's');
+ // width of image (float from 0 to 1)
+ newParameter("ww", new Float(1), null, 's');
+ // height of image (float from 0 to 1)
+ newParameter("wh", new Float(1), null, 's');
+ // scale factor
+ newParameter("ws", new Float(1), null, 's');
+ // special options like 'fit' for gifs
+ newParameter("mo", this.options, null, 's');
+ // rotation angle (degree)
+ newParameter("rot", new Float(0), null, 's');
+ // contrast enhancement factor
+ newParameter("cont", new Float(0), null, 's');
+ // brightness enhancement factor
+ newParameter("brgt", new Float(0), null, 's');
+ // color multiplicative factors
+ newParameter("rgbm", "0/0/0", null, 's');
+ // color additive factors
+ newParameter("rgba", "0/0/0", null, 's');
+ // display dpi resolution (total)
+ newParameter("ddpi", new Float(0), null, 's');
+ // display dpi X resolution
+ newParameter("ddpix", new Float(0), null, 's');
+ // display dpi Y resolution
+ newParameter("ddpiy", new Float(0), null, 's');
+ // scale factor for mo=ascale
+ newParameter("scale", new Float(1), null, 's');
+ // color conversion operation
+ newParameter("colop", "", null, 's');
+ }
-
- /* (non-Javadoc)
- * @see digilib.servlet.ParameterMap#initOptions()
- */
- @Override
- protected void initOptions() {
- String s = this.getAsString("mo");
- options = new OptionsSet(s);
- }
-
+ /*
+ * (non-Javadoc)
+ *
+ * @see digilib.servlet.ParameterMap#initOptions()
+ */
+ @Override
+ protected void initOptions() {
+ String s = this.getAsString("mo");
+ options = new OptionsSet(s);
+ }
- /** Creates new ImageJobDescription by merging Parameters from a DigilibRequest.
- * @param dlReq
- * @param dlcfg
- * @return
- */
- public static ImageJobDescription getInstance(DigilibRequest dlReq, DigilibConfiguration dlcfg) {
- ImageJobDescription newMap = new ImageJobDescription(dlcfg);
- // add all params to this map
- newMap.params.putAll(dlReq.getParams());
- newMap.initOptions();
- // add ImageJobDescription back into DigilibRequest
- dlReq.setJobDescription(newMap);
- return newMap;
- }
+ /**
+ * Creates new ImageJobDescription by merging Parameters from a
+ * DigilibRequest.
+ *
+ * @param dlReq
+ * @param dlcfg
+ * @return
+ */
+ public static ImageJobDescription getInstance(DigilibRequest dlReq, DigilibConfiguration dlcfg) {
+ ImageJobDescription newMap = new ImageJobDescription(dlcfg);
+ // add all params to this map
+ newMap.params.putAll(dlReq.getParams());
+ newMap.initOptions();
+ // add ImageJobDescription back into DigilibRequest
+ dlReq.setJobDescription(newMap);
+ return newMap;
+ }
- /** Creates new ImageJobDescription by merging Parameters from another ParameterMap.
+ /**
+ * Creates new ImageJobDescription by merging Parameters from another
+ * ParameterMap.
+ *
* @param pm
* @param dlcfg
* @return
@@ -171,410 +183,439 @@
return newMap;
}
-
- /** Returns the mime-type (of the input).
- * @return
- * @throws IOException
- */
- public String getMimeType() throws IOException {
- if (mimeType == null) {
- input = getInput();
- mimeType = input.getMimetype();
- }
- return mimeType;
- }
-
- /**
- * @param input the input to set
+ /**
+ * Returns the mime-type (of the input).
+ *
+ * @return
+ * @throws IOException
+ */
+ public String getMimeType() throws IOException {
+ if (mimeType == null) {
+ input = getInput();
+ mimeType = input.getMimetype();
+ }
+ return mimeType;
+ }
+
+ /**
+ * @param input
+ * the input to set
*/
public void setInput(ImageInput input) {
this.input = input;
}
+ /**
+ * Returns the ImageInput to use.
+ *
+ * @return
+ * @throws IOException
+ */
+ public ImageInput getInput() throws IOException {
+ if (input == null) {
+ imageSet = getImageSet();
- /** Returns the ImageInput to use.
- * @return
- * @throws IOException
- */
- public ImageInput getInput() throws IOException {
- if(input == null){
- imageSet = getImageSet();
-
- /* select a resolution */
- if (isHiresOnly()) {
- // get first element (= highest resolution)
- input = imageSet.getBiggest();
- } else if (isLoresOnly()) {
- // enforced lores uses next smaller resolution
- input = imageSet.getNextSmaller(getExpectedSourceSize());
- if (input == null) {
- // this is the smallest we have
- input = imageSet.getSmallest();
- }
- } else {
- // autores: use next higher resolution
- input = imageSet.getNextBigger(getExpectedSourceSize());
- if (input == null) {
- // this is the highest we have
- input = imageSet.getBiggest();
- }
- }
- if (input == null || input.getMimetype() == null) {
- throw new FileOpException("Unable to load "+input);
- }
+ /* select a resolution */
+ if (isHiresOnly()) {
+ // get first element (= highest resolution)
+ input = imageSet.getBiggest();
+ } else if (isLoresOnly()) {
+ // enforced lores uses next smaller resolution
+ input = imageSet.getNextSmaller(getExpectedSourceSize());
+ if (input == null) {
+ // this is the smallest we have
+ input = imageSet.getSmallest();
+ }
+ } else {
+ // autores: use next higher resolution
+ input = imageSet.getNextBigger(getExpectedSourceSize());
+ if (input == null) {
+ // this is the highest we have
+ input = imageSet.getBiggest();
+ }
+ }
+ if (input == null || input.getMimetype() == null) {
+ throw new FileOpException("Unable to load " + input);
+ }
logger.info("Planning to load: " + input);
- }
- return input;
- }
-
- /** Returns the DocuDirectory for the input (file).
- * @return
- * @throws FileOpException
- */
- public DocuDirectory getFileDirectory() throws FileOpException {
- if(fileDir == null){
- DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
- String fp = getFilePath();
- fileDir = dirCache.getDirectory(fp);
- if (fileDir == null) {
- throw new FileOpException("Directory " + getFilePath() + " not found.");
- }
- }
- return fileDir;
- }
-
- /** Returns the ImageSet to load.
+ }
+ return input;
+ }
+
+ /**
+ * Returns the DocuDirectory for the input (file).
+ *
+ * @return
+ * @throws FileOpException
+ */
+ public DocuDirectory getFileDirectory() throws FileOpException {
+ if (fileDir == null) {
+ DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
+ String fp = getFilePath();
+ fileDir = dirCache.getDirectory(fp);
+ if (fileDir == null) {
+ throw new FileOpException("Directory " + getFilePath() + " not found.");
+ }
+ }
+ return fileDir;
+ }
+
+ /**
+ * Returns the ImageSet to load.
+ *
* @return
* @throws FileOpException
*/
public ImageSet getImageSet() throws FileOpException {
- if(imageSet==null){
+ if (imageSet == null) {
DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
-
+
imageSet = (ImageSet) dirCache.getFile(getFilePath(), getAsInt("pn"), FileClass.IMAGE);
if (imageSet == null) {
- throw new FileOpException("File " + getFilePath() + "("
- + getAsInt("pn") + ") not found.");
+ throw new FileOpException("File " + getFilePath() + "(" + getAsInt("pn") + ") not found.");
}
}
return imageSet;
}
-
- /** Returns the file path name from the request.
- * @return
- */
- public String getFilePath() {
- if(filePath == null){
- String s = this.getAsString("request.path");
- s += this.getAsString("fn");
- filePath = FileOps.normalName(s);
- }
- return filePath;
- }
+
+ /**
+ * Returns the file path name from the request.
+ *
+ * @return
+ */
+ public String getFilePath() {
+ if (filePath == null) {
+ String s = this.getAsString("request.path");
+ s += this.getAsString("fn");
+ filePath = FileOps.normalName(s);
+ }
+ return filePath;
+ }
- public boolean isHiresOnly(){
- return hasOption("clip") || hasOption("hires");
- }
-
- public boolean isLoresOnly(){
- return hasOption("lores");
- }
+ public boolean isHiresOnly() {
+ return hasOption("clip") || hasOption("hires") || hasOption("pxarea");
+ }
+
+ public boolean isLoresOnly() {
+ return hasOption("lores");
+ }
- public boolean isScaleToFit() {
- return !(hasOption("clip") || hasOption("osize") || hasOption("ascale"));
- }
+ public boolean isScaleToFit() {
+ return !(hasOption("clip") || hasOption("osize") || hasOption("ascale"));
+ }
+
+ public boolean isAbsoluteScale() {
+ return hasOption("osize") || hasOption("ascale");
+ }
- public boolean isAbsoluteScale(){
- return hasOption("osize") || hasOption("ascale");
- }
-
-
- /** Returns the minimum size the source image should have for scaling.
- * @return
- * @throws IOException
- */
- public ImageSize getExpectedSourceSize() throws IOException {
- if (expectedSourceSize == null){
- expectedSourceSize = new ImageSize();
- if (isScaleToFit()) {
- // scale to fit -- calculate minimum source size
- float scale = (1 / Math.min(getAsFloat("ww"), getAsFloat("wh"))) * getAsFloat("ws");
- expectedSourceSize.setSize((int) (getDw() * scale),
- (int) (getDh() * scale));
- } else if (isAbsoluteScale() && hasOption("ascale")) {
- // absolute scale -- apply scale to hires size
- expectedSourceSize = getHiresSize().getScaled(getAsFloat("scale"));
- } else {
- // clip to fit -- source = destination size
- expectedSourceSize.setSize((int) (getDw() * getAsFloat("ws")),
- (int) (getDh() * getAsFloat("ws")));
- }
- }
- return expectedSourceSize;
- }
-
- /** Returns the size of the highest resolution image.
- * @return
- * @throws IOException
- */
- public ImageSize getHiresSize() throws IOException {
- logger.debug("get_hiresSize()");
+ /**
+ * Returns the minimum size the source image should have for scaling.
+ *
+ * @return
+ * @throws IOException
+ */
+ public ImageSize getExpectedSourceSize() throws IOException {
+ if (expectedSourceSize == null) {
+ expectedSourceSize = new ImageSize();
+ if (isScaleToFit()) {
+ // scale to fit -- calculate minimum source size
+ float scale = (1 / Math.min(getAsFloat("ww"), getAsFloat("wh"))) * getAsFloat("ws");
+ expectedSourceSize.setSize((int) (getDw() * scale), (int) (getDh() * scale));
+ } else if (isAbsoluteScale() && hasOption("ascale")) {
+ // absolute scale -- apply scale to hires size
+ expectedSourceSize = getHiresSize().getScaled(getAsFloat("scale"));
+ } else {
+ // clip to fit -- source = destination size
+ expectedSourceSize.setSize((int) (getDw() * getAsFloat("ws")), (int) (getDh() * getAsFloat("ws")));
+ }
+ }
+ return expectedSourceSize;
+ }
+
+ /**
+ * Returns the size of the highest resolution image.
+ *
+ * @return
+ * @throws IOException
+ */
+ public ImageSize getHiresSize() throws IOException {
+ logger.debug("get_hiresSize()");
+
+ ImageSize hiresSize = null;
+ ImageSet fileset = getImageSet();
+ if (isAbsoluteScale()) {
+ ImageInput hiresFile = fileset.getBiggest();
+ hiresSize = hiresFile.getSize();
+ }
+ return hiresSize;
+ }
+
+ /**
+ * Returns image scaling factor.
+ * Uses image size and user parameters.
+ * Modifies scaleXY, userImgArea.
+ *
+ * @return
+ * @throws IOException
+ * @throws ImageOpException
+ */
+ public float getScaleXY() throws IOException, ImageOpException {
+ // logger.debug("get_scaleXY()");
+ if (scaleXY != null) {
+ return (float) scaleXY;
+ }
+
+ /*
+ * calculate region of interest
+ */
+ float areaWidth;
+ float areaHeight;
+ // size of the currently selected input image
+ ImageSize imgSize = getInput().getSize();
+ if (!options.hasOption("pxarea")) {
+ // user area is in [0,1] coordinates
+ Rectangle2D relUserArea = new Rectangle2D.Float(getAsFloat("wx"), getAsFloat("wy"), getAsFloat("ww"), getAsFloat("wh"));
+ // transform from relative [0,1] to image coordinates.
+ AffineTransform imgTrafo = AffineTransform.getScaleInstance(imgSize.getWidth(), imgSize.getHeight());
+ // transform user coordinate area to image coordinate area
+ userImgArea = imgTrafo.createTransformedShape(relUserArea).getBounds2D();
+ } else {
+ // ugly: user area in pixel coordinates
+ userImgArea = new Rectangle2D.Float(getAsFloat("wx"), getAsFloat("wy"), getAsFloat("ww"), getAsFloat("wh"));
+ }
- ImageSize hiresSize = null;
- ImageSet fileset = getImageSet();
- if (isAbsoluteScale()) {
- ImageInput hiresFile = fileset.getBiggest();
- hiresSize = hiresFile.getSize();
- }
- return hiresSize;
- }
-
- /** Returns image scaling factor.
- * Uses image size and user parameters.
- * Modifies scaleXY, userImgArea.
- * @return
- * @throws IOException
- * @throws ImageOpException
- */
- public float getScaleXY() throws IOException, ImageOpException {
- //logger.debug("get_scaleXY()");
- if(scaleXY == null){
- // coordinates and scaling
- float areaWidth;
- float areaHeight;
- float ws = getAsFloat("ws");
- ImageSize imgSize = getInput().getSize();
- // user window area in [0,1] coordinates
- Rectangle2D relUserArea = new Rectangle2D.Float(getAsFloat("wx"), getAsFloat("wy"),
- getAsFloat("ww"), getAsFloat("wh"));
- // transform from relative [0,1] to image coordinates.
- AffineTransform imgTrafo = AffineTransform.getScaleInstance(imgSize
- .getWidth(), imgSize.getHeight());
- // transform user coordinate area to image coordinate area
- userImgArea = imgTrafo.createTransformedShape(
- relUserArea).getBounds2D();
-
- if (isScaleToFit()) {
- // calculate scaling factors based on inner user area
- areaWidth = (float) userImgArea.getWidth();
- areaHeight = (float) userImgArea.getHeight();
- float scaleX = getDw() / areaWidth * ws;
- float scaleY = getDh() / areaHeight * ws;
- scaleXY = (scaleX > scaleY) ? scaleY : scaleX;
- } else if (isAbsoluteScale()) {
- // absolute scaling factor
- if (hasOption("osize")) {
- // get original resolution from metadata
- imageSet.checkMeta();
- float origResX = imageSet.getResX();
- float origResY = imageSet.getResY();
- if ((origResX == 0) || (origResY == 0)) {
- throw new ImageOpException("Missing image DPI information!");
- }
- float ddpix = getAsFloat("ddpix");
- float ddpiy = getAsFloat("ddpiy");
- if (ddpix == 0 || ddpiy == 0) {
- float ddpi = getAsFloat("ddpi");
- if (ddpi == 0) {
- throw new ImageOpException("Missing display DPI information!");
- } else {
- ddpix = ddpi;
- ddpiy = ddpi;
- }
- }
- // calculate absolute scale factor
- float sx = ddpix / origResX;
- float sy = ddpiy / origResY;
- // currently only same scale -- mean value
- scaleXY = (sx + sy) / 2f;
- } else {
- // absolute scale factor
- scaleXY = getAsFloat("scale");
- // use original size if no destination size given
- if (getDw() == 0 && getDh() == 0) {
- paramDW = (int) userImgArea.getWidth();
- paramDH = (int) userImgArea.getHeight();
- }
- }
- // we need to correct the factor if we use a pre-scaled image
- ImageSize hiresSize = getHiresSize();
- if (imgSize.getWidth() != hiresSize.getWidth()) {
- scaleXY *= (float)hiresSize.getWidth() / (float)imgSize.getWidth();
- }
- areaWidth = getDw() / scaleXY * ws;
- areaHeight = getDh() / scaleXY * ws;
- // reset user area size
- userImgArea.setRect(userImgArea.getX(), userImgArea.getY(),
- areaWidth, areaHeight);
- } else {
- // crop to fit -- don't scale
- areaWidth = getDw() * ws;
- areaHeight = getDh() * ws;
- // reset user area size
- userImgArea.setRect(userImgArea.getX(), userImgArea.getY(),
- areaWidth, areaHeight);
- scaleXY = 1f;
- }
- }
- return (float) scaleXY;
- }
-
- /** Returns the width of the destination image.
- * Uses dh parameter and aspect ratio if dw parameter is empty.
- * @return
- * @throws IOException
- */
- public int getDw() throws IOException {
- logger.debug("get_paramDW()");
- if (paramDW == null) {
+ /*
+ * calculate scaling factor
+ */
+ float ws = getAsFloat("ws");
+ if (isScaleToFit()) {
+ /*
+ * scale to fit -- scaling factor based on destination size and user area
+ */
+ areaWidth = (float) userImgArea.getWidth();
+ areaHeight = (float) userImgArea.getHeight();
+ float scaleX = getDw() / areaWidth * ws;
+ float scaleY = getDh() / areaHeight * ws;
+ scaleXY = (scaleX > scaleY) ? scaleY : scaleX;
+ } else if (isAbsoluteScale()) {
+ /*
+ * absolute scaling factor -- either original size, based on dpi, or absolute
+ */
+ if (hasOption("osize")) {
+ // get original resolution from metadata
+ imageSet.checkMeta();
+ float origResX = imageSet.getResX();
+ float origResY = imageSet.getResY();
+ if ((origResX == 0) || (origResY == 0)) {
+ throw new ImageOpException("Missing image DPI information!");
+ }
+ float ddpix = getAsFloat("ddpix");
+ float ddpiy = getAsFloat("ddpiy");
+ if (ddpix == 0 || ddpiy == 0) {
+ float ddpi = getAsFloat("ddpi");
+ if (ddpi == 0) {
+ throw new ImageOpException("Missing display DPI information!");
+ } else {
+ ddpix = ddpi;
+ ddpiy = ddpi;
+ }
+ }
+ // calculate absolute scale factor
+ float sx = ddpix / origResX;
+ float sy = ddpiy / origResY;
+ // currently only same scale -- mean value
+ scaleXY = (sx + sy) / 2f;
+ } else {
+ // absolute scale factor
+ scaleXY = getAsFloat("scale");
+ // use original size if no destination size given
+ if (getDw() == 0 && getDh() == 0) {
+ paramDW = (int) userImgArea.getWidth();
+ paramDH = (int) userImgArea.getHeight();
+ }
+ }
+ // we need to correct the factor if we use a pre-scaled image
+ ImageSize hiresSize = getHiresSize();
+ if (imgSize.getWidth() != hiresSize.getWidth()) {
+ scaleXY *= (float) hiresSize.getWidth() / (float) imgSize.getWidth();
+ }
+ areaWidth = getDw() / scaleXY * ws;
+ areaHeight = getDh() / scaleXY * ws;
+ // reset user area size
+ userImgArea.setRect(userImgArea.getX(), userImgArea.getY(), areaWidth, areaHeight);
+ } else {
+ /*
+ * crop to fit -- don't scale
+ */
+ areaWidth = getDw() * ws;
+ areaHeight = getDh() * ws;
+ // reset user area size
+ userImgArea.setRect(userImgArea.getX(), userImgArea.getY(), areaWidth, areaHeight);
+ scaleXY = 1f;
+ }
+ return (float) scaleXY;
+ }
- paramDW = getAsInt("dw");
- paramDH = getAsInt("dh");
+ /**
+ * Returns the width of the destination image.
+ * Uses dh parameter and aspect ratio if dw parameter is empty.
+ *
+ * @return
+ * @throws IOException
+ */
+ public int getDw() throws IOException {
+ logger.debug("get_paramDW()");
+ if (paramDW == null) {
+
+ paramDW = getAsInt("dw");
+ paramDH = getAsInt("dh");
+
+ float imgAspect = getInput().getAspect();
+ if (paramDW == 0) {
+ // calculate dw
+ paramDW = Math.round(paramDH * imgAspect);
+ setValue("dw", paramDW);
+ } else if (paramDH == 0) {
+ // calculate dh
+ paramDH = Math.round(paramDW / imgAspect);
+ setValue("dh", paramDH);
+ }
+ }
+ return paramDW;
+ }
+
+ /**
+ * Returns the height of the destination image.
+ * Uses dw parameter and aspect ratio if dh parameter is empty.
+ *
+ * @return
+ * @throws IOException
+ */
+ public int getDh() throws IOException {
+ logger.debug("get_paramDH()");
+ if (paramDH == null) {
+
+ paramDW = getAsInt("dw");
+ paramDH = getAsInt("dh");
- float imgAspect = getInput().getAspect();
- if (paramDW == 0) {
- // calculate dw
- paramDW = Math.round(paramDH * imgAspect);
- setValue("dw", paramDW);
- } else if (paramDH == 0) {
- // calculate dh
- paramDH = Math.round(paramDW / imgAspect);
- setValue("dh", paramDH);
- }
- }
- return paramDW;
- }
-
- /** Returns the height of the destination image.
- * Uses dw parameter and aspect ratio if dh parameter is empty.
- * @return
- * @throws IOException
- */
- public int getDh() throws IOException {
- logger.debug("get_paramDH()");
- if (paramDH == null) {
-
- paramDW = getAsInt("dw");
- paramDH = getAsInt("dh");
+ float imgAspect = getInput().getAspect();
+ if (paramDW == 0) {
+ // calculate dw
+ paramDW = Math.round(paramDH * imgAspect);
+ setValue("dw", paramDW);
+ } else if (paramDH == 0) {
+ // calculate dh
+ paramDH = Math.round(paramDW / imgAspect);
+ setValue("dh", paramDH);
+ }
+ }
+ return paramDH;
+ }
- float imgAspect = getInput().getAspect();
- if (paramDW == 0) {
- // calculate dw
- paramDW = Math.round(paramDH * imgAspect);
- setValue("dw", paramDW);
- } else if (paramDH == 0) {
- // calculate dh
- paramDH = Math.round(paramDW / imgAspect);
- setValue("dh", paramDH);
- }
- }
- return paramDH;
- }
-
- /** Returns image quality as an integer.
- * @return
- */
- public int getScaleQual(){
- logger.debug("get_scaleQual()");
- int qual = dlConfig.getAsInt("default-quality");
- if(hasOption("q0"))
- qual = 0;
- else if(hasOption("q1"))
- qual = 1;
- else if(hasOption("q2"))
- qual = 2;
- return qual;
- }
+ /**
+ * Returns image quality as an integer.
+ *
+ * @return
+ */
+ public int getScaleQual() {
+ logger.debug("get_scaleQual()");
+ int qual = dlConfig.getAsInt("default-quality");
+ if (hasOption("q0"))
+ qual = 0;
+ else if (hasOption("q1"))
+ qual = 1;
+ else if (hasOption("q2")) qual = 2;
+ return qual;
+ }
+
+ public ColorOp getColOp() {
+ String op = getAsString("colop");
+ if (op == null || op.length() == 0) {
+ return null;
+ }
+ try {
+ return ColorOp.valueOf(op.toUpperCase());
+ } catch (Exception e) {
+ logger.error("Invalid color op: " + op);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the area of the source image that will be transformed into the
+ * destination image.
+ *
+ * @return
+ * @throws IOException
+ * @throws ImageOpException
+ */
+ public Rectangle2D getUserImgArea() throws IOException, ImageOpException {
+ if (userImgArea == null) {
+ // getScaleXY sets userImgArea
+ getScaleXY();
+ }
+ return userImgArea;
+ }
- public ColorOp getColOp() {
- String op = getAsString("colop");
- if (op == null || op.length() == 0) {
- return null;
- }
- try {
- return ColorOp.valueOf(op.toUpperCase());
- } catch (Exception e) {
- logger.error("Invalid color op: " + op);
- }
- return null;
- }
-
- /**
- * Returns the area of the source image that will be transformed into the
- * destination image.
- *
- * @return
- * @throws IOException
- * @throws ImageOpException
- */
- public Rectangle2D getUserImgArea() throws IOException, ImageOpException{
- if(userImgArea == null) {
- // getScaleXY sets userImgArea
- getScaleXY();
- }
- return userImgArea;
- }
-
- /** Returns the maximal area of the source image that will be used.
- * @return
- * @throws IOException
- * @throws ImageOpException
- */
- public Rectangle2D getOuterUserImgArea() throws IOException, ImageOpException {
- if(outerUserImgArea == null){
- outerUserImgArea = getUserImgArea();
-
- // image size in pixels
- ImageSize imgSize = getInput().getSize();
- Rectangle2D imgBounds = new Rectangle2D.Float(0, 0, imgSize.getWidth(),
- imgSize.getHeight());
-
- // clip area at the image border
- outerUserImgArea = outerUserImgArea.createIntersection(imgBounds);
-
- // check image parameters sanity
- scaleXY = getScaleXY();
- logger.debug("outerUserImgArea.getWidth()=" + outerUserImgArea.getWidth());
- logger.debug("get_scaleXY() * outerUserImgArea.getWidth() = " + (scaleXY * outerUserImgArea.getWidth()));
-
- if ((outerUserImgArea.getWidth() < 1)
- || (outerUserImgArea.getHeight() < 1)
- || (scaleXY * outerUserImgArea.getWidth() < 2)
- || (scaleXY * outerUserImgArea.getHeight() < 2)) {
- logger.error("ERROR: invalid scale parameter set!");
- throw new ImageOpException("Invalid scale parameter set!");
- }
- }
- return outerUserImgArea;
- }
-
-
- public float[] getRGBM(){
- float[] paramRGBM = null;//{0f,0f,0f};
- Parameter p = params.get("rgbm");
- if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) {
- return p.parseAsFloatArray("/");
- }
- return paramRGBM;
- }
-
- public float[] getRGBA(){
- float[] paramRGBA = null;//{0f,0f,0f};
- Parameter p = params.get("rgba");
- if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) {
- paramRGBA = p.parseAsFloatArray("/");
- }
- return paramRGBA;
- }
-
- /** Has send-as-file been requested?
- * @return
- */
- public boolean getSendAsFile(){
- return hasOption("file")
- || hasOption("rawfile");
- }
-
+ /**
+ * Returns the maximal area of the source image that will be used.
+ *
+ * @return
+ * @throws IOException
+ * @throws ImageOpException
+ */
+ public Rectangle2D getOuterUserImgArea() throws IOException, ImageOpException {
+ if (outerUserImgArea == null) {
+ outerUserImgArea = getUserImgArea();
+
+ // image size in pixels
+ ImageSize imgSize = getInput().getSize();
+ Rectangle2D imgBounds = new Rectangle2D.Float(0, 0, imgSize.getWidth(), imgSize.getHeight());
+
+ // clip area at the image border
+ outerUserImgArea = outerUserImgArea.createIntersection(imgBounds);
+
+ // check image parameters sanity
+ scaleXY = getScaleXY();
+ logger.debug("outerUserImgArea.getWidth()=" + outerUserImgArea.getWidth());
+ logger.debug("get_scaleXY() * outerUserImgArea.getWidth() = " + (scaleXY * outerUserImgArea.getWidth()));
+
+ if ((outerUserImgArea.getWidth() < 1) || (outerUserImgArea.getHeight() < 1)
+ || (scaleXY * outerUserImgArea.getWidth() < 2) || (scaleXY * outerUserImgArea.getHeight() < 2)) {
+ logger.error("ERROR: invalid scale parameter set!");
+ throw new ImageOpException("Invalid scale parameter set!");
+ }
+ }
+ return outerUserImgArea;
+ }
+
+ public float[] getRGBM() {
+ float[] paramRGBM = null;// {0f,0f,0f};
+ Parameter p = params.get("rgbm");
+ if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) {
+ return p.parseAsFloatArray("/");
+ }
+ return paramRGBM;
+ }
+
+ public float[] getRGBA() {
+ float[] paramRGBA = null;// {0f,0f,0f};
+ Parameter p = params.get("rgba");
+ if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) {
+ paramRGBA = p.parseAsFloatArray("/");
+ }
+ return paramRGBA;
+ }
+
+ /**
+ * Has send-as-file been requested?
+ *
+ * @return
+ */
+ public boolean getSendAsFile() {
+ return hasOption("file") || hasOption("rawfile");
+ }
+
/**
* Returns if the image can be sent without processing. Takes image type and
* additional image operations into account. Does not check requested size
@@ -587,36 +628,34 @@
if (imageSendable == null) {
String mimeType = getMimeType();
imageSendable = (mimeType != null
- && (mimeType.equals("image/jpeg") || mimeType.equals("image/png")
- || mimeType.equals("image/gif"))
- && !(hasOption("hmir")
- || hasOption("vmir") || (getAsFloat("rot") != 0.0)
- || (getRGBM() != null) || (getRGBA() != null) || (this.getColOp() != null)
- || (getAsFloat("cont") != 0.0) || (getAsFloat("brgt") != 0.0)));
+ && (mimeType.equals("image/jpeg") || mimeType.equals("image/png") || mimeType.equals("image/gif")) && !(hasOption("hmir")
+ || hasOption("vmir")
+ || (getAsFloat("rot") != 0.0)
+ || (getRGBM() != null)
+ || (getRGBA() != null)
+ || (this.getColOp() != null) || (getAsFloat("cont") != 0.0) || (getAsFloat("brgt") != 0.0)));
}
return imageSendable;
}
-
-
- /**
- * Returns if any transformation of the source image (image manipulation or
- * format conversion) is required.
- *
- * @return
- * @throws IOException
- */
- public boolean isTransformRequired() throws IOException {
- ImageSize is = getInput().getSize();
- ImageSize ess = getExpectedSourceSize();
- // nt = no transform required
- boolean nt = isImageSendable() && (
- // lores: send if smaller
- (isLoresOnly() && is.isSmallerThan(ess))
- // else send if it fits
- || (!(isLoresOnly() || isHiresOnly()) && is.fitsIn(ess)));
- return ! nt;
- }
+ /**
+ * Returns if any transformation of the source image (image manipulation or
+ * format conversion) is required.
+ *
+ * @return
+ * @throws IOException
+ */
+ public boolean isTransformRequired() throws IOException {
+ ImageSize is = getInput().getSize();
+ ImageSize ess = getExpectedSourceSize();
+ // nt = no transform required
+ boolean nt = isImageSendable() && (
+ // lores: send if smaller
+ (isLoresOnly() && is.isSmallerThan(ess))
+ // else send if it fits
+ || (!(isLoresOnly() || isHiresOnly()) && is.fitsIn(ess)));
+ return !nt;
+ }
/**
* @return the docuImage
@@ -625,9 +664,9 @@
return docuImage;
}
-
/**
- * @param docuImage the docuImage to set
+ * @param docuImage
+ * the docuImage to set
*/
public void setDocuImage(DocuImage docuImage) {
this.docuImage = docuImage;
diff -r 5d0eeccca1d9 -r a6532856dae1 common/src/main/java/digilib/image/ImageWorker.java
--- a/common/src/main/java/digilib/image/ImageWorker.java Fri Jul 19 14:08:29 2013 +0200
+++ b/common/src/main/java/digilib/image/ImageWorker.java Fri Jul 19 19:08:39 2013 +0200
@@ -94,10 +94,7 @@
subf = 1 / scaleXY;
// for higher quality reduce subsample factor by minSubsample
if (jobinfo.getScaleQual() > 0) {
- subsamp = (float) Math
- .max(Math.floor(subf
- / dlConfig.getAsFloat("subsample-minimum")),
- 1d);
+ subsamp = (float) Math.max(Math.floor(subf / dlConfig.getAsFloat("subsample-minimum")), 1d);
} else {
subsamp = (float) Math.floor(subf);
}
diff -r 5d0eeccca1d9 -r a6532856dae1 servlet/src/main/java/digilib/conf/DigilibServletRequest.java
--- a/servlet/src/main/java/digilib/conf/DigilibServletRequest.java Fri Jul 19 14:08:29 2013 +0200
+++ b/servlet/src/main/java/digilib/conf/DigilibServletRequest.java Fri Jul 19 19:08:39 2013 +0200
@@ -54,16 +54,18 @@
* mk: list of marks.
* pt: total number of pages (generated by sevlet).
* baseURL: base URL (from http:// to below /servlet).
- * ...et alii
+ * ...et al
*
* @author casties
*
*/
public class DigilibServletRequest extends DigilibRequest {
- protected DocuImage image; // internal DocuImage instance for this request
+ /** internal DocuImage instance for this request */
+ protected DocuImage image;
- protected HttpServletRequest servletRequest; // internal ServletRequest
+ /** internal ServletRequest */
+ protected HttpServletRequest servletRequest;
/**
* Creates a new instance of DigilibRequest with parameters from a
@@ -88,10 +90,11 @@
initOptions();
}
- /**
- * set up parameters.
- *
+ /* (non-Javadoc)
+ * @see digilib.conf.DigilibRequest#initParams()
+ * Define and set up parameters with default values.
*/
+ @Override
protected void initParams() {
/*
* Definition of parameters and default values. Parameter of type 's'
@@ -191,6 +194,7 @@
/**
* Populate the request object with data from a ServletRequest.
*
+ * Recognizes digilib API (old and new) and IIIF API style requests.
*
* @param request
*/
@@ -207,6 +211,7 @@
// we try to match servlet name + iiifPrefix in the uri
int mp = uri.indexOf(ms+"/"+iiifPrefix+"/");
if (mp > -1) {
+ // replace path with part of uri
path = uri.substring(mp + ms.length());
}
setWithIiifPath(path.substring(1));