digilib doesn't work! Please switch on Javascript or notify the server administrator!
+mt
and sent to the output
- * stream of the ServletResponse
res
.
+ * stream ostream
.
*
* Currently only mime-types "image/jpeg" and "image/png" are supported.
*
* @param mt mime-type of the image to be sent.
- * @param res ServletResponse where the image is sent.
+ * @param ostream OutputStream where the image is sent.
* @throws ServletException Exception thrown on sending data.
* @throws ImageOpException Exception in other cases.
*/
@@ -95,7 +96,7 @@
*/
public ImageSize getSize();
- /** The mime-type of the current image.
+ /** The mime-type of the image, i.e. the mime-type of the input that was read.
*
* @return String the mime-type of this image.
*/
@@ -201,6 +202,22 @@
public void enhanceRGB(float[] rgbm, float[] rgba)
throws ImageOpException;
+
+ /** Operations for colorOps.
+ *
+ *
+ */
+ public enum ColorOp {GRAYSCALE, INVERT};
+
+ /** Changes the colors of the current image.
+ *
+ * Changes the colors of the current image. Operations are e.g.
+ * reduction to grayscale or false-color palettes.
+ *
+ * @throws ImageOpException
+ */
+ public void colorOp(ColorOp op) throws ImageOpException;
+
/**
* Returns the interpolation quality.
* @return int
@@ -221,9 +238,9 @@
public void dispose();
/**
- * Check image size and type and store in ImageFile f
+ * Check image size and type and store in ImageInput ii
*/
- public ImageFile identify(ImageFile imgf) throws IOException;
+ public ImageInput identify(ImageInput ii) throws IOException;
/**
* Returns a list of supported image formats
diff -r 9fa078dcb493 -r a7e157d258e8 servlet/src/digilib/image/DocuImageImpl.java
--- a/servlet/src/digilib/image/DocuImageImpl.java Tue Mar 01 17:12:25 2011 +0100
+++ b/servlet/src/digilib/image/DocuImageImpl.java Tue Mar 01 22:00:50 2011 +0100
@@ -33,7 +33,8 @@
import org.apache.log4j.Logger;
import digilib.io.FileOpException;
-import digilib.io.ImageFile;
+import digilib.io.ImageInput;
+import digilib.util.ImageSize;
/** Simple abstract implementation of the DocuImage
interface.
*
@@ -53,13 +54,13 @@
/** epsilon for float comparisons. */
public final double epsilon = 1e-5;
-
- /** image mime-type */
- protected String mimeType = null;
/** image size */
protected ImageSize imgSize = null;
+ /** ImageInput that was read */
+ protected ImageInput input;
+
/**
* Returns the quality.
* @return int
@@ -99,14 +100,20 @@
scale(scale, scale);
}
+ /* (non-Javadoc)
+ * @see digilib.image.DocuImage#getMimetype()
+ */
public String getMimetype() {
- return mimeType;
+ if (input != null) {
+ return input.getMimetype();
+ }
+ return null;
}
/* (non-Javadoc)
* @see digilib.image.DocuImage#identify(digilib.io.ImageFile)
*/
- public ImageFile identify(ImageFile imgf) throws IOException {
+ public ImageInput identify(ImageInput ii) throws IOException {
// just a do-nothing implementation
return null;
}
@@ -128,7 +135,7 @@
return false;
}
- public void loadSubimage(ImageFile f, Rectangle region, int subsample)
+ public void loadSubimage(ImageInput ii, Rectangle region, int subsample)
throws FileOpException {
// empty implementation
}
@@ -138,6 +145,10 @@
// emtpy implementation
}
+ public void colorOp(ColorOp op) throws ImageOpException {
+ // emtpy implementation
+ }
+
public void dispose() {
// emtpy implementation
}
@@ -149,11 +160,11 @@
public void crop(int xoff, int yoff, int width, int height)
throws ImageOpException {
- // TODO Auto-generated method stub
+ // emtpy implementation
}
public Image getAwtImage() {
- // TODO Auto-generated method stub
+ // emtpy implementation
return null;
}
@@ -177,19 +188,12 @@
return imgSize;
}
- public void loadImage(ImageFile f) throws FileOpException {
- // TODO Auto-generated method stub
-
- }
+ public abstract void loadImage(ImageInput ii) throws FileOpException;
+
+ public abstract void scale(double scaleX, double scaleY) throws ImageOpException;
- public void scale(double scaleX, double scaleY) throws ImageOpException {
- // TODO Auto-generated method stub
-
- }
+ public abstract void writeImage(String mt, OutputStream ostream)
+ throws ServletException, ImageOpException;
- public void writeImage(String mt, OutputStream ostream)
- throws ServletException, ImageOpException {
- // TODO Auto-generated method stub
- }
}
diff -r 9fa078dcb493 -r a7e157d258e8 servlet/src/digilib/image/ImageInfoDocuImage.java
--- a/servlet/src/digilib/image/ImageInfoDocuImage.java Tue Mar 01 17:12:25 2011 +0100
+++ b/servlet/src/digilib/image/ImageInfoDocuImage.java Tue Mar 01 22:00:50 2011 +0100
@@ -3,13 +3,13 @@
*/
package digilib.image;
-import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import org.marcoschmidt.image.ImageInfo;
-import digilib.io.ImageFile;
+import digilib.io.ImageInput;
+import digilib.util.ImageSize;
/** Simple abstract implementation of the DocuImage
interface.
* Implements only the identify method using the ImageInfo class.
@@ -18,31 +18,38 @@
*/
public abstract class ImageInfoDocuImage extends DocuImageImpl {
- /** Check image size and type and store in ImageFile f */
- public ImageFile identify(ImageFile imgf) throws IOException {
- // fileset to store the information
- File f = imgf.getFile();
- if (f == null) {
- throw new IOException("File not found!");
- }
- RandomAccessFile raf = new RandomAccessFile(f, "r");
- // set up ImageInfo object
- ImageInfo iif = new ImageInfo();
- iif.setInput(raf);
- iif.setCollectComments(false);
- iif.setDetermineImageNumber(false);
- logger.debug("identifying (ImageInfo) " + f);
- // try with ImageInfo first
- if (iif.check()) {
- ImageSize d = new ImageSize(iif.getWidth(), iif.getHeight());
- imgf.setSize(d);
- imgf.setMimetype(iif.getMimeType());
- //logger.debug(" format:"+iif.getFormatName());
- raf.close();
- logger.debug("image size: " + imgf.getSize());
- return imgf;
- } else {
- raf.close();
+ /* Check image size and type and store in ImageFile f */
+ public ImageInput identify(ImageInput ii) throws IOException {
+ logger.debug("identifying (ImageInfo) " + ii);
+ RandomAccessFile raf = null;
+ try {
+ // set up ImageInfo object
+ ImageInfo iif = new ImageInfo();
+ if (ii.hasImageInputStream()) {
+ iif.setInput(ii.getImageInputStream());
+ } else if (ii.hasFile()) {
+ raf = new RandomAccessFile(ii.getFile(), "r");
+ iif.setInput(raf);
+ } else {
+ return null;
+ }
+ iif.setCollectComments(false);
+ iif.setDetermineImageNumber(false);
+ // try with ImageInfo first
+ if (iif.check()) {
+ ImageSize d = new ImageSize(iif.getWidth(), iif.getHeight());
+ ii.setSize(d);
+ ii.setMimetype(iif.getMimeType());
+ logger.debug("image size: " + ii.getSize());
+ return ii;
+ }
+ } catch (Exception e) {
+ logger.debug("ImageInfoDocuimage unable to identify.", e);
+ } finally {
+ // close file, don't close stream(?)
+ if (raf != null) {
+ raf.close();
+ }
}
return null;
}
diff -r 9fa078dcb493 -r a7e157d258e8 servlet/src/digilib/image/ImageJobDescription.java
--- a/servlet/src/digilib/image/ImageJobDescription.java Tue Mar 01 17:12:25 2011 +0100
+++ b/servlet/src/digilib/image/ImageJobDescription.java Tue Mar 01 22:00:50 2011 +0100
@@ -6,29 +6,29 @@
import org.apache.log4j.Logger;
+import digilib.image.DocuImage.ColorOp;
import digilib.io.DocuDirCache;
import digilib.io.DocuDirectory;
import digilib.io.FileOpException;
import digilib.io.FileOps;
import digilib.io.FileOps.FileClass;
-import digilib.io.ImageFile;
-import digilib.io.ImageFileset;
+import digilib.io.ImageInput;
+import digilib.io.ImageSet;
import digilib.servlet.DigilibConfiguration;
+import digilib.util.ImageSize;
import digilib.util.OptionsSet;
import digilib.util.Parameter;
import digilib.util.ParameterMap;
-
-/**
- * A container class for storing a set of instructional parameters
- * used for content generating classes like MakePDF.
+/**
+ * A class for storing the set of parameters necessary for scaling images
+ * with an ImageWorker.
*
- * This contains the functionality formerly found in Scaler, processRequest, only factorized.
- *
- * TODO clean up...
+ * This contains the functionality formerly found in Scaler.processRequest(),
+ * only factorized.
*
* @author cmielack, casties
- *
+ *
*/
public class ImageJobDescription extends ParameterMap {
@@ -36,18 +36,18 @@
DigilibConfiguration dlConfig = null;
protected static Logger logger = Logger.getLogger("digilib.servlet");
- ImageFile fileToLoad = null;
- ImageFileset fileset = null;
+ ImageInput input = null;
+ ImageSet imageSet = null;
DocuDirectory fileDir = null;
String filePath = null;
ImageSize expectedSourceSize = null;
Float scaleXY = null;
Rectangle2D userImgArea = null;
- Rectangle2D outerUserImgArea= null;
+ Rectangle2D outerUserImgArea = null;
Boolean imageSendable = null;
- String mimeType;
- Integer paramDW;
- Integer paramDH;
+ String mimeType = null;
+ Integer paramDW = null;
+ Integer paramDH = null;
/** create empty ImageJobDescription.
* @param dlcfg
@@ -101,6 +101,8 @@
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');
}
@@ -128,48 +130,57 @@
}
+ /** Returns the mime-type (of the input).
+ * @return
+ * @throws IOException
+ */
public String getMimeType() throws IOException {
if (mimeType == null) {
- fileToLoad = getFileToLoad();
- if(! fileToLoad.isChecked()){
- DigilibConfiguration.docuImageIdentify(fileToLoad);
- }
- mimeType = fileToLoad.getMimetype();
+ input = getInput();
+ mimeType = input.getMimetype();
}
return mimeType;
}
- public ImageFile getFileToLoad() throws IOException {
-
- if(fileToLoad == null){
- fileset = getFileset();
+ /** Returns the ImageInput to use.
+ * @return
+ * @throws IOException
+ */
+ public ImageInput getInput() throws IOException {
+ if(input == null){
+ imageSet = getImageSet();
/* select a resolution */
- if (getHiresOnly()) {
+ if (isHiresOnly()) {
// get first element (= highest resolution)
- fileToLoad = fileset.getBiggest();
- } else if (getLoresOnly()) {
+ input = imageSet.getBiggest();
+ } else if (isLoresOnly()) {
// enforced lores uses next smaller resolution
- fileToLoad = fileset.getNextSmaller(getExpectedSourceSize());
- if (fileToLoad == null) {
+ input = imageSet.getNextSmaller(getExpectedSourceSize());
+ if (input == null) {
// this is the smallest we have
- fileToLoad = fileset.getSmallest();
+ input = imageSet.getSmallest();
}
} else {
// autores: use next higher resolution
- fileToLoad = fileset.getNextBigger(getExpectedSourceSize());
- if (fileToLoad == null) {
+ input = imageSet.getNextBigger(getExpectedSourceSize());
+ if (input == null) {
// this is the highest we have
- fileToLoad = fileset.getBiggest();
+ input = imageSet.getBiggest();
}
}
- logger.info("Planning to load: " + fileToLoad.getFile());
+ if (input == null || input.getMimetype() == null) {
+ throw new FileOpException("Unable to load "+input);
+ }
+ logger.info("Planning to load: " + input);
}
-
- return fileToLoad;
-
+ 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");
@@ -182,19 +193,26 @@
return fileDir;
}
- public ImageFileset getFileset() throws FileOpException {
- if(fileset==null){
+ /** Returns the ImageSet to load.
+ * @return
+ * @throws FileOpException
+ */
+ public ImageSet getImageSet() throws FileOpException {
+ if(imageSet==null){
DocuDirCache dirCache = (DocuDirCache) dlConfig.getValue("servlet.dir.cache");
- fileset = (ImageFileset) dirCache.getFile(getFilePath(), getAsInt("pn"), FileClass.IMAGE);
- if (fileset == null) {
+ imageSet = (ImageSet) dirCache.getFile(getFilePath(), getAsInt("pn"), FileClass.IMAGE);
+ if (imageSet == null) {
throw new FileOpException("File " + getFilePath() + "("
+ getAsInt("pn") + ") not found.");
}
}
- return fileset;
+ return imageSet;
}
+ /** Returns the file path name from the request.
+ * @return
+ */
public String getFilePath() {
if(filePath == null){
String s = this.getAsString("request.path");
@@ -204,32 +222,36 @@
return filePath;
}
- public boolean getHiresOnly(){
+ public boolean isHiresOnly(){
return hasOption("clip") || hasOption("hires");
}
- public boolean getLoresOnly(){
+ public boolean isLoresOnly(){
return hasOption("lores");
}
- public boolean getScaleToFit() {
+ public boolean isScaleToFit() {
return !(hasOption("clip") || hasOption("osize") || hasOption("ascale"));
}
- public boolean getAbsoluteScale(){
+ 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 (getScaleToFit()) {
+ 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 (getAbsoluteScale() && hasOption("ascale")) {
+ } else if (isAbsoluteScale() && hasOption("ascale")) {
// absolute scale -- apply scale to hires size
expectedSourceSize = getHiresSize().getScaled(getAsFloat("scale"));
} else {
@@ -241,16 +263,17 @@
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;
- ImageFileset fileset = getFileset();
- if (getAbsoluteScale()) {
- ImageFile hiresFile = fileset.getBiggest();
- if (!hiresFile.isChecked()) {
- DigilibConfiguration.docuImageIdentify(hiresFile);
- }
+ ImageSet fileset = getImageSet();
+ if (isAbsoluteScale()) {
+ ImageInput hiresFile = fileset.getBiggest();
hiresSize = hiresFile.getSize();
}
return hiresSize;
@@ -270,7 +293,7 @@
float areaWidth;
float areaHeight;
float ws = getAsFloat("ws");
- ImageSize imgSize = getFileToLoad().getSize();
+ ImageSize imgSize = getInput().getSize();
// user window area in [0,1] coordinates
Rectangle2D relUserArea = new Rectangle2D.Float(getAsFloat("wx"), getAsFloat("wy"),
getAsFloat("ww"), getAsFloat("wh"));
@@ -281,20 +304,20 @@
userImgArea = imgTrafo.createTransformedShape(
relUserArea).getBounds2D();
- if (getScaleToFit()) {
+ 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 (getAbsoluteScale()) {
+ } else if (isAbsoluteScale()) {
// absolute scaling factor
if (hasOption("osize")) {
// get original resolution from metadata
- fileset.checkMeta();
- float origResX = fileset.getResX();
- float origResY = fileset.getResY();
+ imageSet.checkMeta();
+ float origResX = imageSet.getResX();
+ float origResY = imageSet.getResY();
if ((origResX == 0) || (origResY == 0)) {
throw new ImageOpException("Missing image DPI information!");
}
@@ -340,6 +363,11 @@
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) {
@@ -347,7 +375,7 @@
paramDW = getAsInt("dw");
paramDH = getAsInt("dh");
- float imgAspect = getFileToLoad().getAspect();
+ float imgAspect = getInput().getAspect();
if (paramDW == 0) {
// calculate dw
paramDW = Math.round(paramDH * imgAspect);
@@ -361,6 +389,11 @@
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) {
@@ -368,7 +401,7 @@
paramDW = getAsInt("dw");
paramDH = getAsInt("dh");
- float imgAspect = getFileToLoad().getAspect();
+ float imgAspect = getInput().getAspect();
if (paramDW == 0) {
// calculate dw
paramDW = Math.round(paramDH * imgAspect);
@@ -382,9 +415,12 @@
return paramDH;
}
- public Integer getScaleQual(){
+ /** Returns image quality as an integer.
+ * @return
+ */
+ public int getScaleQual(){
logger.debug("get_scaleQual()");
- Integer qual = dlConfig.getAsInt("default-quality");
+ int qual = dlConfig.getAsInt("default-quality");
if(hasOption("q0"))
qual = 0;
else if(hasOption("q1"))
@@ -394,22 +430,43 @@
return qual;
}
+ public ColorOp getColOp() {
+ String op = getAsString("colop");
+ 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 = getFileToLoad().getSize();
+ ImageSize imgSize = getInput().getSize();
Rectangle2D imgBounds = new Rectangle2D.Float(0, 0, imgSize.getWidth(),
imgSize.getHeight());
@@ -437,10 +494,7 @@
float[] paramRGBM = null;//{0f,0f,0f};
Parameter p = params.get("rgbm");
if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) {
- paramRGBM = p.parseAsFloatArray("/");
- if ((paramRGBM == null) || (paramRGBM.length != 3)) {
- return null;
- }
+ return p.parseAsFloatArray("/");
}
return paramRGBM;
}
@@ -450,9 +504,6 @@
Parameter p = params.get("rgba");
if (p.hasValue() && (!p.getAsString().equals("0/0/0"))) {
paramRGBA = p.parseAsFloatArray("/");
- if ((paramRGBA == null) || (paramRGBA.length != 3)) {
- return null;
- }
}
return paramRGBA;
}
@@ -465,42 +516,45 @@
|| hasOption("rawfile");
}
- /** Could the image be sent without processing?
- * Takes image type and additional image operations into account.
- * Does not check requested size transformation.
- * @return
- * @throws IOException
- */
- public boolean isImageSendable() throws IOException {
- // cached result?
- if (imageSendable == null) {
- String mimeType = getMimeType();
- imageSendable = ( (mimeType.equals("image/jpeg")
- || mimeType.equals("image/png")
- || mimeType.equals("image/gif") )
- &&
- !(hasOption("hmir")
- || hasOption("vmir")
- || (getAsFloat("rot") != 0.0)
- || (getRGBM() != null)
- || (getRGBA() != null)
- || (getAsFloat("cont") != 0.0)
- || (getAsFloat("brgt") != 0.0)));
- }
-
- return imageSendable;
- }
+ /**
+ * Returns if the image can be sent without processing. Takes image type and
+ * additional image operations into account. Does not check requested size
+ * transformation.
+ *
+ * @return
+ * @throws IOException
+ */
+ public boolean isImageSendable() throws IOException {
+ 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)
+ || (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 = getFileToLoad().getSize();
+ ImageSize is = getInput().getSize();
ImageSize ess = getExpectedSourceSize();
// nt = no transform required
boolean nt = isImageSendable() && (
// lores: send if smaller
- (getLoresOnly() && is.isSmallerThan(ess))
+ (isLoresOnly() && is.isSmallerThan(ess))
// else send if it fits
- || (!(getLoresOnly() || getHiresOnly()) && is.fitsIn(ess)));
+ || (!(isLoresOnly() || isHiresOnly()) && is.fitsIn(ess)));
return ! nt;
}
}
\ No newline at end of file
diff -r 9fa078dcb493 -r a7e157d258e8 servlet/src/digilib/image/ImageLoaderDocuImage.java
--- a/servlet/src/digilib/image/ImageLoaderDocuImage.java Tue Mar 01 17:12:25 2011 +0100
+++ b/servlet/src/digilib/image/ImageLoaderDocuImage.java Tue Mar 01 22:00:50 2011 +0100
@@ -2,7 +2,7 @@
Digital Image Library servlet components
- Copyright (C) 2002, 2003 Robert Casties (robcast@mail.berlios.de)
+ Copyright (C) 2002 - 2011 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
@@ -22,14 +22,19 @@
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
+import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
+import java.awt.image.ByteLookupTable;
+import java.awt.image.ColorConvertOp;
+import java.awt.image.ColorModel;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
+import java.awt.image.LookupOp;
+import java.awt.image.LookupTable;
import java.awt.image.RescaleOp;
-import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
@@ -49,24 +54,48 @@
import digilib.io.FileOpException;
import digilib.io.FileOps;
-import digilib.io.ImageFile;
-import digilib.io.ImageFileset;
+import digilib.io.ImageInput;
+import digilib.util.ImageSize;
/** Implementation of DocuImage using the ImageLoader API of Java 1.4 and Java2D. */
public class ImageLoaderDocuImage extends ImageInfoDocuImage {
-
+
/** image object */
protected BufferedImage img;
/** interpolation type */
- protected RenderingHints renderHint;
+ protected RenderingHints renderHint = null;
+
+ /** convolution kernels for blur() */
+ protected static Kernel[] convolutionKernels = {
+ null,
+ new Kernel(1, 1, new float[] {1f}),
+ new Kernel(2, 2, new float[] {0.25f, 0.25f, 0.25f, 0.25f}),
+ new Kernel(3, 3, new float[] {1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f, 1f/9f})
+ };
- /** ImageIO image reader */
- protected ImageReader reader;
-
- /** File that was read */
- protected File imgFile;
-
+ /** lookup table for inverting images (byte) */
+ protected static LookupTable invertByteTable;
+ protected static LookupTable invertRGBByteTable;
+
+ static {
+ byte[] invertByte = new byte[256];
+ byte[] orderedByte = new byte[256];
+ for (int i = 0; i < 256; ++i) {
+ invertByte[i] = (byte) (256 - i);
+ orderedByte[i] = (byte) i;
+ }
+ // works for JPEG in q2
+ invertRGBByteTable = new ByteLookupTable(0, new byte[][] {
+ orderedByte, invertByte, invertByte});
+ // should work for all color models
+ invertByteTable = new ByteLookupTable(0, invertByte);
+ }
+
+ /** the size of the current image */
+ protected ImageSize imageSize;
+
+
/* loadSubimage is supported. */
public boolean isSubimageSupported() {
return true;
@@ -91,25 +120,26 @@
/* returns the size of the current image */
public ImageSize getSize() {
- ImageSize is = null;
- // TODO: do we want to cache imageSize?
- int h = 0;
- int w = 0;
- try {
- if (img == null) {
- // get size from ImageReader
- h = reader.getHeight(0);
- w = reader.getWidth(0);
- } else {
- // get size from image
- h = img.getHeight();
- w = img.getWidth();
+ if (imageSize == null) {
+ int h = 0;
+ int w = 0;
+ try {
+ if (img == null) {
+ ImageReader reader = getReader(input);
+ // get size from ImageReader
+ h = reader.getHeight(0);
+ w = reader.getWidth(0);
+ } else {
+ // get size from image
+ h = img.getHeight();
+ w = img.getWidth();
+ }
+ imageSize = new ImageSize(w, h);
+ } catch (IOException e) {
+ logger.debug("error in getSize:", e);
}
- is = new ImageSize(w, h);
- } catch (IOException e) {
- logger.debug("error in getSize:", e);
}
- return is;
+ return imageSize;
}
/* returns a list of supported image formats */
@@ -118,44 +148,56 @@
return Arrays.asList(formats).iterator();
}
- /** Check image size and type and store in ImageFile f */
- public ImageFile identify(ImageFile imageFile) throws IOException {
+ /* Check image size and type and store in ImageInput */
+ public ImageInput identify(ImageInput input) throws IOException {
// try parent method first
- ImageFile imf = super.identify(imageFile);
- if (imf != null) {
- return imf;
- }
- // fileset to store the information
- ImageFileset imgfs = imageFile.getParent();
- File f = imageFile.getFile();
- if (f == null) {
- throw new IOException("File not found!");
+ ImageInput ii = super.identify(input);
+ if (ii != null) {
+ return ii;
}
- logger.debug("identifying (ImageIO) " + f);
- /*
- * try ImageReader
- */
- if ((reader == null) || (imgFile != imageFile.getFile())) {
- getReader(imageFile);
+ logger.debug("identifying (ImageIO) " + input);
+ ImageReader reader = null;
+ try {
+ /*
+ * try ImageReader
+ */
+ reader = getReader(input);
+ // set size
+ ImageSize d = new ImageSize(reader.getWidth(0), reader.getHeight(0));
+ input.setSize(d);
+ // set mime type
+ if (input.getMimetype() == null) {
+ if (input.hasFile()) {
+ String t = FileOps.mimeForFile(input.getFile());
+ input.setMimetype(t);
+ } else {
+ // FIXME: is format name a mime type???
+ String t = reader.getFormatName();
+ input.setMimetype(t);
+ }
+ }
+ return input;
+ } catch (FileOpException e) {
+ // maybe just our class doesn't know what to do
+ logger.error("ImageLoaderDocuimage unable to identify:", e);
+ return null;
+ } finally {
+ if (reader != null) {
+ reader.dispose();
+ }
}
- ImageSize d = new ImageSize(reader.getWidth(0), reader.getHeight(0));
- imageFile.setSize(d);
- // String t = reader.getFormatName();
- String t = FileOps.mimeForFile(f);
- imageFile.setMimetype(t);
- // logger.debug(" format:"+t);
- if (imgfs != null) {
- imgfs.setAspect(d);
- }
- return imageFile;
}
/* load image file */
- public void loadImage(ImageFile f) throws FileOpException {
- logger.debug("loadImage " + f.getFile());
+ public void loadImage(ImageInput ii) throws FileOpException {
+ logger.debug("loadImage: " + ii);
+ this.input = ii;
try {
- img = ImageIO.read(f.getFile());
- mimeType = f.getMimetype();
+ if (ii.hasImageInputStream()) {
+ img = ImageIO.read(ii.getImageInputStream());
+ } else if (ii.hasFile()) {
+ img = ImageIO.read(ii.getFile());
+ }
} catch (IOException e) {
throw new FileOpException("Error reading image.");
}
@@ -166,17 +208,28 @@
*
* @return
*/
- public ImageReader getReader(ImageFile f) throws IOException {
- logger.debug("preloadImage " + f.getFile());
- if (reader != null) {
- logger.debug("Reader was not null!");
- // clean up old reader
- dispose();
+ public ImageReader getReader(ImageInput input) throws IOException {
+ logger.debug("get ImageReader for " + input);
+ ImageInputStream istream = null;
+ if (input.hasImageInputStream()) {
+ // stream input
+ istream = input.getImageInputStream();
+ } else if (input.hasFile()) {
+ // file only input
+ RandomAccessFile rf = new RandomAccessFile(input.getFile(), "r");
+ istream = new FileImageInputStream(rf);
+ } else {
+ throw new FileOpException("Unable to get data from ImageInput");
}
- RandomAccessFile rf = new RandomAccessFile(f.getFile(), "r");
- ImageInputStream istream = new FileImageInputStream(rf);
Iterator