# HG changeset patch
# User robcast
# Date 1046354849 -3600
# Node ID 4e6757e8ccd402864492d80159a37e04af5019f3
# Parent ed1b698b4f0ae783ddf6bcc96e3c276671011f7b
New enhanced ImageLoader stuff.
Now uses Subsampling and image regions on read.
Now implements enhance, rotate and mirror for ImageLoader/Java2D
diff -r ed1b698b4f0a -r 4e6757e8ccd4 servlet/src/digilib/image/DocuImage.java
--- a/servlet/src/digilib/image/DocuImage.java Mon Feb 10 17:09:28 2003 +0100
+++ b/servlet/src/digilib/image/DocuImage.java Thu Feb 27 15:07:29 2003 +0100
@@ -2,7 +2,7 @@
Digital Image Library servlet components
- Copyright (C) 2001, 2002 Robert Casties (robcast@mail.berlios.de)
+ Copyright (C) 2001, 2002, 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
@@ -20,6 +20,7 @@
package digilib.image;
+import java.awt.Rectangle;
import java.io.File;
import java.io.OutputStream;
@@ -47,6 +48,35 @@
*/
public void loadImage(File f) throws FileOpException;
+ /** This DocuImage support the loadSubImage operation.
+ *
+ * @return boolean
+ */
+ public boolean isSubimageSupported();
+
+ /** Load only a subsampled region of the image file.
+ *
+ * @param f
+ * @param region
+ * @param subsample
+ * @throws FileOpException
+ */
+ public void loadSubimage(File f, Rectangle region, int subsample)
+ throws FileOpException;
+
+ /** This DocuImage support the preloadImage operation for getWidth/getHeight.
+ *
+ * @return boolean
+ */
+ public boolean isPreloadSupported();
+
+ /** Preload image file into a state to use getWidth/getHeight.
+ *
+ * @param f
+ * @throws FileOpException
+ */
+ public void preloadImage(File f) throws FileOpException;
+
/** Writes the current image to a ServletResponse.
*
* The image is encoded to the mime-type mt
and sent to the output
@@ -121,17 +151,18 @@
double scale,
int qual)
throws ImageOpException;
-
+
/** Rotates the current image.
*
* Replaces the current image with a rotated image. The image is rotated
- * around the center by angle
given in degrees [0, 360]
- * clockwise. Image size and aspect ratio are likely to change.
+ * around the point x
,y
by angle
+ * given in degrees [0, 360] clockwise.
+ * Image size and aspect ratio are likely to change.
*
* @param angle rotation angle in degree
*/
public void rotate(double angle) throws ImageOpException;
-
+
/** Mirrors the current image.
*
* Replaces the current image with a mirrored image. The mirror axis goes
@@ -143,7 +174,7 @@
* @throws ImageOpException
*/
public void mirror(double angle) throws ImageOpException;
-
+
/** Enhaces brightness and contrast of the current image.
*
* Replaces the current image with a brightness and contrast enhanced image.
diff -r ed1b698b4f0a -r 4e6757e8ccd4 servlet/src/digilib/image/DocuImageImpl.java
--- a/servlet/src/digilib/image/DocuImageImpl.java Mon Feb 10 17:09:28 2003 +0100
+++ b/servlet/src/digilib/image/DocuImageImpl.java Thu Feb 27 15:07:29 2003 +0100
@@ -2,7 +2,7 @@
Digital Image Library servlet components
- Copyright (C) 2001, 2002 Robert Casties (robcast@mail.berlios.de)
+ Copyright (C) 2001, 2002, 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
@@ -20,7 +20,11 @@
package digilib.image;
+import java.awt.Rectangle;
+import java.io.File;
+
import digilib.Utils;
+import digilib.io.FileOpException;
/** Simple abstract implementation of the DocuImage
interface.
*
@@ -37,6 +41,9 @@
/** Interpolation quality. */
protected int quality = 0;
+
+ // epsilon for float comparisons
+ public final double epsilon = 1e-5;
/** Default constructor. */
public DocuImageImpl() {
@@ -121,4 +128,23 @@
// just a do-nothing implementation
}
+ public void preloadImage(File f) throws FileOpException {
+ // just a do-nothing implementation
+ }
+
+ public boolean isPreloadSupported() {
+ // preload per default not supported
+ return false;
+ }
+
+ public boolean isSubimageSupported() {
+ // partial loading per default not supported
+ return false;
+ }
+
+ public void loadSubimage(File f, Rectangle region, int subsample)
+ throws FileOpException {
+ // empty implementation
+ }
+
}
diff -r ed1b698b4f0a -r 4e6757e8ccd4 servlet/src/digilib/image/ImageLoaderDocuImage.java
--- a/servlet/src/digilib/image/ImageLoaderDocuImage.java Mon Feb 10 17:09:28 2003 +0100
+++ b/servlet/src/digilib/image/ImageLoaderDocuImage.java Thu Feb 27 15:07:29 2003 +0100
@@ -2,7 +2,7 @@
Digital Image Library servlet components
- Copyright (C) 2001, 2002 Robert Casties (robcast@mail.berlios.de)
+ Copyright (C) 2002, 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
@@ -20,16 +20,21 @@
package digilib.image;
+import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
+import java.awt.image.RescaleOp;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Iterator;
import javax.imageio.ImageIO;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
-import digilib.Utils;
import digilib.io.FileOpException;
/** Implementation of DocuImage using the ImageLoader API of Java 1.4 and Java2D. */
@@ -37,13 +42,59 @@
private BufferedImage img;
- private int scaleInt;
+ private int interpol;
+
+ // ImageIO image reader
+ ImageReader reader;
- public ImageLoaderDocuImage() {
+ /* preload is supported. */
+ public boolean isPreloadSupported() {
+ return true;
+ }
+
+ /* loadSubimage is supported. */
+ public boolean isSubimageSupported() {
+ return true;
}
- public ImageLoaderDocuImage(Utils u) {
- util = u;
+ public void setQuality(int qual) {
+ quality = qual;
+ // setup interpolation quality
+ if (qual > 0) {
+ util.dprintln(4, "quality q1");
+ interpol = AffineTransformOp.TYPE_BILINEAR;
+ } else {
+ util.dprintln(4, "quality q0");
+ interpol = AffineTransformOp.TYPE_NEAREST_NEIGHBOR;
+ }
+ }
+
+ public int getHeight() {
+ int h = 0;
+ try {
+ if (img == null) {
+ h = reader.getHeight(0);
+ } else {
+ h = img.getHeight();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return h;
+ }
+
+ public int getWidth() {
+ int w = 0;
+ try {
+ if (img == null) {
+ w = reader.getWidth(0);
+ } else {
+ w = img.getWidth();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return w;
}
/**
@@ -63,6 +114,48 @@
}
}
+ /* Get an ImageReader for the image file. */
+ public void preloadImage(File f) throws FileOpException {
+ System.gc();
+ try {
+ ImageInputStream istream = ImageIO.createImageInputStream(f);
+ Iterator readers = ImageIO.getImageReaders(istream);
+ reader = (ImageReader) readers.next();
+ reader.setInput(istream);
+ } catch (IOException e) {
+ util.dprintln(3, "ERROR(loadImage): unable to load file");
+ throw new FileOpException("Unable to load File!" + e);
+ }
+ if (reader == null) {
+ util.dprintln(3, "ERROR(loadImage): unable to load file");
+ throw new FileOpException("Unable to load File!");
+ }
+ }
+
+ /* Load an image file into the Object. */
+ public void loadSubimage(File f, Rectangle region, int prescale)
+ throws FileOpException {
+ System.gc();
+ try {
+ if (reader == null) {
+ preloadImage(f);
+ }
+ // set up reader parameters
+ ImageReadParam readParam = reader.getDefaultReadParam();
+ readParam.setSourceRegion(region);
+ readParam.setSourceSubsampling(prescale, prescale, 0, 0);
+ // read image
+ img = reader.read(0, readParam);
+ } catch (IOException e) {
+ util.dprintln(3, "ERROR(loadImage): unable to load file");
+ throw new FileOpException("Unable to load File!");
+ }
+ if (img == null) {
+ util.dprintln(3, "ERROR(loadImage): unable to load file");
+ throw new FileOpException("Unable to load File!");
+ }
+ }
+
/**
* write image of type mt to Stream
*/
@@ -94,26 +187,12 @@
}
}
- public int getWidth() {
- if (img != null) {
- return img.getWidth();
- }
- return 0;
- }
-
- public int getHeight() {
- if (img != null) {
- return img.getHeight();
- }
- return 0;
- }
-
public void scale(double scale) throws ImageOpException {
// setup scale
AffineTransformOp scaleOp =
new AffineTransformOp(
AffineTransform.getScaleInstance(scale, scale),
- scaleInt);
+ interpol);
BufferedImage scaledImg = scaleOp.filter(img, null);
if (scaledImg == null) {
@@ -141,16 +220,102 @@
img = croppedImg;
}
- public void setQuality(int qual) {
- quality = qual;
- // setup interpolation quality
- if (qual > 0) {
- util.dprintln(4, "quality q1");
- scaleInt = AffineTransformOp.TYPE_BILINEAR;
+ public void enhance(double mult, double add) throws ImageOpException {
+ /* The number of constants must match the number of bands in the image.
+ * We only handle 1 (greyscale) or 3 (RGB) bands.
+ */
+ float[] dm;
+ float[] da;
+ int ncol = img.getColorModel().getNumColorComponents();
+ if (ncol == 3) {
+ float[] f1 = {(float)mult, (float)mult, (float)mult};
+ dm = f1;
+ float[] f2 = {(float)add, (float)add, (float)add};
+ da = f2;
+ } else if (ncol == 1) {
+ float[] f1 = {(float)mult};
+ dm = f1;
+ float[] f2 = {(float)add};
+ da = f2;
} else {
- util.dprintln(4, "quality q0");
- scaleInt = AffineTransformOp.TYPE_NEAREST_NEIGHBOR;
+ util.dprintln(2, "ERROR(enhance): unknown number of color bands ("+ncol+")");
+ return;
+ }
+ RescaleOp scaleOp =
+ new RescaleOp(
+ dm, da,
+ null);
+ scaleOp.filter(img, img);
+
+ /* Operation with only one constant should work regardless of the number of bands
+ * according to the JDK spec.
+ * Doesn't work on JDK 1.4 for OSX PR10 (at least).
+ */
+ /*
+ RescaleOp scaleOp =
+ new RescaleOp(
+ (float)mult, (float)add,
+ null);
+ scaleOp.filter(img, img);
+ */
+ }
+
+ public void rotate(double angle) throws ImageOpException {
+ // setup rotation
+ double rangle = Math.toRadians(angle);
+ double x = getWidth()/2;
+ double y = getHeight()/2;
+ AffineTransformOp rotOp =
+ new AffineTransformOp(
+ AffineTransform.getRotateInstance(rangle, x, y),
+ interpol);
+ BufferedImage rotImg = rotOp.filter(img, null);
+
+ if (rotImg == null) {
+ util.dprintln(2, "ERROR: error in rotate");
+ throw new ImageOpException("Unable to rotate");
}
+ img = rotImg;
+ }
+
+ public void mirror(double angle) throws ImageOpException {
+ // setup mirror
+ double mx = 1;
+ double my = 1;
+ double tx = 0;
+ double ty = 0;
+ if (Math.abs(angle - 0) < epsilon) {
+ // 0 degree
+ mx = -1;
+ tx = getWidth();
+ } else if (Math.abs(angle - 90) < epsilon) {
+ // 90 degree
+ my = -1;
+ ty = getHeight();
+ } else if (Math.abs(angle - 180) < epsilon) {
+ // 180 degree
+ mx = -1;
+ tx = getWidth();
+ } else if (Math.abs(angle - 270) < epsilon) {
+ // 270 degree
+ my = -1;
+ ty = getHeight();
+ } else if (Math.abs(angle - 360) < epsilon) {
+ // 360 degree
+ mx = -1;
+ tx = getWidth();
+ }
+ AffineTransformOp mirOp =
+ new AffineTransformOp(
+ new AffineTransform(mx, 0 , 0, my, tx, ty),
+ interpol);
+ BufferedImage mirImg = mirOp.filter(img, null);
+
+ if (mirImg == null) {
+ util.dprintln(2, "ERROR: error in mirror");
+ throw new ImageOpException("Unable to mirror");
+ }
+ img = mirImg;
}
}
diff -r ed1b698b4f0a -r 4e6757e8ccd4 servlet/src/digilib/image/JAIDocuImage.java
--- a/servlet/src/digilib/image/JAIDocuImage.java Mon Feb 10 17:09:28 2003 +0100
+++ b/servlet/src/digilib/image/JAIDocuImage.java Thu Feb 27 15:07:29 2003 +0100
@@ -2,7 +2,7 @@
Digital Image Library servlet components
- Copyright (C) 2001, 2002 Robert Casties (robcast@mail.berlios.de)
+ Copyright (C) 2001, 2002, 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
@@ -40,9 +40,6 @@
protected RenderedImage img;
protected Interpolation interpol = null;
- // epsilon for float comparisons
- public final double epsilon = 1e-5;
-
/** Default constructor. */
public JAIDocuImage() {
}
@@ -203,9 +200,8 @@
RenderedImage rotImg;
// convert degrees to radians
double rangle = Math.toRadians(angle);
- // rotate about the image center
- double xoff = img.getWidth() / 2;
- double yoff = img.getHeight() / 2;
+ float x = getWidth()/2;
+ float y = getHeight()/2;
// optimize rotation by right angles
TransposeType rotOp = null;
@@ -235,8 +231,8 @@
// setup "normal" rotation
ParameterBlock param = new ParameterBlock();
param.addSource(img);
- param.add((float) xoff);
- param.add((float) yoff);
+ param.add(x);
+ param.add(y);
param.add((float) rangle);
param.add(interpol);
// hint with border extender
@@ -251,9 +247,9 @@
util.dprintln(
3,
"ROTATE: "
- + xoff
+ + x
+ ","
- + yoff
+ + y
+ ", "
+ angle
+ " ("
diff -r ed1b698b4f0a -r 4e6757e8ccd4 servlet/src/digilib/image/JAIImageLoaderDocuImage.java
--- a/servlet/src/digilib/image/JAIImageLoaderDocuImage.java Mon Feb 10 17:09:28 2003 +0100
+++ b/servlet/src/digilib/image/JAIImageLoaderDocuImage.java Thu Feb 27 15:07:29 2003 +0100
@@ -2,7 +2,7 @@
Digital Image Library servlet components
- Copyright (C) 2001, 2002 Robert Casties (robcast@mail.berlios.de)
+ Copyright (C) 2002, 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
@@ -20,13 +20,21 @@
package digilib.image;
+import java.awt.Rectangle;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Iterator;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
import javax.media.jai.JAI;
+import com.sun.media.jai.operator.ImageReadDescriptor;
+
import digilib.io.FileOpException;
/** DocuImage implementation using the Java Advanced Imaging API and the ImageLoader
@@ -34,6 +42,46 @@
*/
public class JAIImageLoaderDocuImage extends JAIDocuImage {
+ // ImageIO image reader
+ ImageReader reader;
+
+ /* preload is supported. */
+ public boolean isPreloadSupported() {
+ return true;
+ }
+
+ /* loadSubimage is supported. */
+ public boolean isSubimageSupported() {
+ return true;
+ }
+
+ public int getHeight() {
+ int h = 0;
+ try {
+ if (img == null) {
+ h = reader.getHeight(0);
+ } else {
+ h = img.getHeight();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return h;
+ }
+
+ public int getWidth() {
+ int w = 0;
+ try {
+ if (img == null) {
+ w = reader.getWidth(0);
+ } else {
+ w = img.getWidth();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return w;
+ }
/* Load an image file into the Object. */
public void loadImage(File f) throws FileOpException {
@@ -45,6 +93,62 @@
}
}
+ /* Load an image file into the Object. */
+ public void loadSubimage(File f, Rectangle region, int prescale)
+ throws FileOpException {
+ System.gc();
+ try {
+ if (reader == null) {
+ preloadImage(f);
+ }
+ ImageInputStream istream = (ImageInputStream) reader.getInput();
+ ImageReadParam readParam = reader.getDefaultReadParam();
+ readParam.setSourceRegion(region);
+ readParam.setSourceSubsampling(prescale, prescale, 0, 0);
+ /* Parameter for ImageRead operation:
+ Input, ImageChoice, ReadMetadata, ReadThumbnails, VerifyInput,
+ Listeners, Locale, ReadParam, Reader, RenderingHints
+ */
+ img =
+ ImageReadDescriptor.create(
+ istream,
+ new Integer(0),
+ Boolean.TRUE,
+ Boolean.FALSE,
+ Boolean.FALSE,
+ null,
+ null,
+ readParam,
+ reader,
+ null);
+ } catch (IOException e) {
+ util.dprintln(3, "ERROR(loadImage): unable to load file");
+ throw new FileOpException("Unable to load File!");
+ }
+ if (img == null) {
+ util.dprintln(3, "ERROR(loadImage): unable to load file");
+ throw new FileOpException("Unable to load File!");
+ }
+ }
+
+ /* Get an ImageReader for the image file. */
+ public void preloadImage(File f) throws FileOpException {
+ System.gc();
+ try {
+ ImageInputStream istream = ImageIO.createImageInputStream(f);
+ Iterator readers = ImageIO.getImageReaders(istream);
+ reader = (ImageReader) readers.next();
+ reader.setInput(istream);
+ } catch (IOException e) {
+ util.dprintln(3, "ERROR(loadImage): unable to load file");
+ throw new FileOpException("Unable to load File!" + e);
+ }
+ if (reader == null) {
+ util.dprintln(3, "ERROR(loadImage): unable to load file");
+ throw new FileOpException("Unable to load File!");
+ }
+ }
+
/* Write the current image to an OutputStream. */
public void writeImage(String mt, OutputStream ostream)
throws FileOpException {
diff -r ed1b698b4f0a -r 4e6757e8ccd4 servlet/src/digilib/io/FileOps.java
--- a/servlet/src/digilib/io/FileOps.java Mon Feb 10 17:09:28 2003 +0100
+++ b/servlet/src/digilib/io/FileOps.java Thu Feb 27 15:07:29 2003 +0100
@@ -1,4 +1,4 @@
-/* FileOps -- Utility class for file operations
+/* FileOps -- Utility class for file operations
Digital Image Library servlet components
diff -r ed1b698b4f0a -r 4e6757e8ccd4 servlet/src/digilib/servlet/DigilibConfiguration.java
--- a/servlet/src/digilib/servlet/DigilibConfiguration.java Mon Feb 10 17:09:28 2003 +0100
+++ b/servlet/src/digilib/servlet/DigilibConfiguration.java Thu Feb 27 15:07:29 2003 +0100
@@ -77,7 +77,7 @@
private int debugLevel = 5;
private String debugLevelParam = "debug-level";
// Utils instance
- private Utils util = new Utils();
+ private Utils util = new Utils(debugLevel);
// HashTable for parameters
private Hashtable confTable = null;
// Type of DocuImage instance
@@ -86,6 +86,9 @@
// part of URL used to indicate authorized access
private String authURLPath = "authenticated/";
private String AuthURLPathParam = "auth-url-path";
+ // degree of subsampling on image load
+ private float subsampleDistance = 0;
+ private String subsampleDistanceParam = "subsample-distance";
/** Constructor taking a ServletConfig.
* Reads the config file location from an init parameter and loads the
@@ -117,7 +120,7 @@
XMLListLoader lilo =
new XMLListLoader("digilib-config", "parameter", "name", "value");
confTable = lilo.loadURL(f.toURL().toString());
- dlConfPath = fn;
+ dlConfPath = f.getCanonicalPath();
/*
* read parameters
@@ -125,6 +128,7 @@
// debugLevel
debugLevel = tryToGetInitParam(debugLevelParam, debugLevel);
+ util.setDebugLevel(debugLevel);
// errorImgFileName
errorImgFileName = tryToGetInitParam(errorImgParam, errorImgFileName);
// denyImgFileName
@@ -151,6 +155,8 @@
authConfPath = tryToGetInitParam(authConfParam, authConfPath);
authOp = new XMLAuthOps(util, authConfPath);
}
+ // subsampleDistance
+ subsampleDistance = tryToGetInitParam(subsampleDistanceParam, subsampleDistance);
}
/**
@@ -455,4 +461,19 @@
return dlConfPath;
}
+ /**
+ * @return float
+ */
+ public float getSubsampleDistance() {
+ return subsampleDistance;
+ }
+
+ /**
+ * Sets the subsampleDistance.
+ * @param subsampleDistance The subsampleDistance to set
+ */
+ public void setSubsampleDistance(float subsampleDistance) {
+ this.subsampleDistance = subsampleDistance;
+ }
+
}
diff -r ed1b698b4f0a -r 4e6757e8ccd4 servlet/src/digilib/servlet/Scaler.java
--- a/servlet/src/digilib/servlet/Scaler.java Mon Feb 10 17:09:28 2003 +0100
+++ b/servlet/src/digilib/servlet/Scaler.java Thu Feb 27 15:07:29 2003 +0100
@@ -52,7 +52,7 @@
public class Scaler extends HttpServlet {
// digilib servlet version (for all components)
- public static final String dlVersion = "1.6b";
+ public static final String dlVersion = "1.6b3";
// Utils instance with debuglevel
Utils util;
@@ -331,7 +331,12 @@
}
// finally load the file
- docuImage.loadImage(fileToLoad);
+ if (docuImage.isPreloadSupported()) {
+ // only preload if supported
+ docuImage.preloadImage(fileToLoad);
+ } else {
+ docuImage.loadImage(fileToLoad);
+ }
/*
* crop and scale the image
@@ -348,20 +353,21 @@
// coordinates using Java2D
// image size
- Rectangle2D imgBounds = new Rectangle2D.Double(0, 0, imgWidth, imgHeight);
+ Rectangle2D imgBounds =
+ new Rectangle2D.Double(0, 0, imgWidth, imgHeight);
// user window area in 4-point form (ul, ur, ll, lr)
- Point2D[] userAreaC = {
- new Point2D.Double(paramWX, paramWY),
- new Point2D.Double(paramWX + paramWW, paramWY),
- new Point2D.Double(paramWX, paramWY + paramWH),
- new Point2D.Double(paramWX + paramWW, paramWY + paramWH)
- };
+ Point2D[] userAreaC =
+ {
+ new Point2D.Double(paramWX, paramWY),
+ new Point2D.Double(paramWX + paramWW, paramWY),
+ new Point2D.Double(paramWX, paramWY + paramWH),
+ new Point2D.Double(paramWX + paramWW, paramWY + paramWH)};
// transformation from relative [0,1] to image coordinates.
AffineTransform imgTrafo = new AffineTransform();
imgTrafo.scale(imgWidth, imgHeight);
// rotate coordinates
//imgTrafo.rotate(Math.toRadians(-paramROT));
-
+
// coordinates and scaling
double areaXoff;
double areaYoff;
@@ -371,27 +377,68 @@
double scaleY;
double scaleXY;
+ /* if (scaleToFit) {
+ // calculate absolute from relative coordinates
+ areaXoff = paramWX * imgWidth;
+ areaYoff = paramWY * imgHeight;
+ areaWidth = paramWW * imgWidth;
+ areaHeight = paramWH * imgHeight;
+ // calculate scaling factors
+ scaleX = paramDW / areaWidth * paramWS;
+ scaleY = paramDH / areaHeight * paramWS;
+ scaleXY = (scaleX > scaleY) ? scaleY : scaleX;
+ } else {
+ // crop to fit
+ // calculate absolute from relative coordinates
+ areaXoff = paramWX * imgWidth;
+ areaYoff = paramWY * imgHeight;
+ areaWidth = paramDW;
+ areaHeight = paramDH;
+ // calculate scaling factors
+ scaleX = 1f;
+ scaleY = 1f;
+ scaleXY = 1f;
+ }
+
+ util.dprintln(
+ 1,
+ "Scale "
+ + scaleXY
+ + "("
+ + scaleX
+ + ","
+ + scaleY
+ + ") on "
+ + areaXoff
+ + ","
+ + areaYoff
+ + " "
+ + areaWidth
+ + "x"
+ + areaHeight);
+ */
+ // Java2D
+ // area in image pixel coordinates
+ Point2D[] imgAreaC = { null, null, null, null };
+ // transform user coordinate area to image coordinate area
+ imgTrafo.transform(userAreaC, 0, imgAreaC, 0, 4);
+ areaXoff = imgAreaC[0].getX();
+ areaYoff = imgAreaC[0].getY();
+ // calculate scaling factors
if (scaleToFit) {
- // calculate absolute from relative coordinates
- areaXoff = paramWX * imgWidth;
- areaYoff = paramWY * imgHeight;
- areaWidth = paramWW * imgWidth;
- areaHeight = paramWH * imgHeight;
- // calculate scaling factors
+ areaWidth = imgAreaC[0].distance(imgAreaC[1]);
+ areaHeight = imgAreaC[0].distance(imgAreaC[2]);
scaleX = paramDW / areaWidth * paramWS;
scaleY = paramDH / areaHeight * paramWS;
scaleXY = (scaleX > scaleY) ? scaleY : scaleX;
} else {
// crop to fit
- // calculate absolute from relative coordinates
- areaXoff = paramWX * imgWidth;
- areaYoff = paramWY * imgHeight;
- areaWidth = paramDW;
- areaHeight = paramDH;
- // calculate scaling factors
+ areaWidth = paramDW * paramWS;
+ areaHeight = paramDH * paramWS;
scaleX = 1f;
scaleY = 1f;
scaleXY = 1f;
+
}
util.dprintln(
@@ -411,42 +458,6 @@
+ "x"
+ areaHeight);
- // Java2D
- Point2D[] imgAreaC = { null, null, null, null };
-
- imgTrafo.transform(userAreaC, 0, imgAreaC, 0, 4);
- areaXoff = imgAreaC[0].getX();
- areaYoff = imgAreaC[0].getY();
- areaWidth = imgAreaC[0].distance(imgAreaC[1]);
- areaHeight = imgAreaC[0].distance(imgAreaC[2]);
- Rectangle2D imgArea =
- new Rectangle2D.Double(
- areaXoff,
- areaYoff,
- areaWidth,
- areaHeight);
- // calculate scaling factors
- scaleX = paramDW / areaWidth * paramWS;
- scaleY = paramDH / areaHeight * paramWS;
- scaleXY = (scaleX > scaleY) ? scaleY : scaleX;
-
- util.dprintln(
- 1,
- "Scale "
- + scaleXY
- + "("
- + scaleX
- + ","
- + scaleY
- + ") on "
- + areaXoff
- + ","
- + areaYoff
- + " "
- + areaWidth
- + "x"
- + areaHeight);
-
// clip area at the image border
/* areaWidth =
(areaXoff + areaWidth > imgWidth)
@@ -457,13 +468,22 @@
? imgHeight - areaYoff
: areaHeight;
*/
+
+ // create new rectangle from coordinates
+ Rectangle2D imgArea =
+ new Rectangle2D.Double(
+ areaXoff,
+ areaYoff,
+ areaWidth,
+ areaHeight);
+ // clip area at the image border
imgArea = imgArea.createIntersection(imgBounds);
areaWidth = imgArea.getWidth();
areaHeight = imgArea.getHeight();
util.dprintln(
2,
- "cropped: "
+ "crop: "
+ areaXoff
+ ","
+ areaYoff
@@ -481,14 +501,48 @@
throw new ImageOpException("Invalid scale parameter set!");
}
- // crop and scale image
- docuImage.crop(
- (int) areaXoff,
- (int) areaYoff,
- (int) areaWidth,
- (int) areaHeight);
+ /*
+ * crop and scale image
+ */
+
+ // use subimage loading if possible
+ if (docuImage.isSubimageSupported()) {
+ System.out.println(
+ "Subimage: scale " + scaleXY + " = " + (1 / scaleXY));
+ double subf = 1d;
+ double subsamp = 1d;
+ if (scaleXY < 1) {
+ subf = 1 / scaleXY;
+ subsamp = Math.floor(subf);
+ scaleXY = subsamp / subf;
+ System.out.println(
+ "Using subsampling: " + subsamp + " rest " + scaleXY);
+ }
- docuImage.scale(scaleXY);
+ docuImage.loadSubimage(
+ fileToLoad,
+ imgArea.getBounds(),
+ (int) subsamp);
+
+ System.out.println(
+ "SUBSAMP: "
+ + subsamp
+ + " -> "
+ + docuImage.getWidth()
+ + "x"
+ + docuImage.getHeight());
+
+ docuImage.scale(scaleXY);
+
+ } else {
+ docuImage.crop(
+ (int) areaXoff,
+ (int) areaYoff,
+ (int) areaWidth,
+ (int) areaHeight);
+
+ docuImage.scale(scaleXY);
+ }
// mirror image
if (doMirror) {
@@ -497,12 +551,13 @@
// rotate image (first shot :-)
if (paramROT != 0) {
- docuImage.rotate(paramROT);
+ docuImage.rotate(
+ paramROT);
}
// contrast and brightness enhancement
if ((paramCONT != 0) || (paramBRGT != 0)) {
- double mult = Math.pow(2, paramCONT);
+ double mult = Math.pow(2, paramCONT);
docuImage.enhance(mult, paramBRGT);
}