# HG changeset patch # User robcast # Date 1331417378 -3600 # Node ID 4e368c85cce45ab2e55c59c99dcf7a04ea064100 # Parent e077f52205a76e6a6a0a9b7752583d4fdd938050 CLOSED - # 22: wrong contrast setting. dito #23 (at least on OSX 10.7) mostly juggling color channels. also separate version number for DocuImage class. diff -r e077f52205a7 -r 4e368c85cce4 common/src/main/java/digilib/image/DocuImage.java --- a/common/src/main/java/digilib/image/DocuImage.java Fri Mar 09 20:47:06 2012 +0100 +++ b/common/src/main/java/digilib/image/DocuImage.java Sat Mar 10 23:09:38 2012 +0100 @@ -16,7 +16,7 @@ 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.image; @@ -25,13 +25,13 @@ import java.io.OutputStream; import java.util.Iterator; - import digilib.io.FileOpException; import digilib.io.ImageInput; import digilib.util.ImageSize; -/** The basic class for the representation of a digilib image. - * +/** + * The basic class for the representation of a digilib image. + * * The actual image object is hidden in the class, only methods for loading, * manipulation, and saving are exported. This strategy enables implementations * using different toolkits that rely on different image base classes (like @@ -39,210 +39,245 @@ */ public interface DocuImage { - /** Loads an image file into the Object. - * - * @param ii Image File. - * @throws FileOpException Exception thrown if any error occurs. - */ - public void loadImage(ImageInput ii) throws FileOpException; + /** + * Loads an image file into the Object. + * + * @param ii + * Image File. + * @throws FileOpException + * Exception thrown if any error occurs. + */ + public void loadImage(ImageInput ii) throws FileOpException; - /** This DocuImage supports the loadSubImage operation. - * - * @return boolean - */ - public boolean isSubimageSupported(); + /** + * This DocuImage supports the loadSubImage operation. + * + * @return boolean + */ + public boolean isSubimageSupported(); - /** Load only a subsampled region of the image file. - * - * @param ii - * @param region - * @param subsample - * @throws FileOpException - */ - public void loadSubimage(ImageInput ii, Rectangle region, int subsample) - throws FileOpException; + /** + * Load only a subsampled region of the image file. + * + * @param ii + * @param region + * @param subsample + * @throws FileOpException + */ + public void loadSubimage(ImageInput ii, Rectangle region, int subsample) throws FileOpException; - /** Writes the current image to an OutputStream. - * - * The image is encoded to the mime-type mt and sent to the output - * stream ostream. - * - * Currently only mime-types "image/jpeg" and "image/png" are supported. - * - * @param mt mime-type of the image to be sent. - * @param ostream OutputStream where the image is sent. - * @throws ImageOpException Exception in other cases. - * @throws FileOpException Exception on sending data - */ - public void writeImage(String mt, OutputStream ostream) - throws ImageOpException, FileOpException; + /** + * Writes the current image to an OutputStream. + * + * The image is encoded to the mime-type mt and sent to the + * output stream ostream. + * + * Currently only mime-types "image/jpeg" and "image/png" are supported. + * + * @param mt + * mime-type of the image to be sent. + * @param ostream + * OutputStream where the image is sent. + * @throws ImageOpException + * Exception in other cases. + * @throws FileOpException + * Exception on sending data + */ + public void writeImage(String mt, OutputStream ostream) throws ImageOpException, FileOpException; + + /** + * The width of the current image in pixel. + * + * @return Image width in pixels. + */ + public int getWidth(); - /** The width of the current image in pixel. - * - * @return Image width in pixels. - */ - public int getWidth(); + /** + * The height of the current image in pixel. + * + * @return Image height in pixels. + */ + public int getHeight(); - /** The height of the current image in pixel. - * - * @return Image height in pixels. - */ - public int getHeight(); - - /** The size of the current image in pixel. - * - * @return - */ - public ImageSize getSize(); + /** + * The size of the current image in pixel. + * + * @return + */ + public ImageSize getSize(); - /** 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. - */ - public String getMimetype(); + /** + * 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. + */ + public String getMimetype(); - /** Crops the current image. - * - * Cuts out a region of the size width x height at - * the offset xoff, yoff from the current image - * and replaces the current image with the result. - * - * @param xoff X offset of crop region - * @param yoff Y offset of crop region - * @param width width of crop region - * @param height height of crop region - * @throws ImageOpException - */ - public void crop(int xoff, int yoff, int width, int height) - throws ImageOpException; + /** + * Crops the current image. + * + * Cuts out a region of the size width x height at + * the offset xoff, yoff from the current image + * and replaces the current image with the result. + * + * @param xoff + * X offset of crop region + * @param yoff + * Y offset of crop region + * @param width + * width of crop region + * @param height + * height of crop region + * @throws ImageOpException + */ + public void crop(int xoff, int yoff, int width, int height) throws ImageOpException; - /** Scales the current image. - * - * Replaces the current image with an image scaled by the factor - * scale. - * - * @param scale scaling factor - * @throws ImageOpException - */ - public void scale(double scaleX, double scaleY) throws ImageOpException; + /** + * Scales the current image. + * + * Replaces the current image with an image scaled by the factor + * scale. + * + * @param scale + * scaling factor + * @throws ImageOpException + */ + public void scale(double scaleX, double scaleY) throws ImageOpException; - /** Crops and scales the current image. - * - * The current image is cropped to a rectangle of width, - * height at position x_off, y_off. The - * resulting image is scaled by the factor scale using the - * interpolation quality qual (0=worst). - * - * @param x_off x offset of the crop rectangle in pixel. - * @param y_off y offset of the crop rectangle in pixel. - * @param width width of the crop rectangle in pixel. - * @param height height of the crop rectangle in pixel. - * @param scale scaling factor. - * @param qual interpolation quality (0=worst). - * @throws ImageOpException exception thrown on any error. - */ - public void cropAndScale( - int x_off, - int y_off, - int width, - int height, - double scale, - int qual) - throws ImageOpException; + /** + * Crops and scales the current image. + * + * The current image is cropped to a rectangle of width, + * height at position x_off, y_off. + * The resulting image is scaled by the factor scale using the + * interpolation quality qual (0=worst). + * + * @param x_off + * x offset of the crop rectangle in pixel. + * @param y_off + * y offset of the crop rectangle in pixel. + * @param width + * width of the crop rectangle in pixel. + * @param height + * height of the crop rectangle in pixel. + * @param scale + * scaling factor. + * @param qual + * interpolation quality (0=worst). + * @throws ImageOpException + * exception thrown on any error. + */ + public void cropAndScale(int x_off, int y_off, int width, int height, 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 the 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; + /** + * Rotates the current image. + * + * Replaces the current image with a rotated image. The image is rotated + * around the center by the 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 - * through the center of the image and is rotated by angle - * degrees. Currently only horizontal and vertical mirroring (0 and 90 - * degree) are supported. - * - * @param angle angle of mirror axis - * @throws ImageOpException - */ - public void mirror(double angle) throws ImageOpException; + /** + * Mirrors the current image. + * + * Replaces the current image with a mirrored image. The mirror axis goes + * through the center of the image and is rotated by angle + * degrees. Currently only horizontal and vertical mirroring (0 and 90 + * degree) are supported. + * + * @param angle + * angle of mirror axis + * @throws ImageOpException + */ + public void mirror(double angle) throws ImageOpException; + + /** + * Enhances brightness and contrast of the current image. + * + * Replaces the current image with a brightness and contrast enhanced image. + * Contrast is enhanced by multiplying the pixel value with the constant + * mult. Brightness is enhanced by adding the constant + * add to the pixel value. Operation: p1 = (p0*mult)+add. + * + * @param mult + * multiplicative constant for contrast enhancement + * @param add + * additive constant for brightness enhancement + * @throws ImageOpException + */ + public void enhance(float mult, float add) throws ImageOpException; - /** Enhances brightness and contrast of the current image. - * - * Replaces the current image with a brightness and contrast enhanced image. - * Contrast is enhanced by multiplying the pixel value with the constant - * mult. Brightness is enhanced by adding the constant - * add to the pixel value. Operation: p1 = (p0*mult)+add. - * - * @param mult multiplicative constant for contrast enhancement - * @param add additive constant for brightness enhancement - * @throws ImageOpException - */ - public void enhance(float mult, float add) throws ImageOpException; + /** + * Manipulates the colors of the current image. + * + * Replaces the current image with a color modified image. For the red, + * green and blue color channels all pixel values are multiplied by the + * constant m and added to the constant a. + * Operation: p1 = (p0*m)+a. + * + * @param rgbm + * multiplicative constants for red, green, blue + * @param rgba + * additive constant for red, green, blue + * @throws ImageOpException + */ + public void enhanceRGB(float[] rgbm, float[] rgba) throws ImageOpException; - /** Manipulates the colors of the current image. - * - * Replaces the current image with a color modified image. - * For the red, green and blue color channels all pixel values are multiplied - * by the constant - * m and added to the constant - * a. Operation: p1 = (p0*m)+a. - * - * @param rgbm multiplicative constants for red, green, blue - * @param rgba additive constant for red, green, blue - * @throws ImageOpException - */ - public void enhanceRGB(float[] rgbm, float[] rgba) - throws ImageOpException; - + /** + * Operations for colorOps. + * + * GRAYSCALE: cast color image to grayscale NTSC_GRAY: convert color image + * to grayscale using NTSC formula INVERT: invert colors (every channel + * separately) MAP_GRAY_BGR: false color image from grayscale (0: blue, 128: + * green, 255: red) + * + */ + public enum ColorOp { + GRAYSCALE, NTSC_GRAY, INVERT, MAP_GRAY_BGR + }; - /** Operations for colorOps. - * - * GRAYSCALE: cast color image to grayscale - * NTSC_GRAY: convert color image to grayscale using NTSC formula - * INVERT: invert colors (every channel separately) - * MAP_GRAY_BGR: false color image from grayscale (0: blue, 128: green, 255: red) - * - */ - public enum ColorOp {GRAYSCALE, NTSC_GRAY, INVERT, MAP_GRAY_BGR}; + /** + * Changes the colors of the current image. + * + * Changes the colors of the current image. Operations are instances of + * ColorOp: + * + * GRAYSCALE: cast color image to grayscale NTSC_GRAY: convert color image + * to grayscale using NTSC formula INVERT: invert colors (every channel + * separately) MAP_GRAY_BGR: false color image from grayscale (0: blue, 128: + * green, 255: red) + * + * @throws ImageOpException + */ + public void colorOp(ColorOp op) throws ImageOpException; - /** Changes the colors of the current image. - * - * Changes the colors of the current image. Operations are instances of ColorOp: - * - * GRAYSCALE: cast color image to grayscale - * NTSC_GRAY: convert color image to grayscale using NTSC formula - * INVERT: invert colors (every channel separately) - * MAP_GRAY_BGR: false color image from grayscale (0: blue, 128: green, 255: red) - * - * @throws ImageOpException - */ - public void colorOp(ColorOp op) throws ImageOpException; + /** + * Returns the interpolation quality. + * + * @return int + */ + public int getQuality(); - /** - * Returns the interpolation quality. - * @return int - */ - public int getQuality(); + /** + * Sets the interpolation quality. + * + * @param quality + * The quality to set + */ + public void setQuality(int quality); - /** - * Sets the interpolation quality. - * @param quality The quality to set - */ - public void setQuality(int quality); - - /** Frees all resources bound to the DocuImage. - * - * Things that should be freed are image objects and open files. - * - */ - public void dispose(); + /** + * Frees all resources bound to the DocuImage. + * + * Things that should be freed are image objects and open files. + * + */ + public void dispose(); /** * Check image size and type and store in ImageInput ii @@ -252,12 +287,19 @@ /** * Returns a list of supported image formats */ - public Iterator getSupportedFormats(); - - /** - * returns the underlying image as java.awt.Image (if possible, or null) - * @return - */ - public java.awt.Image getAwtImage(); + public Iterator getSupportedFormats(); + + /** + * returns the underlying image as java.awt.Image (if possible, or null) + * + * @return + */ + public java.awt.Image getAwtImage(); + + /** + * returns the version of the DocuImage implementation. + * @return + */ + public String getVersion(); } diff -r e077f52205a7 -r 4e368c85cce4 common/src/main/java/digilib/image/DocuImageImpl.java --- a/common/src/main/java/digilib/image/DocuImageImpl.java Fri Mar 09 20:47:06 2012 +0100 +++ b/common/src/main/java/digilib/image/DocuImageImpl.java Sat Mar 10 23:09:38 2012 +0100 @@ -16,7 +16,7 @@ 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.image; @@ -28,88 +28,112 @@ import java.util.LinkedList; import java.util.List; - import org.apache.log4j.Logger; import digilib.io.FileOpException; import digilib.io.ImageInput; import digilib.util.ImageSize; -/** Simple abstract implementation of the DocuImage interface. - * +/** + * Simple abstract implementation of the DocuImage interface. + * * This implementation provides basic functionality for the utility methods like - * getKnownFileTypes. Image methods like - * loadImage, writeImage, getWidth, - * getHeight, crop and scale must be - * implemented by derived classes. + * getKnownFileTypes. Image methods like loadImage, + * writeImage, getWidth, getHeight, + * crop and scale must be implemented by derived + * classes. */ public abstract class DocuImageImpl implements DocuImage { - /** logger */ - protected static final Logger logger = Logger.getLogger(DocuImage.class); - - /** Interpolation quality. */ - protected int quality = 0; - - /** epsilon for float comparisons. */ - public static final double epsilon = 1e-5; + /** DocuImage version */ + public static final String version = "DocuImageImpl 2.1"; + + /** logger */ + protected static final Logger logger = Logger.getLogger(DocuImage.class); - /** image size */ + /** Interpolation quality. */ + protected int quality = 0; + + /** epsilon for float comparisons. */ + public static final double epsilon = 1e-5; + + /** image size */ protected ImageSize imgSize = null; /** ImageInput that was read */ protected ImageInput input; - /** - * Returns the quality. - * @return int - */ - public int getQuality() { - return quality; - } + /** + * Returns the version. + * @return the version + */ + public String getVersion() { + return version; + } - /** - * Sets the quality. - * @param quality The quality to set - */ - public void setQuality(int quality) { - this.quality = quality; - } + /** + * Returns the quality. + * + * @return int + */ + public int getQuality() { + return quality; + } + + /** + * Sets the quality. + * + * @param quality + * The quality to set + */ + public void setQuality(int quality) { + this.quality = quality; + } - /** Crop and scale the current image. - * - * The current image is cropped to a rectangle of width, height at position - * x_off, y_off. The resulting image is scaled by the factor scale using the - * interpolation quality qual (0=worst). - * - * @param x_off X offset of the crop rectangle in pixel. - * @param y_off Y offset of the crop rectangle in pixel. - * @param width Width of the crop rectangle in pixel. - * @param height Height of the crop rectangle in pixel. - * @param scale Scaling factor. - * @param qual Interpolation quality (0=worst). - * @throws ImageOpException Exception thrown on any error. - */ - public void cropAndScale( - int x_off, int y_off, int width, int height, double scale, int qual) - throws ImageOpException { - // default implementation: first crop, then scale - setQuality(qual); - crop(x_off, y_off, width, height); - scale(scale, scale); - } - - /* (non-Javadoc) - * @see digilib.image.DocuImage#getMimetype() - */ - public String getMimetype() { - if (input != null) { - return input.getMimetype(); - } - return null; - } + /** + * Crop and scale the current image. + * + * The current image is cropped to a rectangle of width, height at position + * x_off, y_off. The resulting image is scaled by the factor scale using the + * interpolation quality qual (0=worst). + * + * @param x_off + * X offset of the crop rectangle in pixel. + * @param y_off + * Y offset of the crop rectangle in pixel. + * @param width + * Width of the crop rectangle in pixel. + * @param height + * Height of the crop rectangle in pixel. + * @param scale + * Scaling factor. + * @param qual + * Interpolation quality (0=worst). + * @throws ImageOpException + * Exception thrown on any error. + */ + public void cropAndScale(int x_off, int y_off, int width, int height, double scale, int qual) throws ImageOpException { + // default implementation: first crop, then scale + setQuality(qual); + crop(x_off, y_off, width, height); + scale(scale, scale); + } - /* (non-Javadoc) + /* + * (non-Javadoc) + * + * @see digilib.image.DocuImage#getMimetype() + */ + public String getMimetype() { + if (input != null) { + return input.getMimetype(); + } + return null; + } + + /* + * (non-Javadoc) + * * @see digilib.image.DocuImage#identify(digilib.io.ImageFile) */ public ImageInput identify(ImageInput ii) throws IOException { @@ -117,48 +141,45 @@ return null; } - public void rotate(double angle) throws ImageOpException { - // just a do-nothing implementation - } + public void rotate(double angle) throws ImageOpException { + // just a do-nothing implementation + } - public void mirror(double angle) throws ImageOpException { - // just a do-nothing implementation - } + public void mirror(double angle) throws ImageOpException { + // just a do-nothing implementation + } - public void enhance(float mult, float add) throws ImageOpException { - // just a do-nothing implementation - } + public void enhance(float mult, float add) throws ImageOpException { + // just a do-nothing implementation + } - public boolean isSubimageSupported() { - // partial loading not supported per default - return false; - } + public boolean isSubimageSupported() { + // partial loading not supported per default + return false; + } - public void loadSubimage(ImageInput ii, Rectangle region, int subsample) - throws FileOpException { - // empty implementation - } + public void loadSubimage(ImageInput ii, Rectangle region, int subsample) throws FileOpException { + // empty implementation + } - public void enhanceRGB(float[] rgbm, float[] rgba) - throws ImageOpException { - // emtpy implementation - } + public void enhanceRGB(float[] rgbm, float[] rgba) throws ImageOpException { + // emtpy implementation + } - public void colorOp(ColorOp op) throws ImageOpException { - // emtpy implementation - } - - public void dispose() { - // emtpy implementation - } + public void colorOp(ColorOp op) throws ImageOpException { + // emtpy implementation + } - public Iterator getSupportedFormats() { - List empty = new LinkedList(); - return empty.iterator(); - } + public void dispose() { + // emtpy implementation + } - public void crop(int xoff, int yoff, int width, int height) - throws ImageOpException { + public Iterator getSupportedFormats() { + List empty = new LinkedList(); + return empty.iterator(); + } + + public void crop(int xoff, int yoff, int width, int height) throws ImageOpException { // emtpy implementation } @@ -191,8 +212,6 @@ public abstract void scale(double scaleX, double scaleY) throws ImageOpException; - public abstract void writeImage(String mt, OutputStream ostream) - throws ImageOpException, FileOpException; + public abstract void writeImage(String mt, OutputStream ostream) throws ImageOpException, FileOpException; - } diff -r e077f52205a7 -r 4e368c85cce4 common/src/main/java/digilib/image/ImageLoaderDocuImage.java --- a/common/src/main/java/digilib/image/ImageLoaderDocuImage.java Fri Mar 09 20:47:06 2012 +0100 +++ b/common/src/main/java/digilib/image/ImageLoaderDocuImage.java Sat Mar 10 23:09:38 2012 +0100 @@ -59,117 +59,125 @@ import digilib.io.ImageInput; import digilib.util.ImageSize; -/** Implementation of DocuImage using the ImageLoader API of Java 1.4 and Java2D. */ +/** + * Implementation of DocuImage using the ImageLoader API of Java 1.4 and Java2D. + */ public class ImageLoaderDocuImage extends ImageInfoDocuImage { + + /** DocuImage version */ + public static final String version = "ImageLoaderDocuImage 2.1.2"; - /** image object */ - protected BufferedImage img; - - /** the reader object */ - protected ImageReader reader = null; - + /** image object */ + protected BufferedImage img; + + /** the reader object */ + protected ImageReader reader = null; + /** try to reuse reader object */ public boolean reuseReader = false; - - /** interpolation type */ - protected RenderingHints renderHint = null; + + /** interpolation type */ + 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}) - }; + /** 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 }) }; - /* lookup tables for inverting images (byte) */ - protected static LookupTable invertSingleByteTable; + /* lookup tables for inverting images (byte) */ + protected static LookupTable invertSingleByteTable; protected static LookupTable invertRgbaByteTable; protected static boolean needsInvertRgba = false; - /* RescaleOp for contrast/brightness operation */ + /* RescaleOp for contrast/brightness operation */ protected static boolean needsRescaleRgba = false; /* lookup table for false-color */ protected static LookupTable mapBgrByteTable; protected static boolean needsMapBgr = false; - - static { - /* - * create static lookup tables - */ - byte[] invertByte = new byte[256]; - byte[] orderedByte = new byte[256]; - byte[] nullByte = new byte[256]; + + static { + /* + * create static lookup tables + */ + byte[] invertByte = new byte[256]; + byte[] orderedByte = new byte[256]; + byte[] nullByte = new byte[256]; byte[] mapR = new byte[256]; byte[] mapG = new byte[256]; byte[] mapB = new byte[256]; - for (int i = 0; i < 256; ++i) { - // counting down - invertByte[i] = (byte) (256 - i); - // counting up - orderedByte[i] = (byte) i; - // constant 0 - nullByte[i] = 0; - // three overlapping slopes - if (i < 64) { - mapR[i] = 0; - mapG[i] = (byte) (4 * i); - mapB[i] = (byte) 255; - } else if (i >= 64 && i < 192) { + for (int i = 0; i < 256; ++i) { + // counting down + invertByte[i] = (byte) (255 - i); + // counting up + orderedByte[i] = (byte) i; + // constant 0 + nullByte[i] = 0; + // three overlapping slopes + if (i < 64) { + mapR[i] = 0; + mapG[i] = (byte) (4 * i); + mapB[i] = (byte) 255; + } else if (i >= 64 && i < 192) { mapR[i] = (byte) (2 * (i - 64)); mapG[i] = (byte) 255; mapB[i] = (byte) (255 - 2 * (i - 64)); - } else { + } else { mapR[i] = (byte) 255; mapG[i] = (byte) (255 - (4 * (i - 192))); mapB[i] = 0; - } - } - // should(!) work for all color models - invertSingleByteTable = new ByteLookupTable(0, invertByte); - // but doesn't work with alpha channel on all platforms - String ver = System.getProperty("java.version"); - String os = System.getProperty("os.name"); - logger.debug("os="+os+" ver="+ver); - if (os.startsWith("Linux") && ver.startsWith("1.6")) { - // GRAB(WTF?) works in Linux JDK1.6 with transparency - invertRgbaByteTable = new ByteLookupTable(0, new byte[][] { - invertByte, invertByte, orderedByte, invertByte}); - needsInvertRgba = true; - needsRescaleRgba = true; - needsMapBgr = true; - } else { - invertRgbaByteTable = invertSingleByteTable; - } - // this hopefully works for all - mapBgrByteTable = new ByteLookupTable(0, new byte[][] { - mapR, mapG, mapB}); - } - - /** the size of the current image */ + } + } + // should(!) work for all color models + invertSingleByteTable = new ByteLookupTable(0, invertByte); + // but doesn't work with alpha channel on all platforms + String ver = System.getProperty("java.version"); + String os = System.getProperty("os.name"); + String osver = System.getProperty("os.version"); + logger.debug("os="+os+" ver="+osver+" java_version="+ver); + if ((os.startsWith("Linux")) || (os.startsWith("Mac OS X") && osver.startsWith("10.7"))) { + // GRAB(WTF?) works for Linux JDK1.6 with transparency + needsInvertRgba = true; + invertRgbaByteTable = new ByteLookupTable(0, new byte[][] { invertByte, invertByte, orderedByte, invertByte }); + needsRescaleRgba = true; + needsMapBgr = true; + } else { + invertRgbaByteTable = invertSingleByteTable; + } + // this hopefully works for all + mapBgrByteTable = new ByteLookupTable(0, new byte[][] { mapR, mapG, mapB }); + logger.debug("ImageIO Hacks: needsRescaleRgba="+needsRescaleRgba+" needsInvertRgba="+needsInvertRgba+ + " needsMapBgr="+needsMapBgr); + } + + /** the size of the current image */ protected ImageSize imageSize; - - - /* loadSubimage is supported. */ - public boolean isSubimageSupported() { - return true; - } + + /** + * @return the version + */ + public String getVersion() { + return version; + } + + /* loadSubimage is supported. */ + public boolean isSubimageSupported() { + return true; + } - public void setQuality(int qual) { - quality = qual; - renderHint = new RenderingHints(null); - // hint.put(RenderingHints.KEY_ANTIALIASING, - // RenderingHints.VALUE_ANTIALIAS_OFF); - // setup interpolation quality - if (qual > 0) { - logger.debug("quality q1"); - renderHint.put(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BICUBIC); - } else { - logger.debug("quality q0"); - renderHint.put(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); - } - } + public void setQuality(int qual) { + quality = qual; + renderHint = new RenderingHints(null); + // hint.put(RenderingHints.KEY_ANTIALIASING, + // RenderingHints.VALUE_ANTIALIAS_OFF); + // setup interpolation quality + if (qual > 0) { + logger.debug("quality q1"); + renderHint.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + } else { + logger.debug("quality q0"); + renderHint.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + } + } /* returns the size of the current image */ public ImageSize getSize() { @@ -195,11 +203,11 @@ return imageSize; } - /* returns a list of supported image formats */ - public Iterator getSupportedFormats() { - String[] formats = ImageIO.getReaderFormatNames(); - return Arrays.asList(formats).iterator(); - } + /* returns a list of supported image formats */ + public Iterator getSupportedFormats() { + String[] formats = ImageIO.getReaderFormatNames(); + return Arrays.asList(formats).iterator(); + } /* Check image size and type and store in ImageInput */ public ImageInput identify(ImageInput input) throws IOException { @@ -242,183 +250,182 @@ } } } - + /* load image file */ - public void loadImage(ImageInput ii) throws FileOpException { - logger.debug("loadImage: " + ii); - this.input = ii; - try { - if (ii.hasImageInputStream()) { + public void loadImage(ImageInput ii) throws FileOpException { + logger.debug("loadImage: " + ii); + this.input = ii; + try { + 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!", e); - } - if (img == null) { - throw new FileOpException("Unable to read image!"); - } - } + } else if (ii.hasFile()) { + img = ImageIO.read(ii.getFile()); + } + } catch (IOException e) { + throw new FileOpException("Error reading image!", e); + } + if (img == null) { + throw new FileOpException("Unable to read image!"); + } + } - /** - * Get an ImageReader for the image file. - * - * @return - */ - public ImageReader getReader(ImageInput input) throws IOException { - logger.debug("get ImageReader for " + input); - if (reuseReader && reader != null) { - logger.debug("reuseing ImageReader"); - return reader; - } - ImageInputStream istream = null; - if (input.hasImageInputStream()) { - // ImageInputStream 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"); - } - Iterator readers; - String mt = null; - if (input.hasMimetype()) { - // check hasMimetype first or we might get into a loop - mt = input.getMimetype(); - } else { - // try file extension + /** + * Get an ImageReader for the image file. + * + * @return + */ + public ImageReader getReader(ImageInput input) throws IOException { + logger.debug("get ImageReader for " + input); + if (reuseReader && reader != null) { + logger.debug("reuseing ImageReader"); + return reader; + } + ImageInputStream istream = null; + if (input.hasImageInputStream()) { + // ImageInputStream 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"); + } + Iterator readers; + String mt = null; + if (input.hasMimetype()) { + // check hasMimetype first or we might get into a loop + mt = input.getMimetype(); + } else { + // try file extension mt = FileOps.mimeForFile(input.getFile()); - } - if (mt == null) { - logger.debug("No mime-type. Trying automagic."); - readers = ImageIO.getImageReaders(istream); - } else { - logger.debug("File type:" + mt); - readers = ImageIO.getImageReadersByMIMEType(mt); - } - if (!readers.hasNext()) { - throw new FileOpException("Can't find Reader to load File!"); - } - ImageReader reader = readers.next(); - /* are there more readers? */ - logger.debug("ImageIO: this reader: " + reader.getClass()); - /* while (readers.hasNext()) { - logger.debug("ImageIO: next reader: " + readers.next().getClass()); - } */ - reader.setInput(istream); - return reader; - } + } + if (mt == null) { + logger.debug("No mime-type. Trying automagic."); + readers = ImageIO.getImageReaders(istream); + } else { + logger.debug("File type:" + mt); + readers = ImageIO.getImageReadersByMIMEType(mt); + } + if (!readers.hasNext()) { + throw new FileOpException("Can't find Reader to load File!"); + } + ImageReader reader = readers.next(); + /* are there more readers? */ + logger.debug("ImageIO: this reader: " + reader.getClass()); + /* + * while (readers.hasNext()) { logger.debug("ImageIO: next reader: " + + * readers.next().getClass()); } + */ + reader.setInput(istream); + return reader; + } /* Load an image file into the Object. */ - public void loadSubimage(ImageInput ii, Rectangle region, int prescale) - throws FileOpException { - logger.debug("loadSubimage"); + public void loadSubimage(ImageInput ii, Rectangle region, int prescale) throws FileOpException { + logger.debug("loadSubimage"); this.input = ii; - //ImageReader reader = null; - try { - reader = getReader(ii); - // set up reader parameters - ImageReadParam readParam = reader.getDefaultReadParam(); - readParam.setSourceRegion(region); - if (prescale > 1) { - readParam.setSourceSubsampling(prescale, prescale, 0, 0); - } - // try to restrict target color space to sRGB - for (Iterator i = reader.getImageTypes(0); i.hasNext(); ) { - ImageTypeSpecifier type = (ImageTypeSpecifier) i.next(); - ColorModel cm = type.getColorModel(); - ColorSpace cs = cm.getColorSpace(); - //logger.debug("loadSubimage: possible color model:"+cm+" color space:"+cs); - if (cs.isCS_sRGB()) { - logger.debug("loadSubimage: substituted sRGB destination type "+type); - readParam.setDestinationType(type); - //break; - } - } - // read image - logger.debug("loadSubimage: loading.."); - img = reader.read(0, readParam); - logger.debug("loadSubimage: loaded"); - // invalidate image size - imageSize = null; - // downconvert highcolor images - if (img.getColorModel().getComponentSize(0) > 8) { - logger.debug("loadSubimage: converting to 8bit"); - int type = BufferedImage.TYPE_INT_RGB; - if (img.getColorModel().hasAlpha()) { - type = BufferedImage.TYPE_INT_ARGB; - } - BufferedImage dest = new BufferedImage(img.getWidth(), img.getHeight(), type); - dest.createGraphics().drawImage(img, null, 0, 0); - img = dest; - } - } catch (IOException e) { - throw new FileOpException("Unable to load File!", e); - } finally { - if (!reuseReader && reader != null) { - reader.dispose(); - } - } - } + // ImageReader reader = null; + try { + reader = getReader(ii); + // set up reader parameters + ImageReadParam readParam = reader.getDefaultReadParam(); + readParam.setSourceRegion(region); + if (prescale > 1) { + readParam.setSourceSubsampling(prescale, prescale, 0, 0); + } + // try to restrict target color space to sRGB + for (Iterator i = reader.getImageTypes(0); i.hasNext();) { + ImageTypeSpecifier type = (ImageTypeSpecifier) i.next(); + ColorModel cm = type.getColorModel(); + ColorSpace cs = cm.getColorSpace(); + // logger.debug("loadSubimage: possible color model:"+cm+" color space:"+cs); + if (cs.isCS_sRGB()) { + logger.debug("loadSubimage: substituted sRGB destination type " + type); + readParam.setDestinationType(type); + // break; + } + } + // read image + logger.debug("loadSubimage: loading.."); + img = reader.read(0, readParam); + logger.debug("loadSubimage: loaded"); + // invalidate image size + imageSize = null; + // downconvert highcolor images + if (img.getColorModel().getComponentSize(0) > 8) { + logger.debug("loadSubimage: converting to 8bit"); + int type = BufferedImage.TYPE_INT_RGB; + if (img.getColorModel().hasAlpha()) { + type = BufferedImage.TYPE_INT_ARGB; + } + BufferedImage dest = new BufferedImage(img.getWidth(), img.getHeight(), type); + dest.createGraphics().drawImage(img, null, 0, 0); + img = dest; + } + } catch (IOException e) { + throw new FileOpException("Unable to load File!", e); + } finally { + if (!reuseReader && reader != null) { + reader.dispose(); + } + } + } - /* write image of type mt to Stream */ - public void writeImage(String mt, OutputStream ostream) - throws ImageOpException, FileOpException { - logger.debug("writeImage"); - // setup output - ImageWriter writer = null; - ImageOutputStream imgout = null; - try { - imgout = ImageIO.createImageOutputStream(ostream); - if (mt == "image/jpeg") { - /* - * JPEG doesn't do transparency so we have to convert any RGBA - * image to RGB or we the client will think its CMYK :-( *Java2D BUG* - */ - if (img.getColorModel().hasAlpha()) { - logger.debug("BARF: JPEG with transparency!!"); - BufferedImage rgbImg = new BufferedImage(img.getWidth(), - img.getHeight(), BufferedImage.TYPE_INT_RGB); - rgbImg.createGraphics().drawImage(img, null, 0, 0); - img = rgbImg; - } - writer = ImageIO.getImageWritersByFormatName("jpeg").next(); - if (writer == null) { - throw new ImageOpException("Unable to get JPEG writer"); - } - ImageWriteParam param = writer.getDefaultWriteParam(); - if (quality > 1) { - // change JPEG compression quality - param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); - param.setCompressionQuality(0.9f); - } - writer.setOutput(imgout); - // render output - logger.debug("writing JPEG"); - writer.write(null, new IIOImage(img, null, null), param); - } else if (mt == "image/png") { - // render output - writer = ImageIO.getImageWritersByFormatName("png").next(); - if (writer == null) { - throw new ImageOpException("Unable to get PNG writer"); - } - writer.setOutput(imgout); - logger.debug("writing PNG"); - writer.write(img); - } else { - // unknown mime type - throw new ImageOpException("Unknown mime type: " + mt); - } + /* write image of type mt to Stream */ + public void writeImage(String mt, OutputStream ostream) throws ImageOpException, FileOpException { + logger.debug("writeImage"); + // setup output + ImageWriter writer = null; + ImageOutputStream imgout = null; + try { + imgout = ImageIO.createImageOutputStream(ostream); + if (mt == "image/jpeg") { + /* + * JPEG doesn't do transparency so we have to convert any RGBA + * image to RGB or we the client will think its CMYK :-( *Java2D + * BUG* + */ + if (img.getColorModel().hasAlpha()) { + logger.debug("BARF: JPEG with transparency!!"); + BufferedImage rgbImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB); + rgbImg.createGraphics().drawImage(img, null, 0, 0); + img = rgbImg; + } + writer = ImageIO.getImageWritersByFormatName("jpeg").next(); + if (writer == null) { + throw new ImageOpException("Unable to get JPEG writer"); + } + ImageWriteParam param = writer.getDefaultWriteParam(); + if (quality > 1) { + // change JPEG compression quality + param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param.setCompressionQuality(0.9f); + } + writer.setOutput(imgout); + // render output + logger.debug("writing JPEG"); + writer.write(null, new IIOImage(img, null, null), param); + } else if (mt == "image/png") { + // render output + writer = ImageIO.getImageWritersByFormatName("png").next(); + if (writer == null) { + throw new ImageOpException("Unable to get PNG writer"); + } + writer.setOutput(imgout); + logger.debug("writing PNG"); + writer.write(img); + } else { + // unknown mime type + throw new ImageOpException("Unknown mime type: " + mt); + } - } catch (IOException e) { - logger.error("Error writing image:", e); - throw new FileOpException("Error writing image!", e); - } - // TODO: should we: finally { writer.dispose(); } - } + } catch (IOException e) { + logger.error("Error writing image:", e); + throw new FileOpException("Error writing image!", e); + } + // TODO: should we: finally { writer.dispose(); } + } public void scale(double scaleX, double scaleY) throws ImageOpException { logger.debug("scale: " + scaleX); @@ -428,24 +435,22 @@ blur(bl); } /* then scaled */ - AffineTransformOp scaleOp = new AffineTransformOp( - AffineTransform.getScaleInstance(scaleX, scaleY), renderHint); + AffineTransformOp scaleOp = new AffineTransformOp(AffineTransform.getScaleInstance(scaleX, scaleY), renderHint); img = scaleOp.filter(img, null); - logger.debug("scaled to " + img.getWidth() + "x" + img.getHeight() - + " img=" + img); + logger.debug("scaled to " + img.getWidth() + "x" + img.getHeight() + " img=" + img); // invalidate image size imageSize = null; } - public void blur(int radius) throws ImageOpException { - logger.debug("blur: " + radius); - // minimum radius is 2 - int klen = Math.max(radius, 2); - Kernel blur = null; - if (klen < convolutionKernels.length) { - // use precalculated Kernel + public void blur(int radius) throws ImageOpException { + logger.debug("blur: " + radius); + // minimum radius is 2 + int klen = Math.max(radius, 2); + Kernel blur = null; + if (klen < convolutionKernels.length) { + // use precalculated Kernel blur = convolutionKernels[klen]; - } else { + } else { // calculate our own kernel int ksize = klen * klen; // kernel is constant 1/k @@ -455,90 +460,86 @@ kern[i] = f; } blur = new Kernel(klen, klen, kern); - } - // blur with convolve operation - ConvolveOp blurOp = new ConvolveOp(blur, ConvolveOp.EDGE_NO_OP, - renderHint); - BufferedImage dest = null; + } + // blur with convolve operation + ConvolveOp blurOp = new ConvolveOp(blur, ConvolveOp.EDGE_NO_OP, renderHint); + BufferedImage dest = null; // blur needs explicit destination image type for 3BYTE_BGR *Java2D BUG* - if (img.getType() == BufferedImage.TYPE_3BYTE_BGR) { - logger.debug("blur: fixing destination image type"); - dest = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_3BYTE_BGR); - } - img = blurOp.filter(img, dest); - logger.debug("blurred: "+img); - } + if (img.getType() == BufferedImage.TYPE_3BYTE_BGR) { + logger.debug("blur: fixing destination image type"); + dest = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_3BYTE_BGR); + } + img = blurOp.filter(img, dest); + logger.debug("blurred: " + img); + } - public void crop(int x_off, int y_off, int width, int height) - throws ImageOpException { - // setup Crop - img = img.getSubimage(x_off, y_off, width, height); - logger.debug("CROP:" + img.getWidth() + "x" - + img.getHeight()); + public void crop(int x_off, int y_off, int width, int height) throws ImageOpException { + // setup Crop + img = img.getSubimage(x_off, y_off, width, height); + logger.debug("CROP:" + img.getWidth() + "x" + img.getHeight()); // invalidate image size imageSize = null; - } + } - public void rotate(double angle) throws ImageOpException { + public void rotate(double angle) throws ImageOpException { logger.debug("rotate: " + angle); - // setup rotation - double rangle = Math.toRadians(angle); - // center of rotation is center of image + // setup rotation + double rangle = Math.toRadians(angle); + // center of rotation is center of image double w = img.getWidth(); double h = img.getHeight(); - double x = (w / 2); - double y = (h / 2); + double x = (w / 2); + double y = (h / 2); AffineTransform trafo = AffineTransform.getRotateInstance(rangle, x, y); - AffineTransformOp rotOp = new AffineTransformOp(trafo, renderHint); + AffineTransformOp rotOp = new AffineTransformOp(trafo, renderHint); // rotate bounds to see how much of the image would be off screen - Rectangle2D rotbounds = rotOp.getBounds2D(img); - double xoff = rotbounds.getX(); - double yoff = rotbounds.getY(); - if (Math.abs(xoff) > epsilon || Math.abs(yoff) > epsilon) { - // move image back on screen - logger.debug("move rotation: xoff="+xoff+" yoff="+yoff); - trafo.preConcatenate(AffineTransform.getTranslateInstance(-xoff, -yoff)); - rotOp = new AffineTransformOp(trafo, renderHint); - } - // transform image - img = rotOp.filter(img, null); - logger.debug("rotated: "+img); + Rectangle2D rotbounds = rotOp.getBounds2D(img); + double xoff = rotbounds.getX(); + double yoff = rotbounds.getY(); + if (Math.abs(xoff) > epsilon || Math.abs(yoff) > epsilon) { + // move image back on screen + logger.debug("move rotation: xoff=" + xoff + " yoff=" + yoff); + trafo.preConcatenate(AffineTransform.getTranslateInstance(-xoff, -yoff)); + rotOp = new AffineTransformOp(trafo, renderHint); + } + // transform image + img = rotOp.filter(img, null); + logger.debug("rotated: " + img); // invalidate image size imageSize = null; - } + } - public void mirror(double angle) throws ImageOpException { + public void mirror(double angle) throws ImageOpException { logger.debug("mirror: " + angle); - // 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 = img.getWidth(); - } else if (Math.abs(angle - 90) < epsilon) { // 90 degree - my = -1; - ty = img.getHeight(); - } else if (Math.abs(angle - 180) < epsilon) { // 180 degree - mx = -1; - tx = img.getWidth(); - } else if (Math.abs(angle - 270) < epsilon) { // 270 degree - my = -1; - ty = img.getHeight(); - } else if (Math.abs(angle - 360) < epsilon) { // 360 degree - mx = -1; - tx = img.getWidth(); - } else { - logger.error("invalid mirror angle "+angle); - return; - } - AffineTransformOp mirOp = new AffineTransformOp(new AffineTransform(mx, - 0, 0, my, tx, ty), renderHint); - img = mirOp.filter(img, null); + // 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 = img.getWidth(); + } else if (Math.abs(angle - 90) < epsilon) { // 90 degree + my = -1; + ty = img.getHeight(); + } else if (Math.abs(angle - 180) < epsilon) { // 180 degree + mx = -1; + tx = img.getWidth(); + } else if (Math.abs(angle - 270) < epsilon) { // 270 degree + my = -1; + ty = img.getHeight(); + } else if (Math.abs(angle - 360) < epsilon) { // 360 degree + mx = -1; + tx = img.getWidth(); + } else { + logger.error("invalid mirror angle " + angle); + return; + } + AffineTransformOp mirOp = new AffineTransformOp(new AffineTransform(mx, 0, 0, my, tx, ty), renderHint); + img = mirOp.filter(img, null); // invalidate image size imageSize = null; - } + } public void enhance(float mult, float add) throws ImageOpException { RescaleOp op = null; @@ -567,21 +568,20 @@ } public void enhanceRGB(float[] rgbm, float[] rgba) throws ImageOpException { - logger.debug("enhanceRGB: rgbm="+rgbm+" rgba="+rgba); + logger.debug("enhanceRGB: rgbm=" + rgbm + " rgba=" + rgba); /* * The number of constants must match the number of bands in the image. * We do only 3 (RGB) bands. */ int ncol = img.getColorModel().getNumColorComponents(); if ((ncol != 3) || (rgbm.length != 3) || (rgba.length != 3)) { - logger.error("enhanceRGB: unknown number of color bands or coefficients (" - + ncol + ")"); + logger.error("enhanceRGB: unknown number of color bands or coefficients (" + ncol + ")"); return; } if (img.getColorModel().hasAlpha()) { // add constant for alpha - rgbm = new float[] {rgbm[0], rgbm[1], rgbm[2], 1}; - rgba = new float[] {rgba[0], rgba[1], rgba[2], 0}; + rgbm = new float[] { rgbm[0], rgbm[1], rgbm[2], 1 }; + rgba = new float[] { rgba[0], rgba[1], rgba[2], 0 }; } RescaleOp scaleOp = new RescaleOp(rgbm, rgba, renderHint); scaleOp.filter(img, img); @@ -605,8 +605,7 @@ logger.debug("Color op: not grayscaling"); return; } - ColorConvertOp op = new ColorConvertOp( - ColorSpace.getInstance(ColorSpace.CS_GRAY), renderHint); + ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), renderHint); // let filter create new image img = op.filter(img, null); } else if (colop == ColorOp.NTSC_GRAY) { @@ -615,7 +614,7 @@ * 0.5870*green + 0.1140*blue */ logger.debug("Color op: NTSC gray"); - logger.debug("img="+img); + logger.debug("img=" + img); ColorModel cm = img.getColorModel(); if (cm.getNumColorComponents() < 3 || cm instanceof IndexColorModel) { // grayscale already or not possible @@ -627,8 +626,7 @@ BandCombineOp op = new BandCombineOp(combineFn, renderHint); // BandCombineOp only works on Rasters so we create a // new image and use its Raster - BufferedImage dest = new BufferedImage(img.getWidth(), - img.getHeight(), BufferedImage.TYPE_BYTE_GRAY); + BufferedImage dest = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_GRAY); op.filter(img.getRaster(), dest.getRaster()); img = dest; } else if (colop == ColorOp.INVERT) { @@ -659,16 +657,18 @@ */ logger.debug("Color op: map_gray_bgr"); // convert to grayscale - ColorConvertOp grayOp = new ColorConvertOp( - ColorSpace.getInstance(ColorSpace.CS_GRAY), renderHint); + ColorConvertOp grayOp = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), renderHint); // create new 3-channel image int destType = BufferedImage.TYPE_INT_RGB; if (needsMapBgr) { - // special case for broken Java2Ds - destType = BufferedImage.TYPE_3BYTE_BGR; + // special case for funny Java2D implementations + if (img.getColorModel().hasAlpha()) { + destType = BufferedImage.TYPE_4BYTE_ABGR_PRE; + } else { + destType = BufferedImage.TYPE_3BYTE_BGR; + } } - BufferedImage dest = new BufferedImage(img.getWidth(), - img.getHeight(), destType); + BufferedImage dest = new BufferedImage(img.getWidth(), img.getHeight(), destType); img = grayOp.filter(img, dest); logger.debug("map_gray: image=" + img); // convert to false color @@ -678,17 +678,16 @@ } } - public void dispose() { - if (reader != null) { - reader.dispose(); - } - // is this necessary? - img = null; - } + public void dispose() { + if (reader != null) { + reader.dispose(); + } + // is this necessary? + img = null; + } - public Image getAwtImage(){ - return (Image) img; - } - - + public Image getAwtImage() { + return (Image) img; + } + } diff -r e077f52205a7 -r 4e368c85cce4 servlet2/src/main/java/digilib/servlet/DigilibServletConfiguration.java --- a/servlet2/src/main/java/digilib/servlet/DigilibServletConfiguration.java Fri Mar 09 20:47:06 2012 +0100 +++ b/servlet2/src/main/java/digilib/servlet/DigilibServletConfiguration.java Sat Mar 10 23:09:38 2012 +0100 @@ -72,6 +72,9 @@ digilib.image.ImageLoaderDocuImage.class, null, 's'); + // DocuImage version + newParameter("servlet.docuimage.version", + "?", null, 's'); // AuthOps instance for authentication newParameter("servlet.auth.op", null, null, 's'); // Executor for image operations @@ -235,6 +238,7 @@ // initialise static DocuImage class instance DigilibServletConfiguration.docuImageClass = (Class) Class .forName(getAsString("docuimage-class")); + setValue("servlet.docuimage.version", getDocuImageInstance().getVersion()); } } diff -r e077f52205a7 -r 4e368c85cce4 servlet2/src/main/java/digilib/servlet/Scaler.java --- a/servlet2/src/main/java/digilib/servlet/Scaler.java Fri Mar 09 20:47:06 2012 +0100 +++ b/servlet2/src/main/java/digilib/servlet/Scaler.java Sat Mar 10 23:09:38 2012 +0100 @@ -34,7 +34,7 @@ private static final long serialVersionUID = -5439198888139362735L; /** digilib servlet version (for all components) */ - public static final String version = "2.1b1 noasync"; + public static final String version = "2.1b2 noasync"; /** servlet error codes */ public static enum Error {UNKNOWN, AUTH, FILE, IMAGE}; @@ -104,6 +104,8 @@ // no Configuration throw new ServletException("No Configuration!"); } + // log DocuImage version + logger.info("Scaler uses " + dlConfig.getValue("servlet.docuimage.version")); // set our AuthOps useAuthorization = dlConfig.getAsBoolean("use-authorization"); authOp = (AuthOps) dlConfig.getValue("servlet.auth.op"); diff -r e077f52205a7 -r 4e368c85cce4 servlet3/src/main/java/digilib/servlet/DigilibServletConfiguration.java --- a/servlet3/src/main/java/digilib/servlet/DigilibServletConfiguration.java Fri Mar 09 20:47:06 2012 +0100 +++ b/servlet3/src/main/java/digilib/servlet/DigilibServletConfiguration.java Sat Mar 10 23:09:38 2012 +0100 @@ -79,6 +79,9 @@ // DocuImage class instance newParameter("servlet.docuimage.class", digilib.image.ImageLoaderDocuImage.class, null, 's'); + // DocuImage version + newParameter("servlet.docuimage.version", + "?", null, 's'); // AuthOps instance for authentication newParameter("servlet.auth.op", null, null, 's'); // Executor for image operations @@ -226,13 +229,13 @@ } } else { // parameter unknown -- just add - newParameter(confEntry.getKey(), null, confEntry.getValue(), - 'f'); + newParameter(confEntry.getKey(), null, confEntry.getValue(), 'f'); } } // initialise static DocuImage class instance DigilibServletConfiguration.docuImageClass = (Class) Class .forName(getAsString("docuimage-class")); + setValue("servlet.docuimage.version", getDocuImageInstance().getVersion()); } } diff -r e077f52205a7 -r 4e368c85cce4 servlet3/src/main/java/digilib/servlet/Scaler.java --- a/servlet3/src/main/java/digilib/servlet/Scaler.java Fri Mar 09 20:47:06 2012 +0100 +++ b/servlet3/src/main/java/digilib/servlet/Scaler.java Sat Mar 10 23:09:38 2012 +0100 @@ -31,7 +31,7 @@ private static final long serialVersionUID = 5289386646192471549L; /** digilib servlet version (for all components) */ - public static final String version = "2.1b1 async"; + public static final String version = "2.1b2 async"; /** servlet error codes */ public static enum Error { @@ -108,6 +108,8 @@ // no Configuration throw new ServletException("No Configuration!"); } + // log DocuImage version + logger.info("Scaler uses " + dlConfig.getValue("servlet.docuimage.version")); // set our AuthOps useAuthorization = dlConfig.getAsBoolean("use-authorization"); authOp = (AuthOps) dlConfig.getValue("servlet.auth.op");