Mercurial > hg > digilib
changeset 1204:a6532856dae1
IIIF region in pixel units works now.
small cleanups.
author | robcast |
---|---|
date | Fri, 19 Jul 2013 19:08:39 +0200 |
parents | 5d0eeccca1d9 |
children | a5aea37fac03 |
files | common/src/main/java/digilib/conf/DigilibRequest.java common/src/main/java/digilib/image/ImageJobDescription.java common/src/main/java/digilib/image/ImageWorker.java servlet/src/main/java/digilib/conf/DigilibServletRequest.java |
diffstat | 4 files changed, 586 insertions(+), 525 deletions(-) [+] |
line wrap: on
line diff
--- 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). <br> * ws: scale factor. <br> * mo: special options like 'fit'. <br> - * ...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
--- 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;
--- 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); }
--- 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. <br> * pt: total number of pages (generated by sevlet). <br> * baseURL: base URL (from http:// to below /servlet). <br> - * ...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));