changeset 130:c36944be0b58

Servlet Version 1.11a1with original size(!) - new meta data file loader - new parameter ddpi, ddpix, ddpiy (client->servlet) - new parameter mo=osize - osize scales based on ddpi and original dpi (currently only equally for x and y)
author robcast
date Wed, 02 Jul 2003 00:02:18 +0200
parents ed7c1e4dd177
children 737f5cd647e1
files servlet/src/digilib/io/DocuDirectory.java servlet/src/digilib/io/DocuFile.java servlet/src/digilib/io/DocuFileset.java servlet/src/digilib/io/XMLMetaLoader.java servlet/src/digilib/servlet/DigilibRequest.java servlet/src/digilib/servlet/Scaler.java
diffstat 6 files changed, 624 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/servlet/src/digilib/io/DocuDirectory.java	Mon Jun 30 17:25:43 2003 +0200
+++ b/servlet/src/digilib/io/DocuDirectory.java	Wed Jul 02 00:02:18 2003 +0200
@@ -22,17 +22,20 @@
 package digilib.io;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 
+import org.xml.sax.SAXException;
+
 /**
  * @author casties
  */
 public class DocuDirectory {
 
-	// list of files
+	// list of files (DocuFileSet)
 	private ArrayList list = null;
 	// directory object is valid (has been read)
 	private boolean isValid = false;
@@ -85,7 +88,7 @@
 
 	/** Read the directory and fill this object.
 	 * 
-	 * Clears the Vector and (re)reads all files.
+	 * Clears the List and (re)reads all files.
 	 * 
 	 * @return boolean the directory exists
 	 */
@@ -172,6 +175,8 @@
 			}
 			dirMTime = dir.lastModified();
 			isValid = true;
+			// read metadata as well
+			readMeta();
 		}
 		return isValid;
 
@@ -197,6 +202,38 @@
 	 */
 	public void readMeta() {
 		// check for directory metadata...
+		File mf = new File(dir, "index.meta");
+		if (mf.canRead()) {
+			XMLMetaLoader ml = new XMLMetaLoader();
+			try {
+				// read directory meta file
+				HashMap fileMeta = ml.loadURL(mf.getAbsolutePath());
+				if (fileMeta == null) {
+					return;
+				}
+				// meta for the directory itself is in the "" bin
+				dirMeta = (HashMap)fileMeta.remove("");
+				// is there meta for other files?
+				if (fileMeta.size() > 0) {
+					// iterate through the list of files
+					for (Iterator i = list.iterator(); i.hasNext();) {
+						DocuFileset df = (DocuFileset)i.next();
+						// look up meta for this file
+						HashMap meta = (HashMap)fileMeta.get(df.getName());
+						if (meta != null) {
+							df.setFileMeta(meta);
+						}
+					}
+				}
+			} catch (SAXException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			} catch (IOException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+
+		}
 	}
 
 	/** Update access time.
--- a/servlet/src/digilib/io/DocuFile.java	Mon Jun 30 17:25:43 2003 +0200
+++ b/servlet/src/digilib/io/DocuFile.java	Wed Jul 02 00:02:18 2003 +0200
@@ -47,6 +47,10 @@
 		file = f;
 	}
 	
+	/** Returns the file name (without path).
+	 * 
+	 * @return
+	 */
 	public String getName() {
 		if (file != null) {
 			return file.getName();
@@ -55,6 +59,10 @@
 	}
 
 
+	/** Checks the file using the provided DocuInfo instance.
+	 *  
+	 * @param info
+	 */
 	public void check(DocuInfo info) {
 		try {
 			info.checkFile(this);
--- a/servlet/src/digilib/io/DocuFileset.java	Mon Jun 30 17:25:43 2003 +0200
+++ b/servlet/src/digilib/io/DocuFileset.java	Wed Jul 02 00:02:18 2003 +0200
@@ -20,6 +20,7 @@
 package digilib.io;
 
 import java.awt.Dimension;
+import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -32,13 +33,19 @@
  */
 public class DocuFileset {
 
-	// list of files
+	// list of files (DocuFile)
 	private ArrayList list = null;
 	// metadata
 	private HashMap fileMeta = null;
+	// metadata has been checked
+	private boolean metaChecked = false;
+	// resolution (DPI)
+	private double resX = 0;
+	private double resY = 0;
 	// parent directory
 	private DocuDirectory parent = null;
 
+
 	/*
 	 * constructors
 	 */
@@ -153,13 +160,97 @@
 	}
 
 	/** Reads meta-data for this Fileset if there is any.
-	 * (not yet implemented)
+	 * 
+	 */
+	public void readMeta() {
+		if ((fileMeta != null) || list.isEmpty()) {
+			// there is already metadata or there's no file 
+			return;
+		}
+		// metadata is in the file {filename}.meta
+		String fn = ((DocuFile) list.get(0)).getFile().getAbsolutePath();
+		File mf = new File(fn + ".meta");
+		if (mf.canRead()) {
+			XMLMetaLoader ml = new XMLMetaLoader();
+			try {
+				// read meta file
+				HashMap meta = ml.loadURL(mf.getAbsolutePath());
+				if (meta == null) {
+					return;
+				}
+				fileMeta = (HashMap) meta.get(getName());
+			} catch (Exception e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+	}
+
+	/** Checks metadata and sets resolution in resX and resY.
+	 * 
 	 */
 	public void checkMeta() {
-		// check for file metadata...
+		if (metaChecked) {
+			return;
+		}
+		if (fileMeta == null) {
+			// try to read meta-data file
+			readMeta();
+			if (fileMeta == null) {
+				// there is no meta data
+				metaChecked = true;
+				return;
+			}
+		}
+		metaChecked = true;
+		double dpi = 0;
+		double dpix = 0;
+		double dpiy = 0;
+		double sizex = 0;
+		double sizey = 0;
+		double pixx = 0;
+		double pixy = 0;
+		// DPI is valid for X and Y
+		try {
+			dpi = Double.parseDouble((String) fileMeta.get("dpi"));
+		} catch (NumberFormatException e) {
+		}
+		if (dpi != 0) {
+			resX = dpi;
+			resY = dpi;
+			return;
+		}
+		// DPI-X and DPI-Y
+		try {
+			dpix = Double.parseDouble((String) fileMeta.get("dpi-x"));
+			dpiy = Double.parseDouble((String) fileMeta.get("dpi-y"));
+		} catch (NumberFormatException e) {
+		}
+		if ((dpix != 0) && (dpiy != 0)) {
+			resX = dpix;
+			resY = dpiy;
+			return;
+		}
+		// SIZE-X and SIZE-Y and PIXEL-X and PIXEL-Y
+		try {
+			sizex =
+				Double.parseDouble((String) fileMeta.get("original-size-x"));
+			sizey =
+				Double.parseDouble((String) fileMeta.get("original-size-y"));
+			pixx =
+				Double.parseDouble((String) fileMeta.get("original-pixel-x"));
+			pixy =
+				Double.parseDouble((String) fileMeta.get("original-pixel-y"));
+		} catch (NumberFormatException e) {
+		}
+		if ((sizex != 0) && (sizey != 0) && (pixx != 0) && (pixy != 0)) {
+			resX = pixx / (sizex * 100 / 2.54);
+			resY = pixy / (sizey * 100 / 2.54);
+			return;
+		}
 	}
 
-	/** The name of the (original) image file.
+	/** The name of the (hires) image file.
 	 * 
 	 * @return
 	 */
@@ -171,6 +262,7 @@
 	}
 
 	/** Returns the parent DocuDirectory.
+	 * 
 	 * @return DocuDirectory
 	 */
 	public DocuDirectory getParent() {
@@ -201,4 +293,25 @@
 		this.fileMeta = fileMeta;
 	}
 
+	/**
+	 * @return
+	 */
+	public boolean isMetaChecked() {
+		return metaChecked;
+	}
+	
+	/**
+	 * @return
+	 */
+	public double getResX() {
+		return resX;
+	}
+
+	/**
+	 * @return
+	 */
+	public double getResY() {
+		return resY;
+	}
+	
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servlet/src/digilib/io/XMLMetaLoader.java	Wed Jul 02 00:02:18 2003 +0200
@@ -0,0 +1,198 @@
+/* XMLMetaLoader -- Load an XML format metadata into a Hashtable
+
+  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.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class XMLMetaLoader {
+
+	private String outerTag = "resource";
+	private String metaTag = "meta";
+	private String fileTag = "file";
+	private String fileNameTag = "name";
+	private String filePathTag = "path";
+	private String infoTag = "img";
+
+	public XMLMetaLoader() {
+	}
+
+	/**
+	 *  inner class XMLMetaParser to be called by the parser
+	 */
+	private class XMLMetaParser extends DefaultHandler {
+
+		private LinkedList tags;
+		private HashMap files;
+		private HashMap meta;
+		private StringBuffer content;
+		private String fileName;
+		private String filePath;
+
+		//		public HashMap getData() {
+		//			return meta;
+		//		}
+
+		// Parser calls this once at the beginning of a document
+		public void startDocument() throws SAXException {
+			tags = new LinkedList();
+			files = new HashMap();
+		}
+
+		// Parser calls this for each element in a document
+		public void startElement(
+			String namespaceURI,
+			String localName,
+			String qName,
+			Attributes atts)
+			throws SAXException {
+
+			String name = (localName != null) ? localName : qName;
+			// open a new tag
+			tags.addLast(name);
+			// start new content (no nesting of tags and content)
+			content = new StringBuffer();
+
+			if (name.equals(metaTag)) {
+				// new meta tag
+				meta = new HashMap();
+			} else if (name.equals(fileTag)) {
+				// new file tag
+				fileName = null;
+				filePath = null;
+			}
+		}
+
+		// parser calls this for all tag content (possibly more than once)
+		public void characters(char[] ch, int start, int length)
+			throws SAXException {
+			// append data to current string buffer
+			content.append(ch, start, length);
+		}
+
+		// parser calls this at the end of each element
+		public void endElement(
+			String namespaceURI,
+			String localName,
+			String qName)
+			throws SAXException {
+				
+			String name = (localName != null) ? localName : qName;
+			// exit the tag
+			tags.removeLast();
+			
+			// was it a file.name tag?
+			if (name.equals(fileNameTag) && tags.contains(fileTag)) {
+				// save name as filename
+				if ((content != null)&&(content.length() > 0)) {
+					fileName = content.toString();
+				}
+				return;
+			}
+
+			// was it a file.path tag?
+			if (name.equals(filePathTag) && tags.contains(fileTag)) {
+				// save path as filepath 
+				if ((content != null)&&(content.length() > 0)) {
+					filePath = content.toString();
+				}
+				return;
+			}
+
+			// was it a file tag?
+			if (name.equals(fileTag)) {
+				// is there meta to save?
+				if ((meta != null)&&(meta.size() > 0)) {
+					// file name is either file.path or file.name
+					String fn = null;
+					if (filePath != null) {
+						fn = filePath;
+					} else if (fileName != null) {
+						fn = fileName;
+					} else {
+						// no file name, no file
+						return;
+					}
+					// save meta in file list 
+					files.put(fn, meta);
+				}
+				return;
+			}
+
+			// was it a meta tag outside a file tag?
+			if (name.equals(metaTag) && !tags.contains(fileTag)) {
+				// save meta as dir meta
+				if ((meta != null)&&(meta.size() > 0)) {
+					files.put("", meta);
+				}
+				return;
+			}
+
+			// is this inside an info tag?
+			if (tags.contains(infoTag)) {
+				// then add whatever this is
+				if ((content != null)&&(content.length() > 0)) {
+					meta.put(name, content.toString());
+				}
+			}
+			
+		}
+
+	}
+
+	/**
+	 *  load and parse a file (as URL)
+	 *    returns HashMap with list data
+	 */
+	public HashMap loadURL(String path) throws SAXException, IOException {
+		//System.out.println("loadurl ("+path+")");
+		// Create a JAXP SAXParserFactory and configure it
+		SAXParserFactory spf = SAXParserFactory.newInstance();
+		spf.setNamespaceAware(true);
+
+		SAXParser parser = null;
+		try {
+			// Create a JAXP SAXParser
+			parser = spf.newSAXParser();
+
+		} catch (ParserConfigurationException e) {
+			throw new SAXException(e);
+		}
+
+		// create a list parser (keeps the data!)
+		XMLMetaParser listParser = new XMLMetaParser();
+
+		// Tell the SAXParser to parse the XML document
+		parser.parse(path, listParser);
+
+		return listParser.files;
+	}
+
+}
--- a/servlet/src/digilib/servlet/DigilibRequest.java	Mon Jun 30 17:25:43 2003 +0200
+++ b/servlet/src/digilib/servlet/DigilibRequest.java	Wed Jul 02 00:02:18 2003 +0200
@@ -26,15 +26,17 @@
 
 package digilib.servlet;
 
-import java.io.*;
-import java.util.*;
+import java.io.File;
+import java.io.StringReader;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
 
 import javax.servlet.ServletRequest;
 import javax.servlet.http.HttpServletRequest;
 
+import com.hp.hpl.mesa.rdf.jena.common.SelectorImpl;
 import com.hp.hpl.mesa.rdf.jena.mem.ModelMem;
 import com.hp.hpl.mesa.rdf.jena.model.*;
-import com.hp.hpl.mesa.rdf.jena.common.*;
 
 import digilib.image.DocuImage;
 
@@ -91,6 +93,18 @@
 	                //                   2 = in frameset, 3 = XUL-'frameset'
 	                //                   4 = XUL-Sidebar )
 	private String lv_s;
+	private float odpi; // resolution of original image
+	private String odpi_s; 
+	private float ddpi; // resolution of original image
+	private String ddpi_s; 
+	private float odpix; // x resolution of original image
+	private String odpix_s; 
+	private float odpiy; // y resolution of original image
+	private String odpiy_s; 
+	private float ddpix; // x resolution of destination image
+	private String ddpix_s; 
+	private float ddpiy; // y resolution of destination image
+	private String ddpiy_s; 
 
 	private DocuImage image; // internal DocuImage instance for this request
 	private ServletRequest servletRequest; // internal ServletRequest
@@ -344,6 +358,15 @@
 		if (lv_s != null) {
 			s += "&lv=" + lv_s;
 		}
+		if (ddpi_s != null) {
+			s += "&ddpi=" + ddpi;
+		}
+		if (ddpix_s != null) {
+			s += "&ddpix=" + ddpix;
+		}
+		if (ddpiy_s != null) {
+			s += "&ddpiy=" + ddpiy;
+		}
 
 		return s;
 	}
@@ -446,6 +469,18 @@
 		if (s != null) {
 			setLv(s);
 		}
+		s = request.getParameter("ddpi");
+		if (s != null) {
+			setDdpi(s);
+		}
+		s = request.getParameter("ddpix");
+		if (s != null) {
+			setDdpix(s);
+		}
+		s = request.getParameter("ddpiy");
+		if (s != null) {
+			setDdpiy(s);
+		}
 		s = ((HttpServletRequest) request).getPathInfo();
 		if (s != null) {
 			setRequestPath(s);
@@ -532,10 +567,22 @@
 	    if (s != null) {
 		setPt(s);
 	    }
-	    s = (String)hashRDF.get("lv");
-	    if (s != null) {
+		s = (String)hashRDF.get("lv");
+		if (s != null) {
 		setLv(s);
-	    }
+		}
+		s = (String)hashRDF.get("ddpi");
+		if (s != null) {
+		setDdpi(s);
+		}
+		s = (String)hashRDF.get("ddpix");
+		if (s != null) {
+		setDdpix(s);
+		}
+		s = (String)hashRDF.get("ddpiy");
+		if (s != null) {
+		setDdpiy(s);
+		}
 	    s = ((HttpServletRequest) request).getPathInfo();
 	    if (s != null) {
 		setRequestPath(s);
@@ -629,6 +676,18 @@
 		rgbm_s = null;
 		rgba = null;
 		rgba_s = null;
+		ddpi = 0;
+		ddpi_s = null;
+		ddpix = 0;
+		ddpix_s = null;
+		ddpiy = 0;
+		ddpiy_s = null;
+		odpi = 0;
+		odpi_s = null;
+		odpix = 0;
+		odpix_s = null;
+		odpiy = 0;
+		odpiy_s = null;
 		baseURL = null;
 		image = null;
 		servletRequest = null;
@@ -707,8 +766,6 @@
 
 	/* Property getter and setter */
 
-// lugi - begin
-
 	/** Getter for property lv.
 	 * @return Value of property lv.
 	 *
@@ -735,8 +792,6 @@
 		}
 	}
 
-// lugi - end
-
 	/** Getter for property dh.
 	 * @return Value of property dh.
 	 *
@@ -1258,6 +1313,163 @@
 		}
 	}
 
+	/** Getter for property ddpi.
+	 * @return Value of property ddpi.
+	 *
+	 */
+	public float getDdpi() {
+		return ddpi;
+	}
+
+	/** Setter for property ddpi.
+	 * @param ddpi New value of property ddpi.
+	 *
+	 */
+	public void setDdpi(float ddpi) {
+		this.ddpi = ddpi;
+		ddpi_s = Float.toString(ddpi);
+	}
+	public void setDdpi(String ddpi) {
+		try {
+			float f = Float.parseFloat(ddpi);
+			this.ddpi = f;
+			this.ddpi_s = ddpi;
+		} catch (Exception e) {
+			//util.dprintln(4, "trytoGetParam(int) failed on param "+s);
+		}
+	}
+
+	/** Getter for property ddpi.
+	 * @return Value of property ddpi.
+	 *
+	 */
+	public float getDdpix() {
+		return ddpix;
+	}
+
+	/** Setter for property ddpi.
+	 * @param ddpi New value of property ddpi.
+	 *
+	 */
+	public void setDdpix(float ddpix) {
+		this.ddpix = ddpix;
+		ddpix_s = Float.toString(ddpix);
+	}
+	public void setDdpix(String s) {
+		try {
+			float f = Float.parseFloat(s);
+			this.ddpix = f;
+			this.ddpix_s = s;
+		} catch (Exception e) {
+			//util.dprintln(4, "trytoGetParam(int) failed on param "+s);
+		}
+	}
+
+	/** Getter for property ddpi.
+	 * @return Value of property ddpi.
+	 *
+	 */
+	public float getDdpiy() {
+		return ddpiy;
+	}
+
+	/** Setter for property ddpi.
+	 * @param ddpi New value of property ddpi.
+	 *
+	 */
+	public void setDdpiy(float f) {
+		this.ddpiy = f;
+		ddpiy_s = Float.toString(f);
+	}
+	public void setDdpiy(String s) {
+		try {
+			float f = Float.parseFloat(s);
+			this.ddpiy = f;
+			this.ddpiy_s = s;
+		} catch (Exception e) {
+			//util.dprintln(4, "trytoGetParam(int) failed on param "+s);
+		}
+	}
+
+	/** Getter for property ddpi.
+	 * @return Value of property ddpi.
+	 *
+	 */
+	public float getOdpi() {
+		return odpi;
+	}
+
+	/** Setter for property ddpi.
+	 * @param ddpi New value of property ddpi.
+	 *
+	 */
+	public void setOdpi(float f) {
+		this.odpi = f;
+		odpi_s = Float.toString(f);
+	}
+	public void setOdpi(String s) {
+		try {
+			float f = Float.parseFloat(s);
+			this.odpi = f;
+			this.odpi_s = s;
+		} catch (Exception e) {
+			//util.dprintln(4, "trytoGetParam(int) failed on param "+s);
+		}
+	}
+
+	/** Getter for property ddpi.
+	 * @return Value of property ddpi.
+	 *
+	 */
+	public float getOdpix() {
+		return odpix;
+	}
+
+	/** Setter for property ddpi.
+	 * @param ddpi New value of property ddpi.
+	 *
+	 */
+	public void setOdpix(float f) {
+		this.odpix = f;
+		odpix_s = Float.toString(f);
+	}
+	public void setOdpix(String s) {
+		try {
+			float f = Float.parseFloat(s);
+			this.odpix = f;
+			this.odpix_s = s;
+		} catch (Exception e) {
+			//util.dprintln(4, "trytoGetParam(int) failed on param "+s);
+		}
+	}
+
+	/** Getter for property ddpi.
+	 * @return Value of property ddpi.
+	 *
+	 */
+	public float getOdpiy() {
+		return odpiy;
+	}
+
+	/** Setter for property ddpi.
+	 * @param ddpi New value of property ddpi.
+	 *
+	 */
+	public void setOdpiy(float f) {
+		this.odpiy = f;
+		odpiy_s = Float.toString(f);
+	}
+	public void setOdpiy(String s) {
+		try {
+			float f = Float.parseFloat(s);
+			this.odpiy = f;
+			this.odpiy_s = s;
+		} catch (Exception e) {
+			//util.dprintln(4, "trytoGetParam(int) failed on param "+s);
+		}
+	}
+
+
 	public boolean isRDF(){
 	  return boolRDF;
         }
--- a/servlet/src/digilib/servlet/Scaler.java	Mon Jun 30 17:25:43 2003 +0200
+++ b/servlet/src/digilib/servlet/Scaler.java	Wed Jul 02 00:02:18 2003 +0200
@@ -58,7 +58,7 @@
 public class Scaler extends HttpServlet {
 
 	// digilib servlet version (for all components)
-	public static final String dlVersion = "1.10b2";
+	public static final String dlVersion = "1.11a1";
 
 	// Utils instance with debuglevel
 	Utils util;
@@ -184,6 +184,9 @@
 		boolean doMirror = false;
 		// angle of mirror axis
 		double mirrorAngle = 0;
+		// original (hires) image resolution
+		double origResX = 0;
+		double origResY = 0;
 
 		/*
 		 *  request parameters
@@ -222,6 +225,14 @@
 		// color modification
 		float[] paramRGBM = dlRequest.getRgbm();
 		float[] paramRGBA = dlRequest.getRgba();
+		// destination resolution (DPI)
+		float paramDDPIX = dlRequest.getDdpix();
+		float paramDDPIY = dlRequest.getDdpiy();
+		if ((paramDDPIX == 0) || (paramDDPIY == 0)) {
+			// if X or Y resolution isn't set, use DDPI
+			paramDDPIX = dlRequest.getDdpi();
+			paramDDPIY = dlRequest.getDdpi();
+		}
 
 		/* operation mode: "fit": always fit to page, 
 		 * "clip": send original resolution cropped, "file": send whole file (if
@@ -237,7 +248,7 @@
 			absoluteScale = false;
 			cropToFit = false;
 			autoRes = true;
-		} else if (dlRequest.isOption("scale")) {
+		} else if (dlRequest.isOption("osize")) {
 			scaleToFit = false;
 			absoluteScale = true;
 			cropToFit = false;
@@ -361,11 +372,11 @@
 			 * select a resolution
 			 */
 			if (autoRes) {
-				// autores: use next bigger resolution
+				// autores: use next higher resolution
 				fileToLoad =
 					fileset.getNextBigger(expectedSourceSize, docuInfo);
 				if (fileToLoad == null) {
-					// this is the biggest we have
+					// this is the highest we have
 					fileToLoad = fileset.get(0);
 				}
 			} else {
@@ -385,16 +396,33 @@
 			}
 			util.dprintln(1, "Loading: " + fileToLoad.getFile());
 
+			if (absoluteScale) {
+				// get original resolution from metadata
+				fileset.checkMeta();
+				origResX = fileset.getResX();
+				origResY = fileset.getResY();
+			}
+
 			// check the source image
 			if (!fileToLoad.isChecked()) {
 				fileToLoad.check(docuInfo);
 			}
 			// get the source image type
 			mimeType = fileToLoad.getMimetype();
-			boolean imageSendable =
+			// decide if the image can be sent as is
+			boolean mimetypeSendable =
 				mimeType.equals("image/jpeg")
 					|| mimeType.equals("image/png")
 					|| mimeType.equals("image/gif");
+			boolean imagoOptions =
+				dlRequest.isOption("hmir")
+					|| dlRequest.isOption("vmir")
+					|| (paramROT != 0)
+					|| (paramRGBM != null)
+					|| (paramRGBA != null)
+					|| (paramCONT != 0)
+					|| (paramBRGT != 0);
+			boolean imageSendable = mimetypeSendable && ! imagoOptions;
 
 			/* if not autoRes and image smaller than requested 
 			 * size then send as is. 
@@ -405,7 +433,7 @@
 				&& imageSendable
 				&& (fileToLoad.getSize().width <= expectedSourceSize.width)
 				&& (fileToLoad.getSize().height <= expectedSourceSize.height))
-				|| (!autoRes && !scaleToFit && !cropToFit)) {
+				|| (!autoRes && !scaleToFit && !cropToFit && !absoluteScale)) {
 
 				util.dprintln(1, "Sending File as is.");
 
@@ -474,17 +502,18 @@
 				scaleXY = (scaleX > scaleY) ? scaleY : scaleX;
 			} else if (absoluteScale) {
 				// absolute scale
-				areaWidth = paramDW * paramWS;
-				areaHeight = paramDH * paramWS;
+				scaleX = paramDDPIX / origResX;
+				scaleY = paramDDPIY / origResY;
+				// currently only same scale :-(
+				scaleXY = scaleX;
+				areaWidth = paramDW / scaleXY * paramWS;
+				areaHeight = paramDH / scaleXY * paramWS;
 				// reset user area size
 				userImgArea.setRect(
 					userImgArea.getX(),
 					userImgArea.getY(),
 					areaWidth,
 					areaHeight);
-				scaleX = 1f;
-				scaleY = 1f;
-				scaleXY = 1f;
 			} else {
 				// crop to fit
 				areaWidth = paramDW * paramWS;