[med-svn] r12569 - in trunk/packages/bio-formats/trunk/debian: . patches

Mathieu Malaterre malat at alioth.debian.org
Sat Nov 24 19:44:26 UTC 2012


Author: malat
Date: 2012-11-24 19:44:25 +0000 (Sat, 24 Nov 2012)
New Revision: 12569

Removed:
   trunk/packages/bio-formats/trunk/debian/patches/bioformats-codeclib-removal.patch
Modified:
   trunk/packages/bio-formats/trunk/debian/changelog
   trunk/packages/bio-formats/trunk/debian/orig-tar.sh
   trunk/packages/bio-formats/trunk/debian/patches/remove_git.patch
   trunk/packages/bio-formats/trunk/debian/patches/series
   trunk/packages/bio-formats/trunk/debian/rules
   trunk/packages/bio-formats/trunk/debian/watch
Log:
Work on 4.4.5

Modified: trunk/packages/bio-formats/trunk/debian/changelog
===================================================================
--- trunk/packages/bio-formats/trunk/debian/changelog	2012-11-24 16:56:30 UTC (rev 12568)
+++ trunk/packages/bio-formats/trunk/debian/changelog	2012-11-24 19:44:25 UTC (rev 12569)
@@ -1,4 +1,4 @@
-bio-formats (4.4.2-1) UNRELEASED; urgency=low
+bio-formats (4.4.5-1) UNRELEASED; urgency=low
 
   * Initial Debian Upload (Closes: #641448)
 

Modified: trunk/packages/bio-formats/trunk/debian/orig-tar.sh
===================================================================
--- trunk/packages/bio-formats/trunk/debian/orig-tar.sh	2012-11-24 16:56:30 UTC (rev 12568)
+++ trunk/packages/bio-formats/trunk/debian/orig-tar.sh	2012-11-24 19:44:25 UTC (rev 12569)
@@ -2,16 +2,15 @@
 
 # called by uscan with '--upstream-version' <version> <file>
 TAR=../bio-formats_$2.orig.tar.gz
-DIR=bio-formats-$2
+DIR=bioformats-$2
 
 # clean up the upstream tarball
 tar -zxf $3
-mv openmicroscopy-bioformats-* $DIR
 # remaining *.jar
 find $DIR -name *.jar -delete
 find $DIR -name *.dll -delete
 tar -czf $TAR $DIR
-rm -rf $DIR $3
+rm -rf $DIR
 
 # move to directory 'tarballs'
 if [ -r .svn/deb-layout ]; then

Deleted: trunk/packages/bio-formats/trunk/debian/patches/bioformats-codeclib-removal.patch
===================================================================
--- trunk/packages/bio-formats/trunk/debian/patches/bioformats-codeclib-removal.patch	2012-11-24 16:56:30 UTC (rev 12568)
+++ trunk/packages/bio-formats/trunk/debian/patches/bioformats-codeclib-removal.patch	2012-11-24 19:44:25 UTC (rev 12569)
@@ -1,14813 +0,0 @@
-Index: bio-formats-4.4.2/ant/toplevel.properties
-===================================================================
---- bio-formats-4.4.2.orig/ant/toplevel.properties	2012-08-22 20:24:05.000000000 +0000
-+++ bio-formats-4.4.2/ant/toplevel.properties	2012-09-20 08:16:06.712187619 +0000
-@@ -8,8 +8,7 @@
- 
- ### Javadoc generation ###
- 
--merged-docs.classpath = ${lib.dir}/clibwrapper_jiio.jar:\
--                        ${lib.dir}/forms-1.3.0.jar:\
-+merged-docs.classpath = ${lib.dir}/forms-1.3.0.jar:\
-                         ${lib.dir}/ij.jar:\
-                         ${lib.dir}/log4j-1.2.15.jar:\
-                         ${lib.dir}/netcdf-4.0.jar:\
-@@ -43,7 +42,6 @@
- loci-tools.main      = loci.formats.gui.ImageViewer
- loci-tools.dir       = loci-tools
- loci-tools.libraries = bio-formats.jar \
--                       clibwrapper_jiio.jar \
-                        forms-1.3.0.jar \
-                        jai_imageio.jar \
-                        loci-common.jar \
-Index: bio-formats-4.4.2/build.xml
-===================================================================
---- bio-formats-4.4.2.orig/build.xml	2012-08-22 20:24:05.000000000 +0000
-+++ bio-formats-4.4.2/build.xml	2012-09-20 08:16:06.712187619 +0000
-@@ -215,13 +215,6 @@
-     Notes:     used by LOCI plugins for ImageJ and OME plugins for ImageJ
-     License:   Public domain
- 
--JAI ImageIO wrapper
--    JAR file:  clibwrapper_jiio.jar
--    URL:       https://jai-imageio.dev.java.net/
--    Notes:     used by Bio-Formats via reflection for JPEG2000 support (ND2,
--               JP2) and lossless JPEG decompression (DICOM)
--    License:   BSD
--
- JUnit
-     JAR file:  junit-4.8.2.jar
-     URL:       http://www.junit.org/
-Index: bio-formats-4.4.2/components/forks/jai/build.properties
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/build.properties	2012-08-22 20:24:05.000000000 +0000
-+++ bio-formats-4.4.2/components/forks/jai/build.properties	2012-09-20 08:16:06.712187619 +0000
-@@ -9,7 +9,7 @@
- component.name           = jai_imageio
- component.jar            = jai_imageio.jar
- component.version        = 1.0.0
--component.classpath      = ${lib.dir}/clibwrapper_jiio.jar
-+component.classpath      =
- component.java-version   = 1.4
- component.deprecation    = false
- 
-Index: bio-formats-4.4.2/components/forks/jai/pom.xml
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/pom.xml	2012-08-22 20:24:05.000000000 +0000
-+++ bio-formats-4.4.2/components/forks/jai/pom.xml	2012-09-20 08:16:06.712187619 +0000
-@@ -27,14 +27,6 @@
-     </license>
-   </licenses>
- 
--  <dependencies>
--    <dependency>
--      <groupId>com.sun</groupId>
--      <artifactId>clibwrapper_jiio</artifactId>
--      <version>1.1</version>
--    </dependency>
--  </dependencies>
--
-   <build>
-     <plugins>
-       <plugin>
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/common/PackageUtil.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/common/PackageUtil.java	2012-08-22 20:24:05.000000000 +0000
-+++ bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/common/PackageUtil.java	2012-09-20 08:16:06.716187619 +0000
-@@ -82,15 +82,9 @@
- 
- import java.security.AccessController;
- import java.security.PrivilegedAction;
--import com.sun.medialib.codec.jiio.Util;
- 
- public class PackageUtil {
-     /**
--     * Flag indicating whether codecLib is available.
--     */
--    private static boolean isCodecLibAvailable = false;
--
--    /**
-      * Implementation version derived from Manifest.
-      */
-     private static String version = "1.0";
-@@ -109,16 +103,6 @@
-      * Set static flags.
-      */
-     static {
--        // Set codecLib flag.
--        try {
--            // Check for codecLib availability.
--            isCodecLibAvailable = Util.isCodecLibAvailable();
--        } catch(Throwable e) {
--            // A Throwable is equivalent to unavailable. Throwable is used
--            // in case an Error rather than an Exception is thrown.
--            isCodecLibAvailable = false;
--        }
--
-         // Set version and vendor strings.
-         try {
-             Class thisClass =
-@@ -136,32 +120,6 @@
-     }
- 
-     /**
--     * Returns a <code>boolean</code> indicating whether codecLib is available.
--     */
--    public static final boolean isCodecLibAvailable() {
--        // Retrieve value of system property here to allow this to be
--        // modified dynamically.
--        Boolean result = (Boolean)
--            AccessController.doPrivileged(new PrivilegedAction() {
--                    public Object run() {
--                        String property = null;
--                        try {
--                            property =
--                                System.getProperty("com.sun.media.imageio.disableCodecLib");
--                        } catch(SecurityException se) {
--                            // Do nothing: leave 'property' null.
--                        }
--                        return (property != null &&
--                                property.equalsIgnoreCase("true")) ?
--                            Boolean.TRUE : Boolean.FALSE;
--                    }
--                });
--        boolean isCodecLibDisabled = result.booleanValue();
--
--        return isCodecLibAvailable && !isCodecLibDisabled;
--    }
--
--    /**
-      * Return a version string for the package.
-      */
-     public static final String getVersion() {
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/clib/CLibImageReader.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/clib/CLibImageReader.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,802 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibImageReader.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.11 $
-- * $Date: 2006/02/28 01:33:31 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.clib;
--
--import java.awt.Point;
--import java.awt.Rectangle;
--import java.awt.Transparency;
--import java.awt.color.ColorSpace;
--import java.awt.geom.AffineTransform;
--import java.awt.image.AffineTransformOp;
--import java.awt.image.BufferedImage;
--import java.awt.image.ColorModel;
--import java.awt.image.ComponentColorModel;
--import java.awt.image.ComponentSampleModel;
--import java.awt.image.DataBuffer;
--import java.awt.image.DataBufferByte;
--import java.awt.image.DataBufferUShort;
--import java.awt.image.IndexColorModel;
--import java.awt.image.MultiPixelPackedSampleModel;
--import java.awt.image.PixelInterleavedSampleModel;
--import java.awt.image.Raster;
--import java.awt.image.SampleModel;
--import java.awt.image.WritableRaster;
--import java.io.InputStream;
--import java.io.IOException;
--import java.util.ArrayList;
--import java.util.Iterator;
--import java.util.NoSuchElementException;
--import javax.imageio.IIOException;
--import javax.imageio.ImageReader;
--import javax.imageio.ImageReadParam;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.metadata.IIOMetadata;
--import javax.imageio.spi.ImageReaderSpi;
--import javax.imageio.stream.ImageInputStream;
--import com.sun.medialib.codec.jiio.Constants;
--import com.sun.medialib.codec.jiio.mediaLibImage;
--
--// XXX Need to verify compliance of all methods with ImageReader specificaiton.
--public abstract class CLibImageReader extends ImageReader {
--    // The current image index.
--    private int currIndex = -1;
--
--    // The position of the byte after the last byte read so far.
--    private long highWaterMark = Long.MIN_VALUE;
--
--    // An <code>ArrayList</code> of <code>Long</code>s indicating the stream
--    // positions of the start of each image. Entries are added as needed.
--    private ArrayList imageStartPosition = new ArrayList();
--
--    // The number of images in the stream, if known, otherwise -1.
--    private int numImages = -1;
--
--    // The image returned by the codecLib Decoder.
--    private mediaLibImage mlibImage = null;
--
--    // The index of the cached image.
--    private int mlibImageIndex = -1;
--
--    /**
--     * Returns true if and only if both arguments are null or
--     * both are non-null and have the same length and content.
--     */
--    private static boolean subBandsMatch(int[] sourceBands,
--                                         int[] destinationBands) {
--        if(sourceBands == null && destinationBands == null) {
--            return true;
--        } else if(sourceBands != null && destinationBands != null) {
--            if (sourceBands.length != destinationBands.length) {
--                // Shouldn't happen ...
--                return false;
--            }
--            for (int i = 0; i < sourceBands.length; i++) {
--                if (sourceBands[i] != destinationBands[i]) {
--                    return false;
--                }
--            }
--            return true;
--        }
--
--        return false;
--    }
--
--    /**
--     * Creates a <code>ImageTypeSpecifier</code> corresponding to a
--     * <code>mediaLibImage</code>.  The <code>mediaLibImage</code> is
--     * assumed always to be either bilevel-packed (MLIB_BIT) or
--     * pixel interleaved in the order ((G|I)|RGB)[A] where 'I' indicates
--     * an index as for palette images.
--     */
--    protected static final ImageTypeSpecifier
--        createImageType(mediaLibImage mlImage,
--                        ColorSpace colorSpace,
--                        int bitDepth,
--                        byte[] redPalette,
--                        byte[] greenPalette,
--                        byte[] bluePalette,
--                        byte[] alphaPalette) throws IOException {
--
--        // Get the mediaLibImage attributes.
--        int mlibType = mlImage.getType();
--        int mlibWidth = mlImage.getWidth();
--        int mlibHeight = mlImage.getHeight();
--        int mlibBands = mlImage.getChannels();
--        int mlibStride = mlImage.getStride();
--
--        // Convert mediaLib type to Java2D type.
--        int dataType;
--        switch(mlibType) {
--        case Constants.MLIB_BIT:
--        case Constants.MLIB_BYTE:
--            dataType = DataBuffer.TYPE_BYTE;
--            break;
--        case Constants.MLIB_SHORT:
--        case Constants.MLIB_USHORT:
--            // Deliberately cast MLIB_SHORT to TYPE_USHORT.
--            dataType = DataBuffer.TYPE_USHORT;
--            break;
--        default:
--            throw new UnsupportedOperationException
--                (I18N.getString("Generic0")+" "+mlibType);
--        }
--
--        // Set up the SampleModel.
--        SampleModel sampleModel = null;
--        if(mlibType == Constants.MLIB_BIT) {
--            // Bilevel-packed
--            sampleModel =
--                new MultiPixelPackedSampleModel(dataType,
--                                                mlibWidth,
--                                                mlibHeight,
--                                                1,
--                                                mlibStride,
--                                                mlImage.getBitOffset());
--        } else {
--            // Otherwise has to be interleaved in the order ((G|I)|RGB)[A].
--            int[] bandOffsets = new int[mlibBands];
--            for(int i = 0; i < mlibBands; i++) {
--                bandOffsets[i] = i;
--            }
--
--            sampleModel =
--                new PixelInterleavedSampleModel(dataType,
--                                                mlibWidth,
--                                                mlibHeight,
--                                                mlibBands,
--                                                mlibStride,
--                                                bandOffsets);
--        }
--
--        // Set up the ColorModel.
--        ColorModel colorModel = null;
--        if(mlibBands == 1 &&
--           redPalette   != null &&
--           greenPalette != null &&
--           bluePalette  != null &&
--           redPalette.length == greenPalette.length &&
--           redPalette.length == bluePalette.length) {
--
--            // Indexed image.
--            int paletteLength = redPalette.length;
--            if(alphaPalette != null) {
--                if(alphaPalette.length != paletteLength) {
--                    byte[] alphaTmp = new byte[paletteLength];
--                    if(alphaPalette.length > paletteLength) {
--                        System.arraycopy(alphaPalette, 0,
--                                         alphaTmp, 0, paletteLength);
--                    } else { // alphaPalette.length < paletteLength
--                        System.arraycopy(alphaPalette, 0,
--                                         alphaTmp, 0, alphaPalette.length);
--                        for(int i = alphaPalette.length; i < paletteLength; i++) {
--                            alphaTmp[i] = (byte)255; // Opaque.
--                        }
--                    }
--                    alphaPalette = alphaTmp;
--                }
--
--                colorModel = new IndexColorModel(bitDepth, //XXX 8
--                                                 paletteLength,
--                                                 redPalette,
--                                                 greenPalette,
--                                                 bluePalette,
--                                                 alphaPalette);
--            } else {
--                colorModel = new IndexColorModel(bitDepth, //XXX 8
--                                                 paletteLength,
--                                                 redPalette,
--                                                 greenPalette,
--                                                 bluePalette);
--            }
--        } else if(mlibType == Constants.MLIB_BIT) {
--            // Bilevel image with no palette: assume black-is-zero.
--            byte[] cmap = new byte[] { (byte)0x00, (byte)0xFF };
--            colorModel = new IndexColorModel(1, 2, cmap, cmap, cmap);
--        } else {
--            // Set the color space and the alpha flag.
--            ColorSpace cs;
--            boolean hasAlpha;
--            if(colorSpace != null &&
--               (colorSpace.getNumComponents() == mlibBands ||
--                colorSpace.getNumComponents() == mlibBands - 1)) {
--                // Use the provided ColorSpace.
--                cs = colorSpace;
--
--                // Set alpha if numBands == numColorComponents + 1.
--                hasAlpha = colorSpace.getNumComponents() != mlibBands;
--            } else {
--                // RGB if more than 2 bands.
--                cs = ColorSpace.getInstance(mlibBands < 3 ?
--                                            ColorSpace.CS_GRAY :
--                                            ColorSpace.CS_sRGB);
--
--                // Alpha if band count is even.
--                hasAlpha = mlibBands % 2 == 0;
--            }
--
--            // All bands have same depth.
--            int[] bits = new int[mlibBands];
--            for(int i = 0; i < mlibBands; i++) {
--                bits[i] = bitDepth;
--            }
--
--            colorModel =
--                new ComponentColorModel(cs,
--                                        bits,
--                                        hasAlpha,
--                                        false,
--                                        hasAlpha ?
--                                        Transparency.TRANSLUCENT :
--                                        Transparency.OPAQUE,
--                                        dataType);
--        }
--
--        return new ImageTypeSpecifier(colorModel, sampleModel);
--    }
--
--    private static final void subsample(Raster src, int subX, int subY,
--                                        WritableRaster dst) {
--        int sx0 = src.getMinX();
--        int sy0 = src.getMinY();
--        int sw = src.getWidth();
--        int syUB = sy0 + src.getHeight();
--
--        int dx0 = dst.getMinX();
--        int dy0 = dst.getMinY();
--        int dw = dst.getWidth();
--
--        int b = src.getSampleModel().getNumBands();
--        int t = src.getSampleModel().getDataType();
--
--        int numSubSamples = (sw + subX - 1)/subX;
--
--        if(t == DataBuffer.TYPE_FLOAT || t == DataBuffer.TYPE_DOUBLE) {
--            float[] fsamples = new float[sw];
--            float[] fsubsamples = new float[numSubSamples];
--
--            for(int k = 0; k < b; k++) {
--                for(int sy = sy0, dy = dy0; sy < syUB; sy += subY, dy++) {
--                    src.getSamples(sx0, sy, sw, 1, k, fsamples);
--                    for(int i = 0, s = 0; i < sw; s++, i += subX) {
--                        fsubsamples[s] = fsamples[i];
--                    }
--                    dst.setSamples(dx0, dy, dw, 1, k, fsubsamples);
--                }
--            }
--        } else {
--            int[] samples = new int[sw];
--            int[] subsamples = new int[numSubSamples];
--
--            for(int k = 0; k < b; k++) {
--                for(int sy = sy0, dy = dy0; sy < syUB; sy += subY, dy++) {
--                    src.getSamples(sx0, sy, sw, 1, k, samples);
--                    for(int i = 0, s = 0; i < sw; s++, i += subX) {
--                        subsamples[s] = samples[i];
--                    }
--                    dst.setSamples(dx0, dy, dw, 1, k, subsamples);
--                }
--            }
--        }
--    }                                 
--
--    protected CLibImageReader(ImageReaderSpi originatingProvider) {
--        super(originatingProvider);
--    }
--
--    /**
--     * An <code>Iterator</code> over a single element.
--     */
--    private class SoloIterator implements Iterator {
--        Object theObject;
--
--        SoloIterator(Object o) {
--            if(o == null) {
--                new IllegalArgumentException
--                    (I18N.getString("CLibImageReader0"));
--            }
--            theObject = o;
--        }
--
--        public boolean hasNext() {
--            return theObject != null;
--        }
--
--        public Object next() {
--            if(theObject == null) {
--                throw new NoSuchElementException();
--            }
--            Object theNextObject = theObject;
--            theObject = null;
--            return theNextObject;
--        }
--
--        public void remove() {
--            throw new UnsupportedOperationException();
--        }
--    }
--
--    // Stores the location of the image at the specified index in the
--    // imageStartPosition List.
--    private int locateImage(int imageIndex) throws IIOException {
--        if (imageIndex < 0) {
--            throw new IndexOutOfBoundsException("imageIndex < 0!");
--        }
--
--        try {
--            // Find closest known index (which can be -1 if none read before).
--            int index = Math.min(imageIndex, imageStartPosition.size() - 1);
--
--            ImageInputStream stream = (ImageInputStream)input;
--
--            // Seek unless at beginning of stream 
--            if(index >= 0) { // index == -1
--                if(index == imageIndex) {
--                    // Seek to previously identified position and return.
--                    Long l = (Long)imageStartPosition.get(index);
--                    stream.seek(l.longValue());
--                    return imageIndex;
--                } else if(highWaterMark >= 0) {
--                    // index >= imageStartPosition.size()
--                    // Seek to first unread byte.
--                    stream.seek(highWaterMark);
--                }
--            }
--
--            // Get the reader SPI.
--            ImageReaderSpi provider = getOriginatingProvider();
--
--            // Search images until at desired index or last image found.
--            do {
--                try {
--                    if(provider.canDecodeInput(stream)) {
--                        // Append the image position.
--                        long offset = stream.getStreamPosition();
--                        imageStartPosition.add(new Long(offset));
--                    } else {
--                        return index;
--                    }
--                } catch(IOException e) {
--                    // Ignore it.
--                    return index;
--                } 
--
--                // Incrememt the index.
--                if(++index == imageIndex) break;
--
--                // Skip the image.
--                if(!skipImage()) return index - 1;
--            } while(true);
--        } catch (IOException e) {
--            throw new IIOException("IOException", e);
--        }
--
--        currIndex = imageIndex;
--
--        return imageIndex;
--    }
--
--    // Verify that imageIndex is in bounds and find the image position.
--    protected void seekToImage(int imageIndex) throws IIOException {
--        // Check lower bound.
--        if (imageIndex < minIndex) {
--            throw new IndexOutOfBoundsException("imageIndex < minIndex!");
--        }
--
--        // Update lower bound if cannot seek back.
--        if (seekForwardOnly) {
--            minIndex = imageIndex;
--        }
--
--        // Locate the image.
--        int index = locateImage(imageIndex);
--
--        // If the located is not the one sought => exception.
--        if (index != imageIndex) {
--            throw new IndexOutOfBoundsException("imageIndex out of bounds!");
--        }
--    }
--
--    /**
--     * Skip the current image. If possible subclasses should override
--     * this method with a more efficient implementation.
--     *
--     * @return Whether the image was successfully skipped.
--     */
--    protected boolean skipImage() throws IOException {
--        boolean retval = false;
--
--        if(input == null) {
--            throw new IllegalStateException("input == null");
--        }
--        InputStream stream = null;
--        if(input instanceof ImageInputStream) {
--            stream = new InputStreamAdapter((ImageInputStream)input);
--        } else {
--            throw new IllegalArgumentException
--                ("!(input instanceof ImageInputStream)");
--        }
--
--        retval = decode(stream) != null;
--
--        if(retval) {
--            long pos = ((ImageInputStream)input).getStreamPosition();
--            if(pos > highWaterMark) {
--                highWaterMark = pos;
--            }
--        }
--
--        return retval;
--    }
--
--    /**
--     * Decodes an image from the supplied <code>InputStream</code>.
--     */
--    protected abstract mediaLibImage decode(InputStream stream)
--        throws IOException;
--
--    /**
--     * Returns the value of the private <code>mlibImage</code> instance
--     * variable initializing it first if it is <code>null</code>.
--     */
--    protected synchronized mediaLibImage getImage(int imageIndex)
--        throws IOException {
--        if(mlibImage == null || imageIndex != mlibImageIndex) {
--            if(input == null) {
--                throw new IllegalStateException("input == null");
--            }
--            seekToImage(imageIndex);
--            InputStream stream = null;
--            if(input instanceof ImageInputStream) {
--                stream = new InputStreamAdapter((ImageInputStream)input);
--            } else {
--                throw new IllegalArgumentException
--                    ("!(input instanceof ImageInputStream)");
--            }
--            mlibImage = decode(stream);
--            if(mlibImage != null) {
--                mlibImageIndex = imageIndex;
--                long pos = ((ImageInputStream)input).getStreamPosition();
--                if(pos > highWaterMark) {
--                    highWaterMark = pos;
--                }
--            } else { // mlibImage == null
--                mlibImageIndex = -1;
--            }
--        }
--        return mlibImage;
--    }
--
--    /**
--     * Returns the index of the image cached in the private
--     * <code>mlibImage</code> instance variable or -1 if no
--     * image is currently cached.
--     */
--    protected int getImageIndex() {
--        return mlibImageIndex;
--    }
--
--    public int getNumImages(boolean allowSearch) throws IOException {
--        if (input == null) {
--            throw new IllegalStateException("input == null");
--        }
--        if (seekForwardOnly && allowSearch) {
--            throw new IllegalStateException
--                ("seekForwardOnly && allowSearch!");
--        }
--
--        if (numImages > 0) {
--            return numImages;
--        }
--        if (allowSearch) {
--            this.numImages = locateImage(Integer.MAX_VALUE) + 1;
--        }
--        return numImages;
--    }
--
--    public int getWidth(int imageIndex) throws IOException {
--        seekToImage(imageIndex);
--
--        return getImage(imageIndex).getWidth();
--    }
--
--    public int getHeight(int imageIndex) throws IOException {
--        seekToImage(imageIndex);
--
--        return getImage(imageIndex).getHeight();
--    }
--
--    public IIOMetadata getStreamMetadata() throws IOException {
--        return null;
--    }
--
--    public IIOMetadata getImageMetadata(int imageIndex) throws IOException {
--        seekToImage(imageIndex);
--
--        return null;
--    }
--
--    public synchronized BufferedImage read(int imageIndex,
--                                           ImageReadParam param)
--        throws IOException {
--
--        processImageStarted(imageIndex);
--
--        seekToImage(imageIndex);
--
--        processImageProgress(0.0F);
--        processImageProgress(0.5F);
--
--        ImageTypeSpecifier rawImageType = getRawImageType(imageIndex);
--
--        processImageProgress(0.95F);
--
--        mediaLibImage mlImage = getImage(imageIndex);
--        int dataOffset = mlImage.getOffset();
--
--        SampleModel rawSampleModel = rawImageType.getSampleModel();
--
--        DataBuffer db;
--        int smType = rawSampleModel.getDataType();
--        switch(smType) {
--        case DataBuffer.TYPE_BYTE:
--            byte[] byteData = mlImage.getType() == mediaLibImage.MLIB_BIT ?
--                mlImage.getBitData() : mlImage.getByteData();
--            db = new DataBufferByte(byteData,
--                                    byteData.length - dataOffset,
--                                    dataOffset);
--            break;
--        case DataBuffer.TYPE_USHORT:
--            // Deliberately cast MLIB_SHORT to TYPE_USHORT.
--            short[] shortData = mlImage.getShortData();
--            if(shortData == null) {
--                shortData = mlImage.getUShortData();
--            }
--            db = new DataBufferUShort(shortData,
--                                      shortData.length - dataOffset,
--                                      dataOffset);
--            break;
--        default:
--            throw new UnsupportedOperationException
--                (I18N.getString("Generic0")+" "+smType);
--        }
--
--        WritableRaster rawRaster =
--            Raster.createWritableRaster(rawSampleModel, db, null);
--
--        ColorModel rawColorModel = rawImageType.getColorModel();
--
--        BufferedImage image =
--            new BufferedImage(rawColorModel,
--                              rawRaster,
--                              rawColorModel.isAlphaPremultiplied(),
--                              null); // XXX getDestination()?
--
--        Rectangle destRegion = new Rectangle(image.getWidth(),
--                                             image.getHeight());
--        int[] destinationBands = null;
--        int subX = 1;
--        int subY = 1;
--
--        if(param != null) {
--            BufferedImage destination = param.getDestination();
--            destinationBands = param.getDestinationBands();
--            Point destinationOffset = param.getDestinationOffset();
--            int[] sourceBands = param.getSourceBands();
--            Rectangle sourceRegion = param.getSourceRegion();
--            subX = param.getSourceXSubsampling();
--            subY = param.getSourceYSubsampling();
--
--            boolean isNominal =
--                destination == null &&
--                destinationBands == null &
--                destinationOffset.x == 0 && destinationOffset.y == 0 &&
--                sourceBands == null &&
--                sourceRegion == null &&
--                subX == 1 && subY == 1;
--
--            if(!isNominal) {
--                int srcWidth = image.getWidth();
--                int srcHeight = image.getHeight();
--
--                if(destination == null) {
--                    destination = getDestination(param,
--                                                 getImageTypes(imageIndex),
--                                                 srcWidth,
--                                                 srcHeight);
--                }
--
--                checkReadParamBandSettings(param,
--                                           image.getSampleModel().getNumBands(),
--                                           destination.getSampleModel().getNumBands());
--
--                Rectangle srcRegion = new Rectangle();
--                computeRegions(param, srcWidth, srcHeight, destination,
--                               srcRegion, destRegion);
--
--                WritableRaster dst =
--                    destination.getWritableTile(0, 0).createWritableChild(
--                        destRegion.x, destRegion.y,
--                        destRegion.width, destRegion.height,
--                        destRegion.x, destRegion.y,
--                        destinationBands);
--
--                if(subX != 1 || subY != 1) { // Subsampling
--                    WritableRaster src =
--                        image.getWritableTile(0, 0).createWritableChild(
--                                srcRegion.x, srcRegion.y,
--                                srcRegion.width, srcRegion.height,
--                                srcRegion.x, srcRegion.y,
--                                sourceBands);
--                    subsample(src, subX, subY, dst);
--                } else { // No subsampling
--                    WritableRaster src =
--                        image.getWritableTile(0, 0).createWritableChild(
--                            srcRegion.x, srcRegion.y,
--                            srcRegion.width, srcRegion.height,
--                            destRegion.x, destRegion.y,
--                            sourceBands);
--                    dst.setRect(src);
--                }
--
--                image = destination;
--            } else if(param.getDestinationType() != null) {
--                // Check for image type other than raw image type.
--                ImageTypeSpecifier destImageType = param.getDestinationType();
--                ColorSpace rawColorSpace = rawColorModel.getColorSpace();
--                ColorSpace destColorSpace =
--                    destImageType.getColorModel().getColorSpace();
--                if(!destColorSpace.equals(rawColorSpace) ||
--                   !destImageType.equals(rawImageType)) {
--                    // Look for destination type in legal types list.
--                    Iterator imageTypes = getImageTypes(imageIndex);
--                    boolean isLegalType = false;
--                    while(imageTypes.hasNext()) {
--                        ImageTypeSpecifier imageType =
--                            (ImageTypeSpecifier)imageTypes.next();
--                        if(imageType.equals(destImageType)) {
--                            isLegalType = true;
--                            break;
--                        }
--                    }
--
--                    if(isLegalType) {
--                        // Set the destination raster.
--                        WritableRaster raster;
--                        if(rawSampleModel.equals(destImageType.getSampleModel())) {
--                            // Re-use the raw raster.
--                            raster = rawRaster;
--                        } else {
--                            // Create a new raster and copy the data.
--                            SampleModel sm = destImageType.getSampleModel();
--                            raster = Raster.createWritableRaster(sm, null);
--                            raster.setRect(rawRaster);
--                        }
--
--                        // Replace the output image.
--                        ColorModel cm = destImageType.getColorModel();
--                        image = new BufferedImage(cm,
--                                                  raster,
--                                                  cm.isAlphaPremultiplied(),
--                                                  null);
--                    }
--                }
--            }
--        }
--
--        processImageUpdate(image,
--                           destRegion.x, destRegion.y,
--                           destRegion.width, destRegion.height,
--                           subX, subY, destinationBands);
--
--        processImageProgress(1.0F);
--        processImageComplete();
--
--        return image;
--    }
--
--    public void reset() {
--        resetLocal();
--        super.reset();
--    }
--
--    protected void resetLocal() {
--        currIndex = -1;
--        highWaterMark = Long.MIN_VALUE;
--        imageStartPosition.clear();
--        numImages = -1;
--        mlibImage = null;
--        mlibImageIndex = -1;
--    }
--
--    public void setInput(Object input,
--                         boolean seekForwardOnly,
--                         boolean ignoreMetadata) {
--        super.setInput(input, seekForwardOnly, ignoreMetadata);
--        if (input != null) {
--            // Check the class type.
--            if (!(input instanceof ImageInputStream)) {
--                throw new IllegalArgumentException
--                    ("!(input instanceof ImageInputStream)");
--            }
--        }
--        resetLocal();
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/clib/CLibImageWriter.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/clib/CLibImageWriter.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,854 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibImageWriter.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.6 $
-- * $Date: 2007/02/06 22:14:59 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.clib;
--
--import java.awt.Point;
--import java.awt.Rectangle;
--import java.awt.color.ColorSpace;
--import java.awt.geom.AffineTransform;
--import java.awt.image.AffineTransformOp;
--import java.awt.image.ColorModel;
--import java.awt.image.ComponentSampleModel;
--import java.awt.image.DataBuffer;
--import java.awt.image.DataBufferByte;
--import java.awt.image.DataBufferUShort;
--import java.awt.image.IndexColorModel;
--import java.awt.image.MultiPixelPackedSampleModel;
--import java.awt.image.PixelInterleavedSampleModel;
--import java.awt.image.Raster;
--import java.awt.image.RenderedImage;
--import java.awt.image.SampleModel;
--import java.awt.image.SinglePixelPackedSampleModel;
--import java.awt.image.WritableRaster;
--import java.io.IOException;
--import javax.imageio.IIOImage;
--import javax.imageio.ImageWriter;
--import javax.imageio.ImageWriteParam;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.metadata.IIOMetadata;
--import javax.imageio.spi.ImageWriterSpi;
--import com.sun.medialib.codec.jiio.Constants;
--import com.sun.medialib.codec.jiio.mediaLibImage;
--
--public abstract class CLibImageWriter extends ImageWriter {
--    /**
--     * Returns the data array from the <code>DataBuffer</code>.
--     */
--    private static final Object getDataBufferData(DataBuffer db) {
--        Object data;
--
--        int dType = db.getDataType();
--        switch (dType) {
--        case DataBuffer.TYPE_BYTE:
--            data = ((DataBufferByte)db).getData();
--            break;
--        case DataBuffer.TYPE_USHORT:
--            data = ((DataBufferUShort)db).getData();
--            break;
--        default:
--            throw new IllegalArgumentException
--                (I18N.getString("Generic0")+" "+dType);
--        }
--
--        return data;
--    }
--
--    /**
--     * Returns the mediaLib type enum given the Java2D type enum.
--     */
--    private static final int getMediaLibDataType(int dataType) {
--        int mlibType;
--
--        switch (dataType) {
--        case DataBuffer.TYPE_BYTE:
--            mlibType = mediaLibImage.MLIB_BYTE;
--            break;
--        case DataBuffer.TYPE_USHORT:
--            mlibType = mediaLibImage.MLIB_USHORT;
--            break;
--        default:
--            throw new IllegalArgumentException
--                (I18N.getString("Generic0")+" "+dataType);
--        }
--
--        return mlibType;
--    }
--
--    /**
--     * Returns the mediaLib format enum given the <code>SampleModel</code>
--     * and <code>ColorModel</code> of an image. If the format cannot be
--     * determined to be anything more specific, the value
--     * <code>Constants.MLIB_FORMAT_UNKNOWN</code> will be returned.
--     *
--     * @param sampleModel The <code>SampleModel</code> describing the
--     * layout of the <code>DataBuffer</code>; may be <code>null</code>.
--     * @param colorModel The <code>ColorModel</code> describing the
--     * mapping of the samples in a pixel to a color.
--     *
--     * @throws IllegalArgumentExcaption if <code>sampleModel</code> is
--     * <code>null</code>.
--     *
--     * @return One of the <code>Constants.MLIB_FORMAT</code> constants.
--     */
--    private static final int getMediaLibFormat(SampleModel sampleModel,
--                                               ColorModel colorModel) {
--        if(sampleModel == null) {
--            throw new IllegalArgumentException("sampleModel == null!");
--        }
--
--        int mlibFormat = Constants.MLIB_FORMAT_UNKNOWN;
--
--        if(sampleModel instanceof SinglePixelPackedSampleModel &&
--           sampleModel.getNumBands() == 4 &&
--           colorModel != null &&
--           colorModel.hasAlpha()) {
--            int[] masks =
--                ((SinglePixelPackedSampleModel)sampleModel).getBitMasks();
--            if(masks[3] == 0xff000000) {
--                if(masks[0] == 0xff &&
--                   masks[1] == 0xff00 &&
--                   masks[2] == 0xff0000) {
--                    mlibFormat = Constants.MLIB_FORMAT_PACKED_ABGR;
--                } else if(masks[0] == 0xff0000 &&
--                          masks[1] == 0xff00 &&
--                          masks[2] == 0xff) {
--                    mlibFormat = Constants.MLIB_FORMAT_PACKED_ARGB;
--                }
--            }
--        } else if(sampleModel instanceof ComponentSampleModel) {
--            ComponentSampleModel csm = (ComponentSampleModel)sampleModel;
--            int bandOffsets[] = csm.getBandOffsets();
--            int pixelStride = csm.getPixelStride();
--
--            if (pixelStride == bandOffsets.length) {
--                int numBands = pixelStride; // for clarity
--
--                boolean hasOneBank = true;
--                int bankIndices[] = csm.getBankIndices();
--                for (int i = 1; i < bankIndices.length; i++) {
--                    if(bankIndices[i] != bankIndices[0]) {
--                        hasOneBank = false;
--                    }
--                }
--
--                if(hasOneBank) {
--                    if(colorModel instanceof IndexColorModel) {
--                        mlibFormat = Constants.MLIB_FORMAT_INDEXED;
--                    } else if(numBands == 1) {
--                        mlibFormat = Constants.MLIB_FORMAT_GRAYSCALE;
--                    } else if(numBands == 2 &&
--                              bandOffsets[0] == 0 &&
--                              bandOffsets[1] == 1) {
--                        mlibFormat = Constants.MLIB_FORMAT_GRAYSCALE_ALPHA;
--                    } else if(numBands == 3) {
--                        int csType = colorModel != null ?
--                            colorModel.getColorSpace().getType() :
--                            ColorSpace.TYPE_RGB;
--                        if(csType == ColorSpace.TYPE_RGB) {
--                            if(bandOffsets[0] == 2 &&
--                               bandOffsets[1] == 1 &&
--                               bandOffsets[2] == 0) {
--                                mlibFormat = Constants.MLIB_FORMAT_BGR;
--                            } else if(bandOffsets[0] == 0 &&
--                                      bandOffsets[1] == 1 &&
--                                      bandOffsets[2] == 2) {
--                                mlibFormat = Constants.MLIB_FORMAT_RGB;
--                            }
--                        } else if(csType == ColorSpace.TYPE_Yxy &&
--                                  bandOffsets[0] == 0 &&
--                                  bandOffsets[1] == 1 &&
--                                  bandOffsets[2] == 2) {
--                            mlibFormat = Constants.MLIB_FORMAT_YCC;
--                        }
--                    } else if(numBands == 4) {
--                        int csType = colorModel != null ?
--                            colorModel.getColorSpace().getType() :
--                            ColorSpace.TYPE_RGB;
--                        if(csType == ColorSpace.TYPE_RGB) {
--                            if(bandOffsets[3] == 0) {
--                                if(bandOffsets[0] == 3 &&
--                                   bandOffsets[1] == 2 &&
--                                   bandOffsets[2] == 1) {
--                                    mlibFormat = Constants.MLIB_FORMAT_ABGR;
--                                } else if(bandOffsets[0] == 1 &&
--                                          bandOffsets[1] == 2 &&
--                                          bandOffsets[2] == 3) {
--                                    mlibFormat = Constants.MLIB_FORMAT_ARGB;
--                                }
--                            } else if(bandOffsets[3] == 3) {
--                                if(bandOffsets[0] == 0 &&
--                                   bandOffsets[1] == 1 &&
--                                   bandOffsets[2] == 2) {
--                                    mlibFormat = Constants.MLIB_FORMAT_RGBA;
--                                } else if(bandOffsets[0] == 2 &&
--                                          bandOffsets[1] == 1 &&
--                                          bandOffsets[2] == 0) {
--                                    mlibFormat = Constants.MLIB_FORMAT_BGRA;
--                                }
--                            }
--                        } else if(csType == ColorSpace.TYPE_CMYK &&
--                                  bandOffsets[0] == 0 &&
--                                  bandOffsets[1] == 1 &&
--                                  bandOffsets[2] == 2 &&
--                                  bandOffsets[3] == 3) {
--                            mlibFormat = Constants.MLIB_FORMAT_CMYK;
--                        } else if(csType == ColorSpace.TYPE_Yxy &&
--                                  bandOffsets[0] == 0 &&
--                                  bandOffsets[1] == 1 &&
--                                  bandOffsets[2] == 2 &&
--                                  bandOffsets[3] == 3) {
--                            if(colorModel != null &&
--                               colorModel.hasAlpha()) {
--                                mlibFormat = Constants.MLIB_FORMAT_YCCA;
--                            } else {
--                                mlibFormat = Constants.MLIB_FORMAT_YCCK;
--                            }
--                        }
--                    }
--                }
--            }
--        }
--
--        return mlibFormat;
--    }
--
--    /**
--     * Returns a contiguous <code>Raster</code> of data over the specified
--     * <code>Rectangle</code>. If the region is a sub-region of a single
--     * tile, then a child of that tile will be returned. If the region
--     * overlaps more than one tile and has 8 bits per sample, then a
--     * pixel interleaved Raster having band offsets 0,1,... will be returned.
--     * Otherwise the Raster returned by <code>im.copyData(null)</code> will
--     * be returned.
--     */
--    private static final Raster getContiguousData(RenderedImage im,
--                                                  Rectangle region) {
--        if(im == null) {
--            throw new IllegalArgumentException("im == null");
--        } else if(region == null) {
--            throw new IllegalArgumentException("region == null");
--        }
--
--        Raster raster;
--        if(im.getNumXTiles() == 1 && im.getNumYTiles() == 1) {
--            // Image is not tiled so just get a reference to the tile.
--            raster = im.getTile(im.getMinTileX(), im.getMinTileY());
--
--            // Ensure result has requested coverage.
--            Rectangle bounds = raster.getBounds();
--            if (!bounds.equals(region)) {
--                raster = raster.createChild(region.x, region.y,
--                                            region.width, region.height,
--                                            region.x, region.y,
--                                            null);
--            }
--        } else {
--            // Image is tiled.
--
--            // Create an interleaved raster for copying for 8-bit case.
--            // This ensures that for RGB data the band offsets are {0,1,2}.
--            SampleModel sampleModel = im.getSampleModel();
--            WritableRaster target = sampleModel.getSampleSize(0) == 8 ?
--                Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
--                                               im.getWidth(),
--                                               im.getHeight(),
--                                               sampleModel.getNumBands(),
--                                               new Point(im.getMinX(),
--                                                         im.getMinY())) :
--                null;
--
--            // Copy the data.
--            raster = im.copyData(target);
--        }
--
--        return raster;
--    }
--
--    /**
--     * Subsamples and sub-bands the input <code>Raster</code> over a
--     * sub-region and stores the result in a <code>WritableRaster</code>.
--     *
--     * @param src The source <code>Raster</code>
--     * @param sourceBands The source bands to use; may be <code>null</code>
--     * @param subsampleX The subsampling factor along the horizontal axis.
--     * @param subsampleY The subsampling factor along the vertical axis.
--     * in which case all bands will be used.
--     * @param dst The destination <code>WritableRaster</code>.
--     * @throws IllegalArgumentException if <code>source</code> is
--     * <code>null</code> or empty, <code>dst</code> is <code>null</code>,
--     * <code>sourceBands.length</code> exceeds the number of bands in
--     * <code>source</code>, or <code>sourcBands</code> contains an element
--     * which is negative or greater than or equal to the number of bands
--     * in <code>source</code>.
--     */
--    private static void reformat(Raster source,
--                                 int[] sourceBands,
--                                 int subsampleX,
--                                 int subsampleY,
--                                 WritableRaster dst) {
--        // Check for nulls.
--        if(source == null) {
--            throw new IllegalArgumentException("source == null!");
--        } else if(dst == null) {
--            throw new IllegalArgumentException("dst == null!");
--        }
--
--        // Validate the source bounds. XXX is this needed?
--        Rectangle sourceBounds = source.getBounds();
--        if(sourceBounds.isEmpty()) {
--            throw new IllegalArgumentException
--                ("source.getBounds().isEmpty()!");
--        }
--
--        // Check sub-banding.
--        boolean isSubBanding = false;
--        int numSourceBands = source.getSampleModel().getNumBands();
--        if(sourceBands != null) {
--            if(sourceBands.length > numSourceBands) {
--                throw new IllegalArgumentException
--                    ("sourceBands.length > numSourceBands!");
--            }
--
--            boolean isRamp = sourceBands.length == numSourceBands;
--            for(int i = 0; i < sourceBands.length; i++) {
--                if(sourceBands[i] < 0 || sourceBands[i] >= numSourceBands) {
--                    throw new IllegalArgumentException
--                        ("sourceBands[i] < 0 || sourceBands[i] >= numSourceBands!");
--                } else if(sourceBands[i] != i) {
--                    isRamp = false;
--                }
--            }
--
--            isSubBanding = !isRamp;
--        }
--
--        // Allocate buffer for a single source row.
--        int sourceWidth = sourceBounds.width;
--        int[] pixels = new int[sourceWidth*numSourceBands];
--
--        // Initialize variables used in loop.
--        int sourceX = sourceBounds.x;
--        int sourceY = sourceBounds.y;
--        int numBands = sourceBands != null ?
--            sourceBands.length : numSourceBands;
--        int dstWidth = dst.getWidth();
--        int dstYMax = dst.getHeight() - 1;
--        int copyFromIncrement = numSourceBands*subsampleX;
--
--        // Loop over source rows, subsample each, and store in destination.
--        for(int dstY = 0; dstY <= dstYMax; dstY++) {
--            // Read one row.
--            source.getPixels(sourceX, sourceY, sourceWidth, 1, pixels);
--
--            // Copy within the same buffer by left shifting.
--            if(isSubBanding) {
--                int copyFrom = 0;
--                int copyTo = 0;
--                for(int i = 0; i < dstWidth; i++) {
--                    for(int j = 0; j < numBands; j++) {
--                        pixels[copyTo++] = pixels[copyFrom + sourceBands[j]];
--                    }
--                    copyFrom += copyFromIncrement;
--                }
--            } else {
--                int copyFrom = copyFromIncrement;
--                int copyTo = numSourceBands;
--                // Start from index 1 as no need to copy the first pixel.
--                for(int i = 1; i < dstWidth; i++) {
--                    int k = copyFrom;
--                    for(int j = 0; j < numSourceBands; j++) {
--                        pixels[copyTo++] = pixels[k++];
--                    }
--                    copyFrom += copyFromIncrement;
--                }
--            }
--
--            // Set the destionation row.
--            dst.setPixels(0, dstY, dstWidth, 1, pixels);
--
--            // Increment the source row.
--            sourceY += subsampleY;
--        }
--    }
--
--    protected CLibImageWriter(ImageWriterSpi originatingProvider) {
--        super(originatingProvider);
--    }
--
--    public IIOMetadata convertImageMetadata(IIOMetadata inData,
--                                            ImageTypeSpecifier imageType,
--                                            ImageWriteParam param) {
--        return null;
--    }
--
--    public IIOMetadata convertStreamMetadata(IIOMetadata inData,
--                                             ImageWriteParam param) {
--        return null;
--    }
--
--    public IIOMetadata
--        getDefaultImageMetadata(ImageTypeSpecifier imageType,
--                                ImageWriteParam param) {
--        return null;
--    }
--
--    public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
--        return null;
--    }
--
--    /* XXX
--    protected int getSignificantBits(RenderedImage image) {
--        SampleModel sampleModel = image.getSampleModel();
--        int numBands = sampleModel.getNumBands();
--        int[] sampleSize = sampleModel.getSampleSize();
--        int significantBits = sampleSize[0];
--        for(int i = 1; i < numBands; i++) {
--            significantBits = Math.max(significantBits, sampleSize[i]);
--        }
--
--        return significantBits;
--    }
--    */
--
--    // Code copied from ImageReader.java with ImageReadParam replaced
--    // by ImageWriteParam.
--    private static final Rectangle getSourceRegion(ImageWriteParam param,
--                                                   int sourceMinX,
--                                                   int sourceMinY,
--                                                   int srcWidth,
--                                                   int srcHeight) {
--        Rectangle sourceRegion =
--            new Rectangle(sourceMinX, sourceMinY, srcWidth, srcHeight);
--        if (param != null) {
--            Rectangle region = param.getSourceRegion();
--            if (region != null) {
--                sourceRegion = sourceRegion.intersection(region);
--            }
--
--            int subsampleXOffset = param.getSubsamplingXOffset();
--            int subsampleYOffset = param.getSubsamplingYOffset();
--            sourceRegion.x += subsampleXOffset;
--            sourceRegion.y += subsampleYOffset;
--            sourceRegion.width -= subsampleXOffset;
--            sourceRegion.height -= subsampleYOffset;
--        }
--
--        return sourceRegion;
--    }
--
--    /**
--     * Returns a <code>mediaLibImage</code> for a specific encoder to use
--     * to encode <code>image</code>.
--     *
--     * @param image The image to encode.
--     * @param param The write parameters.
--     * @param allowBilevel Whether bilevel images are allowed. A bilevel
--     * image must have one 1-bit sample per pixel, have data type
--     * <code>DataBuffer.TYE_BYTE</code>, and have a
--     * <code>MultiPixelPackedSampleModel</code>.
--     * @param supportedFormats An array containing constan values from
--     * the set of <code>mediaLibImage.MLIB_FORMAT</code> enums.
--     *
--     * @throws IllegalArgumentException if <code>supportedFormats</code>
--     * is <code>null</code>.
--     *
--     * @return A <code>mediaLibImage in a format capable of being written
--     * by the encoder.
--     */
--    protected mediaLibImage getMediaLibImage(RenderedImage image,
--                                             ImageWriteParam param,
--                                             boolean allowBilevel,
--                                             int[] supportedFormats) {
--        if(supportedFormats == null) {
--            throw new IllegalArgumentException("supportedFormats == null!");
--        }
--
--        // Determine the source region.
--        Rectangle sourceRegion = getSourceRegion(param,
--                                                 image.getMinX(),
--                                                 image.getMinY(),
--                                                 image.getWidth(),
--                                                 image.getHeight());
--
--        if(sourceRegion.isEmpty()) {
--            throw new IllegalArgumentException("sourceRegion.isEmpty()");
--        }
--
--        // Check whether reformatting is necessary to conform to mediaLib
--        // image format (packed bilevel if allowed or ((G|I)|(RGB))[A]).
--
--        // Flag indicating need to reformat data.
--        boolean reformatData = false;
--
--        // Flag indicating bilevel data.
--        boolean isBilevel = false;
--
--        // Value indicating the mediaLib image format.
--        int mediaLibFormat = Constants.MLIB_FORMAT_UNKNOWN;
--
--        // Get the SampleModel.
--        SampleModel sampleModel = image.getSampleModel();
--
--        // Get the number of bands.
--        int numSourceBands = sampleModel.getNumBands();
--
--        // Get the source sub-banding array.
--        int[] sourceBands = param != null ? param.getSourceBands() : null;
--
--        // Check for non-nominal sub-banding.
--        int numBands;
--        if(sourceBands != null) {
--            numBands = sourceBands.length;
--            if(numBands != numSourceBands) {
--                // The number of bands must be the same.
--                reformatData = true;
--            } else {
--                // The band order must not change.
--                for(int i = 0; i < numSourceBands; i++) {
--                    if(sourceBands[i] != i) {
--                        reformatData = true;
--                        break;
--                    }
--                }
--            }
--        } else {
--            numBands = numSourceBands;
--        }
--
--        // If sub-banding does not dictate reformatting, check subsampling..
--        if(!reformatData && param != null &&
--           (param.getSourceXSubsampling() != 1 ||
--            param.getSourceXSubsampling() != 1)) {
--            reformatData = true;
--        }
--
--        // If sub-banding does not dictate reformatting check SampleModel.
--        if(!reformatData) {
--            if(allowBilevel &&
--               sampleModel.getNumBands() == 1 &&
--               sampleModel.getSampleSize(0) == 1 &&
--               sampleModel instanceof MultiPixelPackedSampleModel &&
--               sampleModel.getDataType() == DataBuffer.TYPE_BYTE) {
--                // Need continguous packed bits.
--                MultiPixelPackedSampleModel mppsm =
--                    (MultiPixelPackedSampleModel)sampleModel;
--                if(mppsm.getPixelBitStride() == 1) {
--                    isBilevel = true;
--                } else {
--                    reformatData = true;
--                }
--            } else {
--                // Set the mediaLib format flag.
--                mediaLibFormat = getMediaLibFormat(sampleModel,
--                                                   image.getColorModel());
--
--                // Set the data reformatting flag.
--                reformatData = true;
--                int len = supportedFormats.length;
--                for(int i = 0; i < len; i++) {
--                    if(mediaLibFormat == supportedFormats[i]) {
--                        reformatData = false;
--                        break;
--                    }
--                }
--            }
--        }
--
--        // Variable for the eventual destination data.
--        Raster raster = null;
--
--        if(reformatData) {
--            // Determine the maximum bit depth.
--            int[] sampleSize = sampleModel.getSampleSize();
--            int bitDepthMax = sampleSize[0];
--            for(int i = 1; i < numSourceBands; i++) {
--                bitDepthMax = Math.max(bitDepthMax, sampleSize[i]);
--            }
--
--            // Set the data type as a function of bit depth.
--            int dataType;
--            if(bitDepthMax <= 8) {
--                dataType = DataBuffer.TYPE_BYTE;
--            } else if(bitDepthMax <= 16) {
--                dataType = DataBuffer.TYPE_USHORT;
--            } else {
--                throw new UnsupportedOperationException
--                    (I18N.getString("CLibImageWriter0")+" "+bitDepthMax);
--            }
--
--            // Determine the width and height.
--            int width;
--            int height;
--            if(param != null) {
--                int subsampleX = param.getSourceXSubsampling();
--                int subsampleY = param.getSourceYSubsampling();
--                width = (sourceRegion.width + subsampleX - 1)/subsampleX;
--                height = (sourceRegion.height + subsampleY - 1)/subsampleY;
--            } else {
--                width = sourceRegion.width;
--                height = sourceRegion.height;
--            }
--
--            // Load a ramp for band offsets.
--            int[] newBandOffsets = new int[numBands];
--            for(int i = 0; i < numBands; i++) {
--                newBandOffsets[i] = i;
--            }
--
--            // Create a new SampleModel.
--            SampleModel newSampleModel;
--            if(allowBilevel &&
--               sampleModel.getNumBands() == 1 &&
--               bitDepthMax == 1) {
--                // Bilevel image.
--                newSampleModel =
--                    new MultiPixelPackedSampleModel(dataType,
--                                                    width,
--                                                    height,
--                                                    1);
--                isBilevel = true;
--            } else {
--                // Pixel interleaved image.
--                newSampleModel =
--                    new PixelInterleavedSampleModel(dataType,
--                                                    width,
--                                                    height,
--                                                    newBandOffsets.length,
--                                                    width*numSourceBands,
--                                                    newBandOffsets);
--            }
--
--            // Create a new Raster at (0,0).
--            WritableRaster newRaster =
--                Raster.createWritableRaster(newSampleModel, null);
--
--            // Populate the new Raster.
--            if(param != null &&
--               (param.getSourceXSubsampling() != 1 ||
--                param.getSourceXSubsampling() != 1)) {
--                // Subsampling, possibly with sub-banding.
--                reformat(getContiguousData(image, sourceRegion),
--                         sourceBands,
--                         param.getSourceXSubsampling(),
--                         param.getSourceYSubsampling(),
--                         newRaster);
--            } else if(sourceBands == null &&
--                      image.getSampleModel().getClass().isInstance
--                      (newSampleModel) &&
--                      newSampleModel.getTransferType() ==
--                      image.getSampleModel().getTransferType()) {
--                // Neither subsampling nor sub-banding.
--                WritableRaster translatedChild =
--                    newRaster.createWritableTranslatedChild(sourceRegion.x,
--                                                            sourceRegion.y);
--                // Use copyData() to avoid potentially cobbling the entire
--                // source region into an extra Raster via getData().
--                image.copyData(translatedChild);
--            } else {
--                // Cannot use copyData() so use getData() to retrieve and
--                // possibly sub-band the source data and use setRect().
--                WritableRaster translatedChild =
--                    newRaster.createWritableTranslatedChild(sourceRegion.x,
--                                                            sourceRegion.y);
--                Raster sourceRaster = getContiguousData(image, sourceRegion);
--                if(sourceBands != null) {
--                    // Copy only the requested bands.
--                    sourceRaster =
--                        sourceRaster.createChild(sourceRegion.x,
--                                                 sourceRegion.y,
--                                                 sourceRegion.width,
--                                                 sourceRegion.height,
--                                                 sourceRegion.x,
--                                                 sourceRegion.y,
--                                                 sourceBands);
--                }
--
--                // Get the region from the image and set it into the Raster.
--                translatedChild.setRect(sourceRaster);
--            }
--
--            // Replace Raster and SampleModel.
--            raster = newRaster;
--            sampleModel = newRaster.getSampleModel();
--        } else { // !reformatData
--            // No reformatting needed.
--            raster = getContiguousData(image, sourceRegion).createTranslatedChild(0, 0);
--            sampleModel = raster.getSampleModel();
--
--            // Update mediaLibFormat indicator in case getContiguousData()
--            // has changed the layout of the data.
--            mediaLibFormat = getMediaLibFormat(sampleModel, image.getColorModel());
--        }
--
--        // The mediaLib image.
--        mediaLibImage mlibImage = null;
--
--        // Create a mediaLibImage with reference to the Raster data.
--        if(isBilevel) {
--            // Bilevel image: either is was already bilevel or was
--            // formatted to bilevel.
--
--            MultiPixelPackedSampleModel mppsm =
--                ((MultiPixelPackedSampleModel)sampleModel);
--
--            // Get the line stride.
--            int stride = mppsm.getScanlineStride();
--
--            // Determine the offset to the start of the data.
--            int offset =
--                raster.getDataBuffer().getOffset() -
--                raster.getSampleModelTranslateY()*stride -
--                raster.getSampleModelTranslateX()/8 +
--                mppsm.getOffset(0, 0);
--
--            // Get a reference to the internal data array.
--            Object bitData = getDataBufferData(raster.getDataBuffer());
--
--            mlibImage = new mediaLibImage(mediaLibImage.MLIB_BIT,
--                                          1,
--                                          raster.getWidth(),
--                                          raster.getHeight(),
--                                          stride,
--                                          offset,
--                                          (byte)mppsm.getBitOffset(0),
--                                          bitData);
--        } else {
--            // If the image is not bilevel then it has to be component.
--            ComponentSampleModel csm = (ComponentSampleModel)sampleModel;
--
--            // Set the mediaLib data type
--            int mlibDataType = getMediaLibDataType(sampleModel.getDataType());
--
--            // Get a reference to the internal data array.
--            Object data = getDataBufferData(raster.getDataBuffer());
--
--            // Get the line stride.
--            int stride = csm.getScanlineStride();
--
--            // Determine the offset of the first sample from the offset
--            // indicated by the (x,y) coordinates. This offset is the
--            // minimum valued offset, not the offset of, e.g., red (index 0)
--            // as the Raster is by now in a contiguous format that
--            // the encoder is guaranteed to handle regardless of whether
--            // the smallest offset is to the, e.g., red band.
--            int[] bandOffsets = csm.getBandOffsets();
--            int minBandOffset = bandOffsets[0];
--            for(int i = 1; i < bandOffsets.length; i++) {
--                if(bandOffsets[i] < minBandOffset) {
--                    minBandOffset = bandOffsets[i];
--                }
--            }
--
--            // Determine the offset to the start of the data. The
--            // sampleModelTranslate parameters are the translations from
--            // Raster to SampleModel coordinates and must be subtracted
--            // from the Raster coordinates.
--            int offset =
--                (raster.getMinY() -
--                 raster.getSampleModelTranslateY())*stride +
--                (raster.getMinX() -
--                 raster.getSampleModelTranslateX())*numSourceBands +
--                minBandOffset;
--
--            // Create the image.
--            mlibImage =
--                !reformatData &&
--                mediaLibFormat != Constants.MLIB_FORMAT_UNKNOWN ?
--                new mediaLibImage(mlibDataType,
--                                  numSourceBands,
--                                  raster.getWidth(),
--                                  raster.getHeight(),
--                                  stride,
--                                  offset,
--                                  mediaLibFormat,
--                                  data) :
--                new mediaLibImage(mlibDataType,
--                                  numSourceBands,
--                                  raster.getWidth(),
--                                  raster.getHeight(),
--                                  stride,
--                                  offset,
--                                  data);
--        }
--
--        return mlibImage;
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageReader.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageReader.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,388 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibJPEGImageReader.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.10 $
-- * $Date: 2006/04/24 20:53:01 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.jpeg;
--
--import java.awt.color.ColorSpace;
--import java.awt.color.ICC_ColorSpace;
--import java.awt.color.ICC_Profile;
--import java.awt.image.BufferedImage;
--import java.awt.image.ColorModel;
--import java.awt.image.DataBuffer;
--import java.awt.image.MultiPixelPackedSampleModel;
--import java.awt.image.PixelInterleavedSampleModel;
--import java.awt.image.SampleModel;
--import java.io.File;
--import java.io.FileInputStream;
--import java.io.InputStream;
--import java.io.IOException;
--import java.util.ArrayList;
--import java.util.HashMap;
--import java.util.Iterator;
--import javax.imageio.IIOException;
--import javax.imageio.IIOImage;
--import javax.imageio.ImageReader;
--import javax.imageio.ImageReadParam;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.metadata.IIOMetadata;
--import javax.imageio.spi.ImageReaderSpi;
--import javax.imageio.stream.ImageInputStream;
--import com.sun.media.imageioimpl.common.InvertedCMYKColorSpace;
--import com.sun.media.imageioimpl.plugins.clib.CLibImageReader;
--import com.sun.media.imageioimpl.plugins.clib.InputStreamAdapter;
--import com.sun.medialib.codec.jpeg.Decoder;
--import com.sun.medialib.codec.jiio.mediaLibImage;
--
--final class CLibJPEGImageReader extends CLibImageReader {
--    private static final boolean DEBUG = false; // XXX false for release
--
--    private mediaLibImage infoImage = null;
--    private int infoImageIndex = -1;
--    private byte[] iccProfileData = null;
--    private IIOMetadata imageMetadata = null;
--    private int imageMetadataIndex = -1;
--    private HashMap imageTypes = new HashMap();
--    private int bitDepth; // XXX Should depend on imageIndex.
--
--    CLibJPEGImageReader(ImageReaderSpi originatingProvider) {
--        super(originatingProvider);
--    }
--
--    // Implement abstract method defined in superclass.
--    protected final synchronized mediaLibImage decode(InputStream stream)
--        throws IOException {
--        if(DEBUG) System.out.println("In decode()");
--
--        mediaLibImage mlImage = null;
--        Decoder decoder = null;
--        try {
--            if(stream instanceof InputStreamAdapter) {
--                ImageInputStream iis =
--                    ((InputStreamAdapter)stream).getWrappedStream();
--                decoder = new Decoder(iis);
--            } else {
--                decoder = new Decoder(stream);
--            }
--            //decoder.setType(Decoder.JPEG_TYPE_UNKNOWN);
--            mlImage = decoder.decode(null);
--
--            // Set the ICC profile data.
--            iccProfileData = decoder.getEmbeddedICCProfile();
--
--            // If there is a profile need to invert the data if they
--            // are YCCK or CMYK originally.
--            if(iccProfileData != null &&
--               mlImage.getType() == mediaLibImage.MLIB_BYTE) {
--                int format = mlImage.getFormat();
--                if(format == mediaLibImage.MLIB_FORMAT_CMYK ||
--                   format == mediaLibImage.MLIB_FORMAT_YCCK) {
--                    long t0 = System.currentTimeMillis();
--                    byte[] data = mlImage.getByteData();
--                    int len = data.length;
--                    for(int i = mlImage.getOffset(); i < len; i++) {
--                        data[i] = (byte)(255 - data[i]&0xff);
--                    }
--                }
--            }
--
--        } catch(Throwable t) {
--            throw new IIOException("codecLib error", t);
--        }
--
--        if(mlImage == null) {
--            throw new IIOException(I18N.getString("CLibJPEGImageReader0"));
--        }
--
--        // Set variable indicating bit depth.
--        try {
--            bitDepth = decoder.getDepth();
--        } catch(Throwable t) {
--            throw new IIOException("codecLib error", t);
--        }
--
--        // Free native resources.
--        decoder.dispose();
--
--        if(DEBUG) {
--            System.out.println("type = "+mlImage.getType());
--            System.out.println("channels = "+mlImage.getChannels());
--            System.out.println("width = "+mlImage.getWidth());
--            System.out.println("height = "+mlImage.getHeight());
--            System.out.println("stride = "+mlImage.getStride());
--            System.out.println("offset = "+mlImage.getOffset());
--            System.out.println("bitOffset = "+mlImage.getBitOffset());
--            System.out.println("format = "+mlImage.getFormat());
--        }
--
--        return mlImage;
--    }
--
--    // Retrieve mediaLibImage containing everything except possibly the
--    // decoded image data. If the real image has already been decoded
--    // then it will be returned.
--    private synchronized mediaLibImage getInfoImage(int imageIndex)
--        throws IOException {
--        if(DEBUG) System.out.println("In getInfoImage()");
--        if(infoImage == null || imageIndex != infoImageIndex) {
--            // Use the cached image if it has the correct index.
--            if(imageIndex == getImageIndex()) {
--                if(DEBUG) {
--                    System.out.println("Using cached image.");
--                }
--                infoImage = getImage(imageIndex);
--                infoImageIndex = imageIndex;
--                return infoImage;
--            }
--
--            if(input == null) {
--                throw new IllegalStateException("input == null");
--            }
--
--            // Check the input and set local variable.
--            ImageInputStream iis = null;
--            if(input instanceof ImageInputStream) {
--                iis = (ImageInputStream)input;
--            } else {
--                throw new IllegalArgumentException
--                    ("!(input instanceof ImageInputStream)");
--            }
--
--            seekToImage(imageIndex);
--
--            // Mark the input.
--            iis.mark();
--
--            Decoder decoder = null;
--            try {
--                // Create the decoder
--                decoder = new Decoder(iis);
--
--                // Set the informational image.
--                infoImage = decoder.getSize();
--
--                // Set the ICC profile data.
--                iccProfileData = decoder.getEmbeddedICCProfile();
--            } catch(Throwable t) {
--                throw new IIOException("codecLib error", t);
--            }
--
--            // XXX The lines marked "XXX" are a workaround for getSize()
--            // not correctly setting the format of infoImage.
--            if(infoImage == null ||
--               (infoImage.getFormat() == // XXX
--                mediaLibImage.MLIB_FORMAT_UNKNOWN && // XXX
--                ((infoImage = getImage(imageIndex)) == null))) { // XXX
--                throw new IIOException(I18N.getString("CLibJPEGImageReader0"));
--            }
--
--            infoImageIndex = imageIndex;
--
--            try {
--                // Set variable indicating bit depth.
--                bitDepth = decoder.getDepth();
--            } catch(Throwable t) {
--                throw new IIOException("codecLib error", t);
--            }
--
--            // Reset the input to the marked position.
--            iis.reset();
--
--            // Free native resources.
--            decoder.dispose();
--
--            if(DEBUG) {
--                System.out.println("type = "+infoImage.getType());
--                System.out.println("channels = "+infoImage.getChannels());
--                System.out.println("width = "+infoImage.getWidth());
--                System.out.println("height = "+infoImage.getHeight());
--                System.out.println("stride = "+infoImage.getStride());
--                System.out.println("offset = "+infoImage.getOffset());
--                System.out.println("bitOffset = "+infoImage.getBitOffset());
--                System.out.println("format = "+infoImage.getFormat());
--            }
--        }
--
--        return infoImage;
--    }
--
--    public int getWidth(int imageIndex) throws IOException {
--        if(DEBUG) System.out.println("In getWidth()");
--
--        return getInfoImage(imageIndex).getWidth();
--    }
--
--    public int getHeight(int imageIndex) throws IOException {
--        if(DEBUG) System.out.println("In getHeight()");
--
--        return getInfoImage(imageIndex).getHeight();
--    }
--
--    public Iterator getImageTypes(int imageIndex) throws IOException {
--        if(DEBUG) System.out.println("In getImageTypes()");
--        seekToImage(imageIndex);
--
--        ArrayList types = null;
--        synchronized(imageTypes) {
--            Integer key = new Integer(imageIndex);
--            if(imageTypes.containsKey(key)) {
--                types = (ArrayList)imageTypes.get(key);
--            } else {
--                types = new ArrayList();
--
--                // Get the informational image.
--                mediaLibImage mlImage = getInfoImage(imageIndex);
--
--                ColorSpace cs;
--
--                // Add profile-based type if an ICC profile is present.
--                if(iccProfileData != null) {
--                    ICC_Profile profile =
--                        ICC_Profile.getInstance(iccProfileData);
--                    cs = new ICC_ColorSpace(profile);
--                    types.add(createImageType(mlImage, cs, bitDepth,
--                                              null, null, null, null));
--                }
--
--                // Add a standard type.
--                cs = mlImage.getFormat() == mediaLibImage.MLIB_FORMAT_CMYK ?
--                    InvertedCMYKColorSpace.getInstance() : null;
--                types.add(createImageType(mlImage, cs, bitDepth,
--                                          null, null, null, null));
--            }
--        }
--
--        return types.iterator();
--    }
--
--    public synchronized IIOMetadata getImageMetadata(int imageIndex)
--        throws IOException {
--        if(input == null) {
--            throw new IllegalStateException("input == null");
--        }
--
--        if(imageMetadata == null || imageIndex != imageMetadataIndex) {
--            seekToImage(imageIndex);
--
--            ImageInputStream stream = (ImageInputStream)input;
--            long pos = stream.getStreamPosition();
--
--            try {
--                imageMetadata = new CLibJPEGMetadata(stream);
--                imageMetadataIndex = imageIndex;
--            } catch(IIOException e) {
--                throw e;
--            } finally {
--                stream.seek(pos);
--            }
--        }
--
--        return imageMetadata;
--    }
--
--    // Override thumbnail methods.
--
--    public boolean readerSupportsThumbnails() {
--        return true;
--    }
--
--    public int getNumThumbnails(int imageIndex) throws IOException {
--        CLibJPEGMetadata metadata =
--            (CLibJPEGMetadata)getImageMetadata(imageIndex);
--        return metadata.getNumThumbnails();
--    }
--
--    public BufferedImage readThumbnail(int imageIndex,
--                                       int thumbnailIndex) throws IOException {
--        CLibJPEGMetadata metadata =
--            (CLibJPEGMetadata)getImageMetadata(imageIndex);
--        return metadata.getThumbnail(thumbnailIndex);
--    }
--
--    // Override superclass method.
--    protected void resetLocal() {
--        infoImage = null;
--        infoImageIndex = -1;
--        iccProfileData = null;
--        imageMetadata = null;
--        imageMetadataIndex = -1;
--        imageTypes.clear();
--        super.resetLocal();
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageReaderSpi.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageReaderSpi.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,205 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibJPEGImageReaderSpi.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.4 $
-- * $Date: 2006/04/24 20:53:01 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.jpeg;
--
--import java.util.Arrays;
--import java.util.Iterator;
--import java.util.List;
--import java.util.Locale;
--import javax.imageio.spi.ImageReaderSpi;
--import javax.imageio.spi.ServiceRegistry;
--import javax.imageio.stream.ImageInputStream;
--import java.io.IOException;
--import javax.imageio.ImageReader;
--import javax.imageio.IIOException;
--import com.sun.media.imageioimpl.common.PackageUtil;
--import com.sun.media.imageioimpl.common.ImageUtil;
--
--public class CLibJPEGImageReaderSpi extends ImageReaderSpi {
--
--    private static final String[] names =
--    {"jpeg", "JPEG", "jpg", "JPG", "jfif", "JFIF",
--     "jpeg-lossless", "JPEG-LOSSLESS", "jpeg-ls", "JPEG-LS"};
--
--    private static final String[] suffixes = {"jpeg", "jpg", "jfif", "jls"};
--    
--    private static final String[] MIMETypes = {"image/jpeg"};
--
--    private static final String readerClassName =
--        "com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader";
--
--    private static final String[] writerSpiNames = {
--        "com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageWriterSpi"
--    };
--
--    private boolean registered = false;
--
--    public CLibJPEGImageReaderSpi() {
--        super(PackageUtil.getVendor(),
--              PackageUtil.getVersion(),
--              names,
--              suffixes,
--              MIMETypes,
--              readerClassName,
--              STANDARD_INPUT_TYPE,
--              writerSpiNames,
--              false, // supportsStandardStreamMetadataFormat
--              null,  // nativeStreamMetadataFormatName
--              null,  // nativeStreamMetadataFormatClassName
--              null,  // extraStreamMetadataFormatNames
--              null,  // extraStreamMetadataFormatClassNames
--              true,  // supportsStandardImageMetadataFormat
--              CLibJPEGMetadata.NATIVE_FORMAT,
--              CLibJPEGMetadata.NATIVE_FORMAT_CLASS,
--              new String[] {CLibJPEGMetadata.TIFF_FORMAT},
--              new String[] {CLibJPEGMetadata.TIFF_FORMAT_CLASS});
--    }
--
--    public void onRegistration(ServiceRegistry registry,
--                               Class category) {
--        if (registered) {
--            return;
--        }
--	
--        registered = true;
--
--        // Branch as a function of codecLib availability.
--        if(!PackageUtil.isCodecLibAvailable()) {
--            // Deregister provider.
--            registry.deregisterServiceProvider(this);
--        } else {
--
--	    List list = 
--		ImageUtil.getJDKImageReaderWriterSPI(registry, "JPEG", true);
--
--	    for (int i=0; i<list.size(); i++) {
--		// Set pairwise ordering to give codecLib reader precedence
--		// over Sun core J2SE reader.
--		registry.setOrdering(category, this, list.get(i));
--	    }
--        }
--    }
--
--    public String getDescription(Locale locale) {
--	String desc = PackageUtil.getSpecificationTitle() + 
--	    " natively-accelerated JPEG Image Reader";
--	return desc;
--    }
--
--    public boolean canDecodeInput(Object source) throws IOException {
--        if (!(source instanceof ImageInputStream)) {
--            return false;
--        }
--        ImageInputStream iis = (ImageInputStream) source;
--        iis.mark();
--        // If the first two bytes are a JPEG SOI marker, it's probably
--        // a JPEG file.  If they aren't, it definitely isn't a JPEG file.
--        int byte1 = iis.read();
--        int byte2 = iis.read();
--        if ((byte1 != 0xFF) || (byte2 != 0xD8)) {
--            iis.reset();
--            return false;
--        }
--        do {
--            byte1 = iis.read();
--            byte2 = iis.read();
--            if (byte1 != 0xFF) break; // something wrong, but probably readable
--            if (byte2 == 0xDA) break; // Start of scan
--            if (byte2 == 0xC2) { // progressive mode, can't decode
--                iis.reset();
--                return false;
--            }
--            if ((byte2 >= 0xC0) && (byte2 <= 0xC3)) // not progressive, can decode
--                break;
--            int length = iis.read() << 8;
--            length += iis.read();
--            length -= 2;
--	    while (length > 0) length -= iis.skipBytes(length);
--        } while(true);
--        iis.reset();
--        return true;
--    }
--    
--    public ImageReader createReaderInstance(Object extension) 
--        throws IIOException {
--        return new CLibJPEGImageReader(this);
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageWriter.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageWriter.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,383 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibJPEGImageWriter.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.5 $
-- * $Date: 2006/04/26 01:14:14 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.jpeg;
--
--import java.awt.image.BufferedImage;
--import java.awt.image.ColorModel;
--import java.awt.image.DirectColorModel;
--import java.awt.image.IndexColorModel;
--import java.awt.image.PackedColorModel;
--import java.awt.image.Raster;
--import java.awt.image.RenderedImage;
--import java.awt.image.WritableRaster;
--import java.io.IOException;
--import java.io.OutputStream;
--import java.util.Locale;
--import javax.imageio.IIOException;
--import javax.imageio.IIOImage;
--import javax.imageio.ImageWriter;
--import javax.imageio.ImageWriteParam;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.metadata.IIOMetadata;
--import javax.imageio.spi.ImageWriterSpi;
--import javax.imageio.stream.ImageOutputStream;
--import com.sun.media.imageioimpl.common.ImageUtil;
--import com.sun.media.imageioimpl.plugins.clib.CLibImageWriter;
--import com.sun.media.imageioimpl.plugins.clib.OutputStreamAdapter;
--import com.sun.medialib.codec.jpeg.Encoder;
--import com.sun.medialib.codec.jiio.Constants;
--import com.sun.medialib.codec.jiio.mediaLibImage;
--
--final class CLibJPEGImageWriter extends CLibImageWriter {
--    private Encoder encoder;
--
--    /**
--     * Convert an IndexColorModel-based image to 3-band component RGB.
--     *
--     * @param im The source image.
--     * @throws IllegalArgumentException if the parameter is <code>null</code>.
--     * @throws IllegalArgumentException if the source does is not indexed.
--     */
--    private static BufferedImage convertTo3BandRGB(RenderedImage im) {
--        // Check parameter.
--        if(im == null) {
--            throw new IllegalArgumentException("im == null");
--        }
--
--        ColorModel cm = im.getColorModel();
--        if(!(cm instanceof IndexColorModel)) {
--            throw new IllegalArgumentException
--                ("!(im.getColorModel() instanceof IndexColorModel)");
--        }
--
--        Raster src;
--        if(im.getNumXTiles() == 1 && im.getNumYTiles() == 1) {
--            // Image is not tiled so just get a reference to the tile.
--            src = im.getTile(im.getMinTileX(), im.getMinTileY());
--
--            if (src.getWidth() != im.getWidth() ||
--                src.getHeight() != im.getHeight()) {
--                src = src.createChild(src.getMinX(), src.getMinY(),
--                                      im.getWidth(), im.getHeight(),
--                                      src.getMinX(), src.getMinY(),
--                                      null);
--            }
--        } else {
--            // Image is tiled so need to get a contiguous raster.
--            src = im.getData();
--        }
--
--        // This is probably not the most efficient approach given that
--        // the mediaLibImage will eventually need to be in component form.
--        BufferedImage dst =
--            ((IndexColorModel)cm).convertToIntDiscrete(src, false);
--
--        if(dst.getSampleModel().getNumBands() == 4) {
--            //
--            // Without copying data create a BufferedImage which has
--            // only the RGB bands, not the alpha band.
--            //
--            WritableRaster rgbaRas = dst.getRaster();
--            WritableRaster rgbRas =
--                rgbaRas.createWritableChild(0, 0,
--                                            dst.getWidth(), dst.getHeight(),
--                                            0, 0,
--                                            new int[] {0, 1, 2});
--            PackedColorModel pcm = (PackedColorModel)dst.getColorModel();
--            int bits =
--                pcm.getComponentSize(0) +
--                pcm.getComponentSize(1) +
--                pcm.getComponentSize(2);
--            DirectColorModel dcm = new DirectColorModel(bits,
--                                                        pcm.getMask(0),
--                                                        pcm.getMask(1),
--                                                        pcm.getMask(2));
--            dst = new BufferedImage(dcm, rgbRas, false, null);
--        }
--
--        return dst;
--    }
--
--    CLibJPEGImageWriter(ImageWriterSpi originatingProvider)
--        throws IOException {
--        super(originatingProvider);
--
--        try {
--            encoder = new Encoder();
--            encoder.setExtend(Encoder.JPEG_IMAGE_NONEXTENDED);
--        } catch(Throwable t) {
--            throw new IIOException("codecLib error", t);
--        }
--    }
--
--    public ImageWriteParam getDefaultWriteParam() {
--        return new CLibJPEGImageWriteParam(getLocale());
--    }
--
--    public void write(IIOMetadata streamMetadata,
--                      IIOImage image,
--                      ImageWriteParam param) throws IOException {
--        if(output == null) {
--            throw new IllegalStateException("output == null");
--        }
--
--        OutputStream stream = null;
--        if(output instanceof ImageOutputStream) {
--            stream = new OutputStreamAdapter((ImageOutputStream)output);
--        } else {
--            throw new IllegalArgumentException
--                ("!(output instanceof ImageOutputStream)");
--        }
--
--        RenderedImage renderedImage = image.getRenderedImage();
--
--        if(renderedImage.getColorModel() instanceof IndexColorModel) {
--            renderedImage = convertTo3BandRGB(renderedImage);
--        }
--
--        // Test for all.
--	ImageUtil.canEncodeImage(this, renderedImage.getColorModel(),
--                                 renderedImage.getSampleModel());
--
--        // Test for baseline.
--        int bitDepth = renderedImage.getColorModel().getComponentSize(0);
--        if((param == null ||
--            (param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT &&
--             !param.isCompressionLossless())) &&
--           bitDepth > 12) {
--            throw new IIOException
--                ("JPEG baseline encoding is limited to 12 bits: "+this);
--        }
--
--        // Set compression mode and quality from ImageWriteParam, if any.
--        if(param != null &&
--           param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) {
--            if(param.isCompressionLossless()) {
--                try {
--                    if(bitDepth >= 2 && bitDepth <= 16 && bitDepth % 8 != 0) {
--                        encoder.setDepth(bitDepth);
--                    }
--                    if(param.getCompressionType().equalsIgnoreCase
--                       (CLibJPEGImageWriteParam.LOSSLESS_COMPRESSION_TYPE)) {
--                        encoder.setMode(Encoder.JPEG_MODE_LOSSLESS);
--                    } else {
--                        encoder.setMode(Encoder.JPEG_MODE_HPLOCO);
--                    }
--                } catch(Throwable t) {
--                    throw new IIOException("codecLib error", t);
--                }
--            } else {
--                try {
--                    encoder.setMode(Encoder.JPEG_MODE_BASELINE);
--                    // XXX Q == 100 caused a core dump during testing.
--                    encoder.setQuality((int)(param.getCompressionQuality()*100));
--                } catch(Throwable t) {
--                    throw new IIOException("codecLib error", t);
--                }
--            }
--        } else {
--            try {
--                encoder.setMode(Encoder.JPEG_MODE_BASELINE);
--                encoder.setQuality(75);
--            } catch(Throwable t) {
--                throw new IIOException("codecLib error", t);
--            }
--        }
--
--        int[] supportedFormats =
--            param == null ||
--            (param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT &&
--             !param.isCompressionLossless()) ?
--            new int [] {Constants.MLIB_FORMAT_GRAYSCALE,
--                        Constants.MLIB_FORMAT_GRAYSCALE_ALPHA,
--                        Constants.MLIB_FORMAT_BGR,
--                        Constants.MLIB_FORMAT_RGB,
--                        Constants.MLIB_FORMAT_CMYK  } : // baseline
--            new int [] {Constants.MLIB_FORMAT_GRAYSCALE,
--                        Constants.MLIB_FORMAT_RGB};  // lossless & LS
--        mediaLibImage mlibImage = getMediaLibImage(renderedImage,
--                                                   param,
--                                                   false,
--                                                   supportedFormats);
--
--        try {
--            if(mlibImage.getChannels() == 2) {
--                // GRAYSCALE_ALPHA
--                encoder.setType(Encoder.JPEG_TYPE_GRAYSCALE);
--            } else if(mlibImage.getChannels() == 4) {
--                // XXX The selection of CMYK (Adobe transform 0) or
--                // YCCK (Adobe transform 2) should probably be made
--                // on the basis of image metadata passed in so this
--                // code should be modified once the writer supports
--                // image metadata. Until then select CMYK type which
--                // will generate Adobe transform 0 and non-subsampled
--                // data.
--                if(mlibImage.getFormat() == Constants.MLIB_FORMAT_CMYK) {
--                    // CMYK
--                    encoder.setType(Encoder.JPEG_TYPE_CMYK);
--                } else if(mlibImage.getFormat() ==
--                          Constants.MLIB_FORMAT_YCCK) {
--                    // YCCK
--                    encoder.setType(Encoder.JPEG_TYPE_YCCK);
--                }
--            }
--            encoder.encode(stream, mlibImage);
--        } catch(Throwable t) {
--            throw new IIOException("codecLib error", t);
--        }
--    }
--}
--
--/**
-- * This differs from the core JPEG ImageWriteParam in that:
-- *
-- * <ul>
-- * <li>compression types are: "JPEG" (standard), "JPEG-LOSSLESS"
-- * (lossless JPEG from 10918-1/ITU-T81), "JPEG-LS" (ISO 14495-1 lossless).</li>
-- * <li>compression modes are: MODE_DEFAULT and MODE_EXPLICIT and the
-- * other modes (MODE_DISABLED and MODE_COPY_FROM_METADATA) cause
-- * an UnsupportedOperationException.</li>
-- * <li>isCompressionLossless() will return true if type is NOT "JPEG".</li>
-- * </ul>
-- */
--final class CLibJPEGImageWriteParam extends ImageWriteParam {
--    private static final float DEFAULT_COMPRESSION_QUALITY = 0.75F;
--
--    static final String LOSSY_COMPRESSION_TYPE = "JPEG";
--    static final String LOSSLESS_COMPRESSION_TYPE = "JPEG-LOSSLESS";
--    static final String LS_COMPRESSION_TYPE = "JPEG-LS";
--
--    private static final String[] compressionQualityDescriptions =
--        new String[] {
--            I18N.getString("CLibJPEGImageWriteParam0"),
--            I18N.getString("CLibJPEGImageWriteParam1"),
--            I18N.getString("CLibJPEGImageWriteParam2")
--        };
--
--    CLibJPEGImageWriteParam(Locale locale) {
--        super(locale);
--
--        canWriteCompressed = true;
--        compressionMode = MODE_EXPLICIT;
--        compressionQuality = DEFAULT_COMPRESSION_QUALITY;
--        compressionType = LOSSY_COMPRESSION_TYPE;
--        compressionTypes = new String[] {LOSSY_COMPRESSION_TYPE,
--                                         LOSSLESS_COMPRESSION_TYPE,
--                                         LS_COMPRESSION_TYPE};
--    }
--
--    public String[] getCompressionQualityDescriptions() {
--        super.getCompressionQualityDescriptions(); // Performs checks.
--
--        return compressionQualityDescriptions;
--    }
--
--    public float[] getCompressionQualityValues() {
--        super.getCompressionQualityValues(); // Performs checks.
--
--        return new float[] { 0.05F,   // "Minimum useful"
--                             0.75F,   // "Visually lossless"
--                             0.95F }; // "Maximum useful"
--    }
--
--    public boolean isCompressionLossless() {
--        super.isCompressionLossless(); // Performs checks.
--
--        return !compressionType.equalsIgnoreCase(LOSSY_COMPRESSION_TYPE);
--    }
--
--    public void setCompressionMode(int mode) {
--        if(mode == MODE_DISABLED ||
--           mode == MODE_COPY_FROM_METADATA) {
--            throw new UnsupportedOperationException
--                ("mode == MODE_DISABLED || mode == MODE_COPY_FROM_METADATA");
--        }
--
--        super.setCompressionMode(mode); // This sets the instance variable.
--    }
--
--    public void unsetCompression() {
--        super.unsetCompression(); // Performs checks.
--
--        compressionQuality = DEFAULT_COMPRESSION_QUALITY;
--        compressionType = LOSSY_COMPRESSION_TYPE;
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageWriterSpi.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGImageWriterSpi.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,215 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibJPEGImageWriterSpi.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.4 $
-- * $Date: 2006/04/26 00:45:06 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.jpeg;
--
--import java.awt.image.ColorModel;
--import java.awt.image.IndexColorModel;
--import java.awt.image.SampleModel;
--import java.io.IOException;
--import java.util.List;
--import java.util.Locale;
--import javax.imageio.ImageWriter;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.metadata.IIOMetadataFormat;
--import javax.imageio.metadata.IIOMetadataFormatImpl;
--import javax.imageio.spi.ImageWriterSpi;
--import javax.imageio.spi.ServiceRegistry;
--import com.sun.media.imageioimpl.common.PackageUtil;
--import com.sun.media.imageioimpl.common.ImageUtil;
--
--/**
-- */
--public class CLibJPEGImageWriterSpi extends ImageWriterSpi {
--
--    private static final String[] names =
--    {"jpeg", "JPEG", "jpg", "JPG", "jfif", "JFIF",
--     "jpeg-lossless", "JPEG-LOSSLESS", "jpeg-ls", "JPEG-LS"};
--
--    private static final String[] suffixes = {"jpeg", "jpg", "jfif", "jls"};
--    
--    private static final String[] MIMETypes = { "image/jpeg" };
--    
--    private static final String writerClassName =
--        "com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageWriter";
--
--    private static final String[] readerSpiNames = {
--        "com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReaderSpi"
--    };
--
--    private boolean registered = false;
--
--    public CLibJPEGImageWriterSpi() {
--        super(PackageUtil.getVendor(),
--              PackageUtil.getVersion(),
--              names,
--              suffixes,
--              MIMETypes,
--              writerClassName,
--              STANDARD_OUTPUT_TYPE,
--              readerSpiNames,
--              false,
--              null, null,
--              null, null,
--              false,
--              null, null,
--              null, null);
--    }
--
--    public void onRegistration(ServiceRegistry registry,
--                               Class category) {
--        if (registered) {
--            return;
--        }
--	
--        registered = true;
--
--        // Branch as a function of codecLib availability.
--        if(!PackageUtil.isCodecLibAvailable()) {
--            // Deregister provider.
--            registry.deregisterServiceProvider(this);
--        } else {
--
--	    List list = 
--		ImageUtil.getJDKImageReaderWriterSPI(registry, "JPEG", false);
--
--	    for (int i=0; i<list.size(); i++) {
--		// Set pairwise ordering to give codecLib writer precedence
--		// over Sun core J2SE writer.
--		registry.setOrdering(category, this, list.get(i));
--	    }
--        }
--    }
--
--    public boolean canEncodeImage(ImageTypeSpecifier type) {
--        ColorModel colorModel = type.getColorModel();
--
--        if (colorModel instanceof IndexColorModel) {
--            // No need to check further: writer converts to 8-8-8 RGB.
--            return true;
--        }
--
--        SampleModel sampleModel = type.getSampleModel();
--
--        // Ensure all channels have the same bit depth
--        int bitDepth;
--        if(colorModel != null) {
--            int[] componentSize = colorModel.getComponentSize(); 
--            bitDepth = componentSize[0];
--            for (int i = 1; i < componentSize.length; i++) {
--                if (componentSize[i] != bitDepth) {
--                    return false;
--                }
--            }
--        } else {
--            int[] sampleSize = sampleModel.getSampleSize(); 
--            bitDepth = sampleSize[0];
--            for (int i = 1; i < sampleSize.length; i++) {
--                if (sampleSize[i] != bitDepth) {
--                    return false;
--                }
--            }
--        }
--
--        // Ensure bitDepth is no more than 16
--        if (bitDepth > 16) {
--            return false;
--        }
--
--        // Check number of bands.
--        int numBands = sampleModel.getNumBands();
--        if (numBands < 1 || numBands > 4) {
--            return false;
--        }
--
--        return true;
--    }
--
--    public String getDescription(Locale locale) {
--	String desc = PackageUtil.getSpecificationTitle() + 
--	    " natively-accelerated JPEG Image Writer";
--	return desc;
--    }
--
--    public ImageWriter createWriterInstance(Object extension)
--        throws IOException {
--        return new CLibJPEGImageWriter(this);
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGMetadata.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg/CLibJPEGMetadata.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,1695 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibJPEGMetadata.java,v $
-- *
-- * 
-- * Copyright (c) 2006 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.7 $
-- * $Date: 2007/08/28 18:45:53 $
-- * $State: Exp $
-- */
--
--package com.sun.media.imageioimpl.plugins.jpeg;
--
--import java.awt.Dimension;
--import java.awt.Transparency;
--import java.awt.color.ColorSpace;
--import java.awt.color.ICC_Profile;
--import java.awt.image.BufferedImage;
--import java.awt.image.ColorModel;
--import java.awt.image.ComponentColorModel;
--import java.awt.image.DataBuffer;
--import java.awt.image.DataBufferByte;
--import java.awt.image.IndexColorModel;
--import java.awt.image.Raster;
--import java.awt.image.RenderedImage;
--import java.awt.image.SampleModel;
--import java.awt.image.WritableRaster;
--import java.io.ByteArrayInputStream;
--import java.io.EOFException;
--import java.io.IOException;
--import java.io.UnsupportedEncodingException;
--import java.nio.ByteOrder;
--import java.util.ArrayList;
--import java.util.Arrays;
--import java.util.Iterator;
--import java.util.List;
--import java.util.Map;
--import java.util.SortedMap;
--import java.util.TreeMap;
--import javax.imageio.IIOException;
--import javax.imageio.IIOImage;
--import javax.imageio.ImageIO;
--import javax.imageio.ImageReader;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.metadata.IIOMetadata;
--import javax.imageio.metadata.IIOMetadataFormatImpl;
--import javax.imageio.metadata.IIOMetadataNode;
--import javax.imageio.metadata.IIOInvalidTreeException;
--import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
--import javax.imageio.plugins.jpeg.JPEGQTable;
--import javax.imageio.stream.ImageInputStream;
--import javax.imageio.stream.MemoryCacheImageInputStream;
--import org.w3c.dom.Node;
--import org.w3c.dom.NodeList;
--import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet;
--import com.sun.media.imageio.plugins.tiff.EXIFGPSTagSet;
--import com.sun.media.imageio.plugins.tiff.EXIFInteroperabilityTagSet;
--import com.sun.media.imageio.plugins.tiff.EXIFParentTIFFTagSet;
--import com.sun.media.imageio.plugins.tiff.EXIFTIFFTagSet;
--import com.sun.media.imageio.plugins.tiff.TIFFDirectory;
--import com.sun.media.imageio.plugins.tiff.TIFFField;
--import com.sun.media.imageio.plugins.tiff.TIFFTag;
--import com.sun.media.imageio.plugins.tiff.TIFFTagSet;
--
--public class CLibJPEGMetadata extends IIOMetadata {
--    // --- Constants ---
--
--    static final String NATIVE_FORMAT = "javax_imageio_jpeg_image_1.0";
--    // XXX Reference to a non-API J2SE class:
--    static final String NATIVE_FORMAT_CLASS =
--        "com.sun.imageio.plugins.jpeg.JPEGImageMetadataFormat";
--
--    static final String TIFF_FORMAT =
--        "com_sun_media_imageio_plugins_tiff_image_1.0";
--    static final String TIFF_FORMAT_CLASS =
--        "com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadataFormat";
--
--    // Marker codes from J2SE in numerically increasing order.
--
--    /** For temporary use in arithmetic coding */
--    static final int TEM = 0x01;
--
--    // Codes 0x02 - 0xBF are reserved
--
--    // SOF markers for Nondifferential Huffman coding
--    /** Baseline DCT */
--    static final int SOF0 = 0xC0;
--    /** Extended Sequential DCT */
--    static final int SOF1 = 0xC1;
--    /** Progressive DCT */
--    static final int SOF2 = 0xC2;
--    /** Lossless Sequential */
--    static final int SOF3 = 0xC3;
--
--    /** Define Huffman Tables */
--    static final int DHT = 0xC4;    
--
--    // SOF markers for Differential Huffman coding
--    /** Differential Sequential DCT */
--    static final int SOF5 = 0xC5;
--    /** Differential Progressive DCT */
--    static final int SOF6 = 0xC6;
--    /** Differential Lossless */
--    static final int SOF7 = 0xC7;
--
--    /** Reserved for JPEG extensions */
--    static final int JPG = 0xC8;
--
--    // SOF markers for Nondifferential arithmetic coding
--    /** Extended Sequential DCT, Arithmetic coding */
--    static final int SOF9 = 0xC9;
--    /** Progressive DCT, Arithmetic coding */
--    static final int SOF10 = 0xCA;
--    /** Lossless Sequential, Arithmetic coding */
--    static final int SOF11 = 0xCB;
--
--    /** Define Arithmetic conditioning tables */
--    static final int DAC = 0xCC;
--
--    // SOF markers for Differential arithmetic coding
--    /** Differential Sequential DCT, Arithmetic coding */
--    static final int SOF13 = 0xCD;
--    /** Differential Progressive DCT, Arithmetic coding */
--    static final int SOF14 = 0xCE;
--    /** Differential Lossless, Arithmetic coding */
--    static final int SOF15 = 0xCF;
--
--    // Restart Markers
--    static final int RST0 = 0xD0;
--    static final int RST1 = 0xD1;
--    static final int RST2 = 0xD2;
--    static final int RST3 = 0xD3;
--    static final int RST4 = 0xD4;
--    static final int RST5 = 0xD5;
--    static final int RST6 = 0xD6;
--    static final int RST7 = 0xD7;
--    /** Number of restart markers */
--    static final int RESTART_RANGE = 8;
--
--    /** Start of Image */
--    static final int SOI = 0xD8;
--    /** End of Image */
--    static final int EOI = 0xD9;
--    /** Start of Scan */
--    static final int SOS = 0xDA;
--
--    /** Define Quantisation Tables */
--    static final int DQT = 0xDB;
--
--    /** Define Number of lines */
--    static final int DNL = 0xDC;
--
--    /** Define Restart Interval */
--    static final int DRI = 0xDD;
--
--    /** Define Heirarchical progression */
--    static final int DHP = 0xDE;
--
--    /** Expand reference image(s) */
--    static final int EXP = 0xDF;
--
--    // Application markers
--    /** APP0 used by JFIF */
--    static final int APP0 = 0xE0;
--    static final int APP1 = 0xE1;
--    static final int APP2 = 0xE2;
--    static final int APP3 = 0xE3;
--    static final int APP4 = 0xE4;
--    static final int APP5 = 0xE5;
--    static final int APP6 = 0xE6;
--    static final int APP7 = 0xE7;
--    static final int APP8 = 0xE8;
--    static final int APP9 = 0xE9;
--    static final int APP10 = 0xEA;
--    static final int APP11 = 0xEB;
--    static final int APP12 = 0xEC;
--    static final int APP13 = 0xED;
--    /** APP14 used by Adobe */
--    static final int APP14 = 0xEE;
--    static final int APP15 = 0xEF;
--
--    // codes 0xF0 to 0xFD are reserved
--
--    /** Comment marker */
--    static final int COM = 0xFE;
--
--    // Marker codes for JPEG-LS
--
--    /** JPEG-LS SOF marker */
--    // This was SOF48 in an earlier revision of the JPEG-LS specification.
--    // "55" is the numerical value of SOF55 - SOF0 (= 247 - 192).
--    static final int SOF55 = 0xF7;
--
--    /** JPEG-LS parameters */
--    static final int LSE = 0xF2;
--
--    // Min and max APPn codes.
--    static final int APPN_MIN = APP0;
--    static final int APPN_MAX = APP15;
--
--    // Min and max contiguous SOFn codes.
--    static final int SOFN_MIN = SOF0;
--    static final int SOFN_MAX = SOF15;
--
--    // Min and Max RSTn codes.
--    static final int RST_MIN = RST0;
--    static final int RST_MAX = RST7;
--
--    // Specific segment types defined as (code << 8) | X.
--    static final int APP0_JFIF   = (APP0 << 8) | 0;
--    static final int APP0_JFXX   = (APP0 << 8) | 1;
--    static final int APP1_EXIF   = (APP1 << 8) | 0;
--    static final int APP2_ICC    = (APP2 << 8) | 0;
--    static final int APP14_ADOBE = (APP14 << 8) | 0;
--    static final int UNKNOWN_MARKER = 0xffff;
--    static final int SOF_MARKER = (SOF0 << 8) | 0;
--
--    // Resolution unit types.
--    static final int JFIF_RESUNITS_ASPECT = 0;
--    static final int JFIF_RESUNITS_DPI = 1;
--    static final int JFIF_RESUNITS_DPC = 2;
--
--    // Thumbnail types
--    static final int THUMBNAIL_JPEG = 0x10;
--    static final int THUMBNAIL_PALETTE = 0x11;
--    static final int THUMBNAIL_RGB = 0x12;
--
--    // Adobe transform type.
--    static final int ADOBE_TRANSFORM_UNKNOWN = 0;
--    static final int ADOBE_TRANSFORM_YCC = 1;
--    static final int ADOBE_TRANSFORM_YCCK = 2;
--
--    // Zig-zag to natural re-ordering array.
--    static final int [] zigzag = {
--        0,  1,  5,  6, 14, 15, 27, 28,
--        2,  4,  7, 13, 16, 26, 29, 42,
--        3,  8, 12, 17, 25, 30, 41, 43,
--        9, 11, 18, 24, 31, 40, 44, 53,
--        10, 19, 23, 32, 39, 45, 52, 54,
--        20, 22, 33, 38, 46, 51, 55, 60,
--        21, 34, 37, 47, 50, 56, 59, 61,
--        35, 36, 48, 49, 57, 58, 62, 63
--    };
--
--    // --- Static methods ---
--
--    private static IIOImage getThumbnail(ImageInputStream stream, int len,
--                                         int thumbnailType, int w, int h)
--        throws IOException {
--
--        IIOImage result;
--
--        long startPos = stream.getStreamPosition();
--
--        if(thumbnailType == THUMBNAIL_JPEG) {
--            Iterator readers = ImageIO.getImageReaders(stream);
--            if(readers == null || !readers.hasNext()) return null;
--            ImageReader reader = (ImageReader)readers.next();
--            reader.setInput(stream);
--            BufferedImage image = reader.read(0, null);
--            IIOMetadata metadata = null;
--            try {
--                metadata = reader.getImageMetadata(0);
--            } catch(Exception e) {
--                // Ignore it
--            }
--            result = new IIOImage(image, null, metadata);
--        } else {
--            int numBands;
--            ColorModel cm;
--            if(thumbnailType == THUMBNAIL_PALETTE) {
--                if(len < 768 + w*h) {
--                    return null;
--                }
--
--                numBands = 1;
--
--                byte[] palette = new byte[768];
--                stream.readFully(palette);
--                byte[] r = new byte[256];
--                byte[] g = new byte[256];
--                byte[] b = new byte[256];
--                for(int i = 0, off = 0; i < 256; i++) {
--                    r[i] = palette[off++];
--                    g[i] = palette[off++];
--                    b[i] = palette[off++];
--                }
--
--                cm = new IndexColorModel(8, 256, r, g, b);
--            } else {
--                if(len < 3*w*h) {
--                    return null;
--                }
--
--                numBands = 3;
--
--                ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
--                cm = new ComponentColorModel(cs, false, false,
--                                             Transparency.OPAQUE,
--                                             DataBuffer.TYPE_BYTE);
--            }
--
--            byte[] data = new byte[w*h*numBands];
--            stream.readFully(data);
--            DataBufferByte db = new DataBufferByte(data, data.length);
--            WritableRaster wr =
--                Raster.createInterleavedRaster(db, w, h, w*numBands, numBands,
--                                               new int[] {0, 1, 2}, null);
--            BufferedImage image = new BufferedImage(cm, wr, false, null);
--            result = new IIOImage(image, null, null);
--        }
--
--        stream.seek(startPos + len);
--
--        return result;
--    }
--
--    // --- Instance variables ---
--
--    /** Whether the object may be edited. */
--    private boolean isReadOnly = true;
--
--    // APP0 JFIF marker segment parameters.
--    boolean app0JFIFPresent;
--    int majorVersion = 1;
--    int minorVersion = 2;
--    int resUnits; // (0 = aspect ratio; 1 = dots/inch; 2 = dots/cm)
--    int Xdensity = 1;
--    int Ydensity = 1;
--    int thumbWidth = 0;
--    int thumbHeight = 0;
--    BufferedImage jfifThumbnail;
--
--    // APP0 JFIF thumbnail(s).
--    boolean app0JFXXPresent;
--    List extensionCodes; // Integers 0x10, 0x11, 0x12
--    List jfxxThumbnails; // IIOImages
--
--    // APP2 ICC_PROFILE marker segment parameters.
--    boolean app2ICCPresent;
--    ICC_Profile profile = null;
--
--    // DQT marker segment parameters.
--    boolean dqtPresent;
--    List qtables; // Each element is a List of QTables
--
--    // DHT marker segment parameters.
--    boolean dhtPresent;
--    List htables; // Each element is a List of HuffmanTables
--
--    // DRI marker segment parameters.
--    boolean driPresent;
--    int driInterval;
--
--    // COM marker segment parameters.
--    boolean comPresent;
--    List comments; // byte[]s
--
--    // Unknown marker segment parameters.
--    boolean unknownPresent;
--    List markerTags; // Integers
--    List unknownData; // byte[] (NB: 'length' parameter is array length)
--
--    // APP14 Adobe marker segment parameters.
--    boolean app14AdobePresent;
--    int version = 100;
--    int flags0 = 0;
--    int flags1 = 0;
--    int transform; // 0 = Unknown, 1 = YCbCr, 2 = YCCK
--
--    // SOF marker segment parameters.
--    boolean sofPresent;
--    int sofProcess;
--    int samplePrecision = 8;
--    int numLines;
--    int samplesPerLine;
--    int numFrameComponents;
--    int[] componentId;
--    int[] hSamplingFactor;
--    int[] vSamplingFactor;
--    int[] qtableSelector;
--
--    // SOS marker segment parameters.
--    boolean sosPresent;
--    int numScanComponents;
--    int[] componentSelector;
--    int[] dcHuffTable;
--    int[] acHuffTable;
--    int startSpectralSelection;
--    int endSpectralSelection;
--    int approxHigh;
--    int approxLow;
--
--    // Embedded TIFF stream from EXIF segment.
--    byte[] exifData = null;
--
--    /** Marker codes in the order encountered. */
--    private List markers = null; // List of Integer
--
--    // Standard metadata variables.
--    private boolean hasAlpha = false;
--
--    // Agregated list of thumbnails: JFIF > JFXX > EXIF.
--    private boolean thumbnailsInitialized = false;
--    private List thumbnails = new ArrayList();
--
--    CLibJPEGMetadata() {
--        super(true, NATIVE_FORMAT, NATIVE_FORMAT_CLASS,
--              new String[] {TIFF_FORMAT}, new String[] {TIFF_FORMAT_CLASS});
--              
--        this.isReadOnly = isReadOnly;
--    }
--
--    CLibJPEGMetadata(ImageInputStream stream)
--        throws IIOException {
--        this();
--
--        try {
--            initializeFromStream(stream);
--        } catch(IOException e) {
--            throw new IIOException("Cannot initialize JPEG metadata!", e);
--        }
--    }
--
--    private class QTable {
--        private static final int QTABLE_SIZE = 64;
--
--        int elementPrecision;
--        int tableID;
--        JPEGQTable table;
--
--        int length;
--
--        QTable(ImageInputStream stream) throws IOException {
--            elementPrecision = (int)stream.readBits(4);
--            tableID = (int)stream.readBits(4);
--            byte[] tmp = new byte[QTABLE_SIZE];
--            stream.readFully(tmp);
--            int[] data = new int[QTABLE_SIZE];
--            for (int i = 0; i < QTABLE_SIZE; i++) {
--                data[i] = tmp[zigzag[i]] & 0xff;
--            }
--            table = new JPEGQTable(data);
--            length = data.length + 1;
--        }
--    }
--
--    private class HuffmanTable {
--        private static final int NUM_LENGTHS = 16;
--
--        int tableClass;
--        int tableID;
--        JPEGHuffmanTable table;
--
--        int length;
--
--        HuffmanTable(ImageInputStream stream) throws IOException {
--            tableClass = (int)stream.readBits(4);
--            tableID = (int)stream.readBits(4);
--            short[] lengths = new short[NUM_LENGTHS];
--            for (int i = 0; i < NUM_LENGTHS; i++) {
--                lengths[i] = (short)stream.read();
--            }
--            int numValues = 0;
--            for (int i = 0; i < NUM_LENGTHS; i++) {
--                numValues += lengths[i];
--            }
--            short[] values = new short[numValues];
--            for (int i = 0; i < numValues; i++) {
--                values[i] = (short)stream.read();
--            }
--            table = new JPEGHuffmanTable(lengths, values);
--
--            length = 1 + NUM_LENGTHS + values.length;
--        }
--    }
--
--    private synchronized void initializeFromStream(ImageInputStream iis)
--        throws IOException {
--        iis.mark();
--        iis.setByteOrder(ByteOrder.BIG_ENDIAN);
--
--        markers = new ArrayList();
--
--        boolean isICCProfileValid = true;
--        int numICCProfileChunks = 0;
--        long[] iccProfileChunkOffsets = null;
--        int[] iccProfileChunkLengths = null;
--
--        while(true) {
--            try {
--                // 0xff denotes a potential marker.
--                if(iis.read() == 0xff) {
--                    // Get next byte.
--                    int code = iis.read();
--
--                    // Is a marker if and only if code not in {0x00, 0xff}.
--                    // Continue to next marker if this is not a marker or if
--                    // it is an empty marker.
--                    if(code == 0x00 || code == 0xff ||
--                       code == SOI || code == TEM ||
--                       (code >= RST_MIN && code <= RST_MAX)) {
--                        continue;
--                    }
--
--                    // If at the end, quit.
--                    if(code == EOI) {
--                        break;
--                    }
--
--                    // Get the content length.
--                    int dataLength = iis.readUnsignedShort() - 2;
--
--                    if(APPN_MIN <= code && code <= APPN_MAX) {
--                        long pos = iis.getStreamPosition();
--                        boolean appnAdded = false;
--
--                        switch(code) {
--                        case APP0:
--                            if(dataLength >= 5) {
--                                byte[] b = new byte[5];
--                                iis.readFully(b);
--                                String id = new String(b);
--                                if(id.startsWith("JFIF") &&
--                                   !app0JFIFPresent) {
--                                    app0JFIFPresent = true;
--                                    markers.add(new Integer(APP0_JFIF));
--                                    majorVersion = iis.read();
--                                    minorVersion = iis.read();
--                                    resUnits = iis.read();
--                                    Xdensity = iis.readUnsignedShort();
--                                    Ydensity = iis.readUnsignedShort();
--                                    thumbWidth = iis.read();
--                                    thumbHeight = iis.read();
--                                    if(thumbWidth > 0 && thumbHeight > 0) {
--                                        IIOImage imiio =
--                                            getThumbnail(iis, dataLength - 14,
--                                                         THUMBNAIL_RGB,
--                                                         thumbWidth,
--                                                         thumbHeight);
--                                        if(imiio != null) {
--                                            jfifThumbnail = (BufferedImage)
--                                                imiio.getRenderedImage();
--                                        }
--                                    }
--                                    appnAdded = true;
--                                } else if(id.startsWith("JFXX")) {
--                                    if(!app0JFXXPresent) {
--                                        extensionCodes = new ArrayList(1);
--                                        jfxxThumbnails = new ArrayList(1);
--                                        app0JFXXPresent = true;
--                                    }
--                                    markers.add(new Integer(APP0_JFXX));
--                                    int extCode = iis.read();
--                                    extensionCodes.add(new Integer(extCode));
--                                    int w = 0, h = 0, offset = 6;
--                                    if(extCode != THUMBNAIL_JPEG) {
--                                        w = iis.read();
--                                        h = iis.read();
--                                        offset += 2;
--                                    }
--                                    IIOImage imiio =
--                                        getThumbnail(iis, dataLength - offset,
--                                                     extCode, w, h);
--                                    if(imiio != null) {
--                                        jfxxThumbnails.add(imiio);
--                                    }
--                                    appnAdded = true;
--                                }
--                            }
--                            break;
--                        case APP1:
--                            if(dataLength >= 6) {
--                                byte[] b = new byte[6];
--                                iis.readFully(b);
--                                if(b[0] == (byte)'E' &&
--                                   b[1] == (byte)'x' &&
--                                   b[2] == (byte)'i' &&
--                                   b[3] == (byte)'f' &&
--                                   b[4] == (byte)0 &&
--                                   b[5] == (byte)0) {
--                                    exifData = new byte[dataLength - 6];
--                                    iis.readFully(exifData);
--                                }
--                            }
--                        case APP2:
--                            if(dataLength >= 12) {
--                                byte[] b = new byte[12];
--                                iis.readFully(b);
--                                String id = new String(b);
--                                if(id.startsWith("ICC_PROFILE")) {
--                                    if(!isICCProfileValid) {
--                                        iis.skipBytes(dataLength - 12);
--                                        continue;
--                                    }
--
--                                    int chunkNum = iis.read();
--                                    int numChunks = iis.read();
--                                    if(numChunks == 0 ||
--                                       chunkNum == 0 ||
--                                       chunkNum > numChunks ||
--                                       (app2ICCPresent &&
--                                        (numChunks != numICCProfileChunks ||
--                                         iccProfileChunkOffsets[chunkNum]
--                                         != 0L))) {
--                                        isICCProfileValid = false;
--                                        iis.skipBytes(dataLength - 14);
--                                        continue;
--                                    }
--
--                                    if(!app2ICCPresent) {
--                                        app2ICCPresent = true;
--                                        // Only flag one marker even though
--                                        // multiple may be present.
--                                        markers.add(new Integer(APP2_ICC));
--
--                                        numICCProfileChunks = numChunks;
--
--                                        if(numChunks == 1) {
--                                            b = new byte[dataLength - 14];
--                                            iis.readFully(b);
--                                            profile =
--                                                ICC_Profile.getInstance(b);
--                                        } else {
--                                            iccProfileChunkOffsets =
--                                                new long[numChunks + 1];
--                                            iccProfileChunkLengths =
--                                                new int[numChunks + 1];
--                                            iccProfileChunkOffsets[chunkNum] =
--                                                iis.getStreamPosition();
--                                            iccProfileChunkLengths[chunkNum] =
--                                                dataLength - 14;
--                                            iis.skipBytes(dataLength - 14);
--                                        }
--                                    } else {
--                                        iccProfileChunkOffsets[chunkNum] =
--                                            iis.getStreamPosition();
--                                        iccProfileChunkLengths[chunkNum] =
--                                            dataLength - 14;
--                                        iis.skipBytes(dataLength - 14);
--                                    }
--
--                                    appnAdded = true;
--                                }
--                            }
--                            break;
--                        case APP14:
--                            if(dataLength >= 5) {
--                                byte[] b = new byte[5];
--                                iis.readFully(b);
--                                String id = new String(b);
--                                if(id.startsWith("Adobe") &&
--                                   !app14AdobePresent) { // Adobe segment
--                                    app14AdobePresent = true;
--                                    markers.add(new Integer(APP14_ADOBE));
--                                    version = iis.readUnsignedShort();
--                                    flags0 = iis.readUnsignedShort();
--                                    flags1 = iis.readUnsignedShort();
--                                    transform = iis.read();
--                                    iis.skipBytes(dataLength - 12);
--                                    appnAdded = true;
--                                }
--                            }
--                            break;
--                        default:
--                            appnAdded = false;
--                            break;
--                        }
--
--                        if(!appnAdded) {
--                            iis.seek(pos);
--                            addUnknownMarkerSegment(iis, code, dataLength);
--                        }
--                    } else if(code == DQT) {
--                        if(!dqtPresent) {
--                            dqtPresent = true;
--                            qtables = new ArrayList(1);
--                        }
--                        markers.add(new Integer(DQT));
--                        List l = new ArrayList(1);
--                        do {
--                            QTable t = new QTable(iis);
--                            l.add(t);
--                            dataLength -= t.length;
--                        } while(dataLength > 0);
--                        qtables.add(l);
--                    } else if(code == DHT) {
--                        if(!dhtPresent) {
--                            dhtPresent = true;
--                            htables = new ArrayList(1);
--                        }
--                        markers.add(new Integer(DHT));
--                        List l = new ArrayList(1);
--                        do {
--                            HuffmanTable t = new HuffmanTable(iis);
--                            l.add(t);
--                            dataLength -= t.length;
--                        } while(dataLength > 0);
--                        htables.add(l);
--                    } else if(code == DRI) {
--                        if(!driPresent) {
--                            driPresent = true;
--                        }
--                        markers.add(new Integer(DRI));
--                        driInterval = iis.readUnsignedShort();
--                    } else if(code == COM) {
--                        if(!comPresent) {
--                            comPresent = true;
--                            comments = new ArrayList(1);
--                        }
--                        markers.add(new Integer(COM));
--                        byte[] b = new byte[dataLength];
--                        iis.readFully(b);
--                        comments.add(b);
--                    } else if((code >= SOFN_MIN && code <= SOFN_MAX) ||
--                              code == SOF55) { // SOFn
--                        if(!sofPresent) {
--                            sofPresent = true;
--                            sofProcess = code - SOFN_MIN;
--                            samplePrecision = iis.read();
--                            numLines = iis.readUnsignedShort();
--                            samplesPerLine = iis.readUnsignedShort();
--                            numFrameComponents = iis.read();
--                            componentId = new int[numFrameComponents];
--                            hSamplingFactor = new int[numFrameComponents];
--                            vSamplingFactor = new int[numFrameComponents];
--                            qtableSelector = new int[numFrameComponents];
--                            for(int i = 0; i < numFrameComponents; i++) {
--                                componentId[i] = iis.read();
--                                hSamplingFactor[i] = (int)iis.readBits(4);
--                                vSamplingFactor[i] = (int)iis.readBits(4);
--                                qtableSelector[i] = iis.read();
--                            }
--                            markers.add(new Integer(SOF_MARKER));
--                        }
--                    } else if(code == SOS) {
--                        if(!sosPresent) {
--                            sosPresent = true;
--                            numScanComponents = iis.read();
--                            componentSelector = new int[numScanComponents];
--                            dcHuffTable = new int[numScanComponents];
--                            acHuffTable = new int[numScanComponents];
--                            for(int i = 0; i < numScanComponents; i++) {
--                                componentSelector[i] = iis.read();
--                                dcHuffTable[i] = (int)iis.readBits(4);
--                                acHuffTable[i] = (int)iis.readBits(4);
--                            }
--                            startSpectralSelection = iis.read();
--                            endSpectralSelection = iis.read();
--                            approxHigh = (int)iis.readBits(4);
--                            approxLow = (int)iis.readBits(4);
--                            markers.add(new Integer(SOS));
--                        }
--                        break;
--                    } else { // Any other marker
--                        addUnknownMarkerSegment(iis, code, dataLength);
--                    }
--                }
--            } catch(EOFException eofe) {
--                // XXX Should this be caught?
--                break;
--            }
--        }
--
--        if(app2ICCPresent && isICCProfileValid && profile == null) {
--            int profileDataLength = 0;
--            for(int i = 1; i <= numICCProfileChunks; i++) {
--                if(iccProfileChunkOffsets[i] == 0L) {
--                    isICCProfileValid = false;
--                    break;
--                }
--                profileDataLength += iccProfileChunkLengths[i];
--            }
--
--            if(isICCProfileValid) {
--                byte[] b = new byte[profileDataLength];
--                int off = 0;
--                for(int i = 1; i <= numICCProfileChunks; i++) {
--                    iis.seek(iccProfileChunkOffsets[i]);
--                    iis.read(b, off, iccProfileChunkLengths[i]);
--                    off += iccProfileChunkLengths[i];
--                }
--
--                profile = ICC_Profile.getInstance(b);
--            }
--        }
--
--        iis.reset();
--    }
--
--    private void addUnknownMarkerSegment(ImageInputStream stream,
--                                         int code, int len)
--        throws IOException {
--        if(!unknownPresent) {
--            unknownPresent = true;
--            markerTags = new ArrayList(1);
--            unknownData = new ArrayList(1);
--        }
--        markerTags.add(new Integer(code));
--        byte[] b = new byte[len];
--        stream.readFully(b);
--        unknownData.add(b);
--        markers.add(new Integer(UNKNOWN_MARKER));
--    }
--
--    public boolean isReadOnly() {
--        return isReadOnly;
--    }
--
--    public Node getAsTree(String formatName) {
--        if (formatName.equals(nativeMetadataFormatName)) {
--            return getNativeTree();
--        } else if (formatName.equals
--                   (IIOMetadataFormatImpl.standardMetadataFormatName)) {
--            return getStandardTree();
--        } else if(formatName.equals(TIFF_FORMAT)) {
--            return getTIFFTree();
--        } else {
--            throw new IllegalArgumentException("Not a recognized format!");
--        }
--    }
--
--    public void mergeTree(String formatName, Node root)
--        throws IIOInvalidTreeException {
--        if(isReadOnly) {
--            throw new IllegalStateException("isReadOnly() == true!");
--        }
--    }
--
--    public void reset() {
--        if(isReadOnly) {
--            throw new IllegalStateException("isReadOnly() == true!");
--        }
--    }
--
--    // Native tree method.
--
--    private Node getNativeTree() {
--        int jfxxIndex = 0;
--        int dqtIndex = 0;
--        int dhtIndex = 0;
--        int comIndex = 0;
--        int unknownIndex = 0;
--
--        IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName);
--
--        IIOMetadataNode JPEGvariety = new IIOMetadataNode("JPEGvariety");
--        root.appendChild(JPEGvariety);
--
--        IIOMetadataNode markerSequence = new IIOMetadataNode("markerSequence");
--        root.appendChild(markerSequence);
--
--        IIOMetadataNode app0JFIF = null;
--        if(app0JFIFPresent || app0JFXXPresent || app2ICCPresent) {
--            app0JFIF = new IIOMetadataNode("app0JFIF");
--            app0JFIF.setAttribute("majorVersion",
--                                  Integer.toString(majorVersion));
--            app0JFIF.setAttribute("minorVersion",
--                                  Integer.toString(minorVersion));
--            app0JFIF.setAttribute("resUnits",
--                                  Integer.toString(resUnits));
--            app0JFIF.setAttribute("Xdensity",
--                                  Integer.toString(Xdensity));
--            app0JFIF.setAttribute("Ydensity",
--                                  Integer.toString(Ydensity));
--            app0JFIF.setAttribute("thumbWidth",
--                                  Integer.toString(thumbWidth));
--            app0JFIF.setAttribute("thumbHeight",
--                                  Integer.toString(thumbHeight));
--            JPEGvariety.appendChild(app0JFIF);
--        }
--
--        IIOMetadataNode JFXX = null;
--        if(app0JFXXPresent) {
--            JFXX = new IIOMetadataNode("JFXX");
--            app0JFIF.appendChild(JFXX);
--        }
--
--        Iterator markerIter = markers.iterator();
--        while(markerIter.hasNext()) {
--            int marker = ((Integer)markerIter.next()).intValue();
--            switch(marker) {
--            case APP0_JFIF:
--                // Do nothing: already handled above.
--                break;
--            case APP0_JFXX:
--                IIOMetadataNode app0JFXX = new IIOMetadataNode("app0JFXX");
--                Integer extensionCode = (Integer)extensionCodes.get(jfxxIndex);
--                app0JFXX.setAttribute("extensionCode",
--                                      extensionCode.toString());
--                IIOMetadataNode JFIFthumb = null;
--                switch(extensionCode.intValue()) {
--                case THUMBNAIL_JPEG:
--                    JFIFthumb = new IIOMetadataNode("JFIFthumbJPEG");
--                    break;
--                case THUMBNAIL_PALETTE:
--                    JFIFthumb = new IIOMetadataNode("JFIFthumbPalette");
--                    break;
--                case THUMBNAIL_RGB:
--                    JFIFthumb = new IIOMetadataNode("JFIFthumbRGB");
--                    break;
--                default:
--                    // No JFIFthumb node will be appended.
--                }
--                if(JFIFthumb != null) {
--                    IIOImage img = (IIOImage)jfxxThumbnails.get(jfxxIndex++);
--                    if(extensionCode.intValue() == THUMBNAIL_JPEG) {
--                        IIOMetadata thumbMetadata = img.getMetadata();
--                        if(thumbMetadata != null) {
--                            Node thumbTree =
--                                thumbMetadata.getAsTree(nativeMetadataFormatName);
--                            if(thumbTree instanceof IIOMetadataNode) {
--                                IIOMetadataNode elt =
--                                    (IIOMetadataNode)thumbTree;
--                                NodeList elts =
--                                    elt.getElementsByTagName("markerSequence");
--                                if(elts.getLength() > 0) {
--                                    JFIFthumb.appendChild(elts.item(0));
--                                }
--                            }
--                        }
--                    } else {
--                        BufferedImage thumb =
--                            (BufferedImage)img.getRenderedImage();
--                        JFIFthumb.setAttribute("thumbWidth",
--                                               Integer.toString(thumb.getWidth()));
--                        JFIFthumb.setAttribute("thumbHeight",
--                                               Integer.toString(thumb.getHeight()));
--                    }
--                    // Add thumbnail as a user object even though not in
--                    // metadata specification.
--                    JFIFthumb.setUserObject(img);
--                    app0JFXX.appendChild(JFIFthumb);
--                }
--                JFXX.appendChild(app0JFXX);
--                break;
--            case APP2_ICC:
--                IIOMetadataNode app2ICC = new IIOMetadataNode("app2ICC");
--                app2ICC.setUserObject(profile);
--                app0JFIF.appendChild(app2ICC);
--                break;
--            case DQT:
--                IIOMetadataNode dqt = new IIOMetadataNode("dqt");
--                List tables = (List)qtables.get(dqtIndex++);
--                int numTables = tables.size();
--                for(int j = 0; j < numTables; j++) {
--                    IIOMetadataNode dqtable = new IIOMetadataNode("dqtable");
--                    QTable t = (QTable)tables.get(j);
--                    dqtable.setAttribute("elementPrecision",
--                                         Integer.toString(t.elementPrecision));
--                    dqtable.setAttribute("qtableId",
--                                         Integer.toString(t.tableID));
--                    dqtable.setUserObject(t.table);
--                    dqt.appendChild(dqtable);                    
--                }
--                markerSequence.appendChild(dqt);
--                break;
--            case DHT:
--                IIOMetadataNode dht = new IIOMetadataNode("dht");
--                tables = (List)htables.get(dhtIndex++);
--                numTables = tables.size();
--                for(int j = 0; j < numTables; j++) {
--                    IIOMetadataNode dhtable = new IIOMetadataNode("dhtable");
--                    HuffmanTable t = (HuffmanTable)tables.get(j);
--                    dhtable.setAttribute("class",
--                                         Integer.toString(t.tableClass));
--                    dhtable.setAttribute("htableId",
--                                         Integer.toString(t.tableID));
--                    dhtable.setUserObject(t.table);
--                    dht.appendChild(dhtable);                    
--                }
--                markerSequence.appendChild(dht);
--                break;
--            case DRI:
--                IIOMetadataNode dri = new IIOMetadataNode("dri");
--                dri.setAttribute("interval", Integer.toString(driInterval));
--                markerSequence.appendChild(dri);
--                break;
--            case COM:
--                IIOMetadataNode com = new IIOMetadataNode("com");
--                com.setUserObject(comments.get(comIndex++));
--                markerSequence.appendChild(com);
--                break;
--            case UNKNOWN_MARKER:
--                IIOMetadataNode unknown = new IIOMetadataNode("unknown");
--                Integer markerTag = (Integer)markerTags.get(unknownIndex);
--                unknown.setAttribute("MarkerTag", markerTag.toString());
--                unknown.setUserObject(unknownData.get(unknownIndex++));
--                markerSequence.appendChild(unknown);
--                break;
--            case APP14_ADOBE:
--                IIOMetadataNode app14Adobe = new IIOMetadataNode("app14Adobe");
--                app14Adobe.setAttribute("version", Integer.toString(version));
--                app14Adobe.setAttribute("flags0", Integer.toString(flags0));
--                app14Adobe.setAttribute("flags1", Integer.toString(flags1));
--                app14Adobe.setAttribute("transform",
--                                        Integer.toString(transform));
--                markerSequence.appendChild(app14Adobe);
--                break;
--            case SOF_MARKER:
--                IIOMetadataNode sof = new IIOMetadataNode("sof");
--                sof.setAttribute("process", Integer.toString(sofProcess));
--                sof.setAttribute("samplePrecision",
--                                 Integer.toString(samplePrecision));
--                sof.setAttribute("numLines", Integer.toString(numLines));
--                sof.setAttribute("samplesPerLine",
--                                 Integer.toString(samplesPerLine));
--                sof.setAttribute("numFrameComponents",
--                                 Integer.toString(numFrameComponents));
--                for(int i = 0; i < numFrameComponents; i++) {
--                    IIOMetadataNode componentSpec =
--                        new IIOMetadataNode("componentSpec");
--                    componentSpec.setAttribute("componentId",
--                                               Integer.toString(componentId[i]));
--                    componentSpec.setAttribute("HsamplingFactor",
--                                               Integer.toString(hSamplingFactor[i]));
--                    componentSpec.setAttribute("VsamplingFactor",
--                                               Integer.toString(vSamplingFactor[i]));
--                    componentSpec.setAttribute("QtableSelector",
--                                               Integer.toString(qtableSelector[i]));
--                    sof.appendChild(componentSpec);
--                }
--                markerSequence.appendChild(sof);
--                break;
--            case SOS:
--                IIOMetadataNode sos = new IIOMetadataNode("sos");
--                sos.setAttribute("numScanComponents",
--                                 Integer.toString(numScanComponents));
--                sos.setAttribute("startSpectralSelection",
--                                 Integer.toString(startSpectralSelection));
--                sos.setAttribute("endSpectralSelection",
--                                 Integer.toString(endSpectralSelection));
--                sos.setAttribute("approxHigh", Integer.toString(approxHigh));
--                sos.setAttribute("approxLow", Integer.toString(approxLow));
--                for(int i = 0; i < numScanComponents; i++) {
--                    IIOMetadataNode scanComponentSpec =
--                        new IIOMetadataNode("scanComponentSpec");
--                    scanComponentSpec.setAttribute("componentSelector",
--                                                   Integer.toString(componentSelector[i]));
--                    scanComponentSpec.setAttribute("dcHuffTable",
--                                                   Integer.toString(dcHuffTable[i]));
--                    scanComponentSpec.setAttribute("acHuffTable",
--                                                   Integer.toString(acHuffTable[i]));
--                    sos.appendChild(scanComponentSpec);
--                }
--                markerSequence.appendChild(sos);
--                break;
--            }
--        }
--
--        return root;
--    }
--
--    // Standard tree node methods
--
--    protected IIOMetadataNode getStandardChromaNode() {
--        if(!sofPresent) {
--            // No image, so no chroma
--            return null;
--        }
--
--        IIOMetadataNode chroma = new IIOMetadataNode("Chroma");
--        IIOMetadataNode csType = new IIOMetadataNode("ColorSpaceType");
--        chroma.appendChild(csType);
--
--        IIOMetadataNode numChanNode = new IIOMetadataNode("NumChannels");
--        chroma.appendChild(numChanNode);
--        numChanNode.setAttribute("value",
--                                 Integer.toString(numFrameComponents));
--
--        // Check JFIF presence.
--        if(app0JFIFPresent) {
--            if(numFrameComponents == 1) {
--                csType.setAttribute("name", "GRAY");
--            } else {
--                csType.setAttribute("name", "YCbCr");
--            }
--            return chroma;
--        }
--
--        // How about an Adobe marker segment?
--        if(app14AdobePresent){
--            switch(transform) {
--            case ADOBE_TRANSFORM_YCCK: // YCCK
--                csType.setAttribute("name", "YCCK");
--                break;
--            case ADOBE_TRANSFORM_YCC: // YCC
--                csType.setAttribute("name", "YCbCr");
--                break;
--            case ADOBE_TRANSFORM_UNKNOWN: // Unknown
--                if(numFrameComponents == 3) {
--                    csType.setAttribute("name", "RGB");
--                } else if(numFrameComponents == 4) {
--                    csType.setAttribute("name", "CMYK");
--                }
--                break;
--            }
--            return chroma;
--        }
--
--        // Initially assume no opacity.
--        hasAlpha = false;
--
--        // Neither marker.  Check components
--        if(numFrameComponents < 3) {
--            csType.setAttribute("name", "GRAY");
--            if(numFrameComponents == 2) {
--                hasAlpha = true;
--            }
--            return chroma;
--        }
--
--        boolean idsAreJFIF = true;
--
--        for(int i = 0; i < componentId.length; i++) {
--            int id = componentId[i];
--            if((id < 1) || (id >= componentId.length)) {
--                idsAreJFIF = false;
--            }
--        }
--        
--        if(idsAreJFIF) {
--            csType.setAttribute("name", "YCbCr");
--            if(numFrameComponents == 4) {
--                hasAlpha = true;
--            }
--            return chroma;
--        }
--
--        // Check against the letters
--        if(componentId[0] == 'R' &&
--           componentId[1] == 'G' &&
--           componentId[2] == 'B'){
--            csType.setAttribute("name", "RGB");
--            if(numFrameComponents == 4 && componentId[3] == 'A') {
--                hasAlpha = true;
--            }
--            return chroma;
--        }
--        
--        if(componentId[0] == 'Y' &&
--           componentId[1] == 'C' &&
--           componentId[2] == 'c'){
--            csType.setAttribute("name", "PhotoYCC");
--            if(numFrameComponents == 4 &&
--               componentId[3] == 'A') {
--                hasAlpha = true;
--            }            
--            return chroma;
--        }
--        
--        // Finally, 3-channel subsampled are YCbCr, unsubsampled are RGB
--        // 4-channel subsampled are YCbCrA, unsubsampled are CMYK
--
--        boolean subsampled = false;
--
--        int hfactor = hSamplingFactor[0];
--        int vfactor = vSamplingFactor[0];
--
--        for(int i = 1; i < componentId.length; i++) {
--            if(hSamplingFactor[i] != hfactor ||
--               vSamplingFactor[i] != vfactor){
--                subsampled = true;
--                break;
--            }
--        }
--
--        if(subsampled) {
--            csType.setAttribute("name", "YCbCr");
--            if(numFrameComponents == 4) {
--                hasAlpha = true;
--            }
--            return chroma;
--        }
--         
--        // Not subsampled.  numFrameComponents < 3 is taken care of above
--        if(numFrameComponents == 3) {
--            csType.setAttribute("name", "RGB");
--        } else {
--            csType.setAttribute("name", "CMYK");
--        }
--
--        return chroma;
--    }
--
--    protected IIOMetadataNode getStandardCompressionNode() {
--        IIOMetadataNode compression = null;
--
--        if(sofPresent || sosPresent) {
--            compression = new IIOMetadataNode("Compression");
--
--            if(sofPresent) {
--                // Process 55 is JPEG-LS, others are lossless JPEG.
--                boolean isLossless =
--                    sofProcess == 3 || sofProcess == 7 || sofProcess == 11 ||
--                    sofProcess == 15 || sofProcess == 55;
--
--                // CompressionTypeName
--                IIOMetadataNode name =
--                    new IIOMetadataNode("CompressionTypeName");
--                String compressionType = isLossless ?
--                    (sofProcess == 55 ? "JPEG-LS" : "JPEG-LOSSLESS") : "JPEG";
--                name.setAttribute("value", compressionType);
--                compression.appendChild(name);
--
--                // Lossless - false
--                IIOMetadataNode lossless = new IIOMetadataNode("Lossless");
--                lossless.setAttribute("value", isLossless ? "true" : "false");
--                compression.appendChild(lossless);
--            }
--
--            if(sosPresent) {
--                IIOMetadataNode prog =
--                    new IIOMetadataNode("NumProgressiveScans");
--                prog.setAttribute("value", "1");
--                compression.appendChild(prog);
--            }
--        }
--
--        return compression;
--    }
--
--    protected IIOMetadataNode getStandardDimensionNode() {
--        IIOMetadataNode dim = new IIOMetadataNode("Dimension");
--        IIOMetadataNode orient = new IIOMetadataNode("ImageOrientation");
--        orient.setAttribute("value", "normal");
--        dim.appendChild(orient);
--
--        if(app0JFIFPresent) {
--            float aspectRatio;
--            if(resUnits == JFIF_RESUNITS_ASPECT) {
--                // Aspect ratio.
--                aspectRatio = (float)Xdensity/(float)Ydensity;
--            } else {
--                // Density.
--                aspectRatio = (float)Ydensity/(float)Xdensity;
--            }
--            IIOMetadataNode aspect = new IIOMetadataNode("PixelAspectRatio");
--            aspect.setAttribute("value", Float.toString(aspectRatio));
--            dim.insertBefore(aspect, orient);
--
--            if(resUnits != JFIF_RESUNITS_ASPECT) {
--                // 1 == dpi, 2 == dpc
--                float scale = (resUnits == JFIF_RESUNITS_DPI) ? 25.4F : 10.0F;
--
--                IIOMetadataNode horiz = 
--                    new IIOMetadataNode("HorizontalPixelSize");
--                horiz.setAttribute("value", 
--                                   Float.toString(scale/Xdensity));
--                dim.appendChild(horiz);
--
--                IIOMetadataNode vert = 
--                    new IIOMetadataNode("VerticalPixelSize");
--                vert.setAttribute("value", 
--                                  Float.toString(scale/Ydensity));
--                dim.appendChild(vert);
--            }
--        }
--        return dim;
--    }
--
--    protected IIOMetadataNode getStandardTextNode() {
--        IIOMetadataNode text = null;
--        if(comPresent) {
--            text = new IIOMetadataNode("Text");
--            Iterator iter = comments.iterator();
--            while (iter.hasNext()) {
--                IIOMetadataNode entry = new IIOMetadataNode("TextEntry");
--                entry.setAttribute("keyword", "comment");
--                byte[] data = (byte[])iter.next();
--                try {
--                    entry.setAttribute("value",
--                                       new String(data, "ISO-8859-1"));
--                } catch(UnsupportedEncodingException e) {
--                    entry.setAttribute("value", new String(data));
--                }
--                text.appendChild(entry);
--            }
--        }
--        return text;
--    }
--
--    // This method assumes that getStandardChromaNode() has already been
--    // called to initialize hasAlpha.
--    protected IIOMetadataNode getStandardTransparencyNode() {
--        IIOMetadataNode trans = null;
--        if (hasAlpha == true) {
--            trans = new IIOMetadataNode("Transparency");
--            IIOMetadataNode alpha = new IIOMetadataNode("Alpha");
--            alpha.setAttribute("value", "nonpremultiplied"); // Always assume
--            trans.appendChild(alpha);
--        }
--        return trans;
--    }
--
--    // TIFF tree method
--
--    private Node getTIFFTree() {
--        String metadataName = TIFF_FORMAT;
--
--        BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance();
--
--        TIFFDirectory dir =
--            new TIFFDirectory(new TIFFTagSet[] {
--                base, EXIFParentTIFFTagSet.getInstance()
--            }, null);
--
--        if(sofPresent) {
--            // sofProcess -> Compression ?
--            int compression = BaselineTIFFTagSet.COMPRESSION_JPEG;
--            TIFFField compressionField =
--                new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_COMPRESSION),
--                              compression);
--            dir.addTIFFField(compressionField);
--
--            // samplePrecision -> BitsPerSample
--            char[] bitsPerSample = new char[numFrameComponents];
--            Arrays.fill(bitsPerSample, (char)(samplePrecision & 0xff));
--            TIFFField bitsPerSampleField =
--                new TIFFField(
--                              base.getTag(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE),
--                              TIFFTag.TIFF_SHORT,
--                              bitsPerSample.length,
--                              bitsPerSample);
--            dir.addTIFFField(bitsPerSampleField);
--
--            // numLines -> ImageLength
--            TIFFField imageLengthField =
--                new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_IMAGE_LENGTH),
--                              numLines);
--            dir.addTIFFField(imageLengthField);
--
--            // samplesPerLine -> ImageWidth
--            TIFFField imageWidthField =
--                new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_IMAGE_WIDTH),
--                              samplesPerLine);
--            dir.addTIFFField(imageWidthField);
--
--            // numFrameComponents -> SamplesPerPixel
--            TIFFField samplesPerPixelField =
--                new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL),
--                              numFrameComponents);
--            dir.addTIFFField(samplesPerPixelField);
--
--            // componentId -> PhotometricInterpretation + ExtraSamples
--            IIOMetadataNode chroma = getStandardChromaNode();
--            if(chroma != null) {
--                IIOMetadataNode csType =
--                    (IIOMetadataNode)chroma.getElementsByTagName("ColorSpaceType").item(0);
--                String name = csType.getAttribute("name");
--                int photometricInterpretation = -1;
--                if(name.equals("GRAY")) {
--                    photometricInterpretation =
--                        BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO;
--                } else if(name.equals("YCbCr") || name.equals("PhotoYCC")) {
--                    // NOTE: PhotoYCC -> YCbCr
--                    photometricInterpretation =
--                        BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR;
--                } else if(name.equals("RGB")) {
--                    photometricInterpretation =
--                        BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB;
--                } else if(name.equals("CMYK") || name.equals("YCCK")) {
--                    // NOTE: YCCK -> CMYK
--                    photometricInterpretation =
--                        BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK;
--                }
--
--                if(photometricInterpretation != -1) {
--                    TIFFField photometricInterpretationField =
--                        new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION),
--                                      photometricInterpretation);
--                    dir.addTIFFField(photometricInterpretationField);
--                }
--
--                if(hasAlpha) {
--                    char[] extraSamples =
--                        new char[] {BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA};
--                    TIFFField extraSamplesField =
--                        new TIFFField(
--                                      base.getTag(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES),
--                                      TIFFTag.TIFF_SHORT,
--                                      extraSamples.length,
--                                      extraSamples);
--                    dir.addTIFFField(extraSamplesField);
--                }
--            } // chroma != null
--        } // sofPresent
--
--        // JFIF APP0 -> Resolution fields.
--        if(app0JFIFPresent) {
--            long[][] xResolution = new long[][] {{Xdensity, 1}};
--            TIFFField XResolutionField =
--                new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION),
--                              TIFFTag.TIFF_RATIONAL,
--                              1,
--                              xResolution);
--            dir.addTIFFField(XResolutionField);
--
--            long[][] yResolution = new long[][] {{Ydensity, 1}};
--            TIFFField YResolutionField =
--                new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION),
--                              TIFFTag.TIFF_RATIONAL,
--                              1,
--                              yResolution);
--            dir.addTIFFField(YResolutionField);
--
--            int resolutionUnit = BaselineTIFFTagSet.RESOLUTION_UNIT_NONE;
--            switch(resUnits) {
--            case JFIF_RESUNITS_ASPECT:
--                resolutionUnit = BaselineTIFFTagSet.RESOLUTION_UNIT_NONE;
--            case JFIF_RESUNITS_DPI:
--                resolutionUnit = BaselineTIFFTagSet.RESOLUTION_UNIT_INCH;
--                break;
--            case JFIF_RESUNITS_DPC:
--                resolutionUnit = BaselineTIFFTagSet.RESOLUTION_UNIT_CENTIMETER;
--                break;
--            }
--            TIFFField ResolutionUnitField =
--                new TIFFField(base.getTag
--                              (BaselineTIFFTagSet.TAG_RESOLUTION_UNIT),
--                              resolutionUnit);
--            dir.addTIFFField(ResolutionUnitField);
--        }
--
--        // DQT + DHT -> JPEGTables.
--        byte[] jpegTablesData = null;
--        if(dqtPresent || dqtPresent) {
--            // Determine length of JPEGTables data.
--            int jpegTablesLength = 2; // SOI
--            if(dqtPresent) {
--                Iterator dqts = qtables.iterator();
--                while(dqts.hasNext()) {
--                    Iterator qtiter = ((List)dqts.next()).iterator();
--                    while(qtiter.hasNext()) {
--                        QTable qt = (QTable)qtiter.next();
--                        jpegTablesLength += 4 + qt.length;
--                    }
--                }
--            }
--            if(dhtPresent) {
--                Iterator dhts = htables.iterator();
--                while(dhts.hasNext()) {
--                    Iterator htiter = ((List)dhts.next()).iterator();
--                    while(htiter.hasNext()) {
--                        HuffmanTable ht = (HuffmanTable)htiter.next();
--                        jpegTablesLength += 4 + ht.length;
--                    }
--                }
--            }
--            jpegTablesLength += 2; // EOI
--
--            // Allocate space.
--            jpegTablesData = new byte[jpegTablesLength];
--
--            // SOI
--            jpegTablesData[0] = (byte)0xff;
--            jpegTablesData[1] = (byte)SOI;
--            int jpoff = 2;
--
--            if(dqtPresent) {
--                Iterator dqts = qtables.iterator();
--                while(dqts.hasNext()) {
--                    Iterator qtiter = ((List)dqts.next()).iterator();
--                    while(qtiter.hasNext()) {
--                        jpegTablesData[jpoff++] = (byte)0xff;
--                        jpegTablesData[jpoff++] = (byte)DQT;
--                        QTable qt = (QTable)qtiter.next();
--                        int qtlength = qt.length + 2;
--                        jpegTablesData[jpoff++] =
--                            (byte)((qtlength & 0xff00) >> 8);
--                        jpegTablesData[jpoff++] = (byte)(qtlength & 0xff);
--                        jpegTablesData[jpoff++] =
--                            (byte)(((qt.elementPrecision & 0xf0) << 4) |
--                                   (qt.tableID & 0x0f));
--                        int[] table = qt.table.getTable();
--                        int qlen = table.length;
--                        for(int i = 0; i < qlen; i++) {
--                            jpegTablesData[jpoff + zigzag[i]] = (byte)table[i];
--                        }
--                        jpoff += qlen;
--                    }
--                }
--            }
--
--            if(dhtPresent) {
--                Iterator dhts = htables.iterator();
--                while(dhts.hasNext()) {
--                    Iterator htiter = ((List)dhts.next()).iterator();
--                    while(htiter.hasNext()) {
--                        jpegTablesData[jpoff++] = (byte)0xff;
--                        jpegTablesData[jpoff++] = (byte)DHT;
--                        HuffmanTable ht = (HuffmanTable)htiter.next();
--                        int htlength = ht.length + 2;
--                        jpegTablesData[jpoff++] =
--                            (byte)((htlength & 0xff00) >> 8);
--                        jpegTablesData[jpoff++] = (byte)(htlength & 0xff);
--                        jpegTablesData[jpoff++] =
--                            (byte)(((ht.tableClass & 0x0f) << 4) |
--                                   (ht.tableID & 0x0f));
--                        short[] lengths = ht.table.getLengths();
--                        int numLengths = lengths.length;
--                        for(int i = 0; i < numLengths; i++) {
--                            jpegTablesData[jpoff++] = (byte)lengths[i];
--                        }
--                        short[] values = ht.table.getValues();
--                        int numValues = values.length;
--                        for(int i = 0; i < numValues; i++) {
--                            jpegTablesData[jpoff++] = (byte)values[i];
--                        }
--                    }
--                }
--            }
--
--            jpegTablesData[jpoff++] = (byte)0xff;
--            jpegTablesData[jpoff] = (byte)EOI;            
--        }
--        if(jpegTablesData != null) {
--            TIFFField JPEGTablesField =
--                new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_JPEG_TABLES),
--                              TIFFTag.TIFF_UNDEFINED,
--                              jpegTablesData.length,
--                              jpegTablesData);
--            dir.addTIFFField(JPEGTablesField);
--        }
--
--        IIOMetadata tiffMetadata = dir.getAsMetadata();
--
--        if(exifData != null) {
--            try {
--                Iterator tiffReaders =
--                    ImageIO.getImageReadersByFormatName("TIFF");
--                if(tiffReaders != null && tiffReaders.hasNext()) {
--                    ImageReader tiffReader = (ImageReader)tiffReaders.next();
--                    ByteArrayInputStream bais =
--                        new ByteArrayInputStream(exifData);
--                    ImageInputStream exifStream =
--                        new MemoryCacheImageInputStream(bais);
--                    tiffReader.setInput(exifStream);
--                    IIOMetadata exifMetadata = tiffReader.getImageMetadata(0);
--                    tiffMetadata.mergeTree(metadataName,
--                                           exifMetadata.getAsTree(metadataName));
--                    tiffReader.reset();
--                }
--            } catch(IOException ioe) {
--                // Ignore it.
--            }
--        }
--
--        return tiffMetadata.getAsTree(metadataName);
--    }
--
--    // Thumbnail methods
--
--    private void initializeThumbnails() {
--        synchronized(thumbnails) {
--            if(!thumbnailsInitialized) {
--                // JFIF/JFXX are not supposed to coexist in the same
--                // JPEG stream but in reality sometimes they do.
--
--                // JFIF thumbnail
--                if(app0JFIFPresent && jfifThumbnail != null) {
--                    thumbnails.add(jfifThumbnail);
--                }
--
--                // JFXX thumbnail(s)
--                if(app0JFXXPresent && jfxxThumbnails != null) {
--                    int numJFXX = jfxxThumbnails.size();
--                    for(int i = 0; i < numJFXX; i++) {
--                        IIOImage img = (IIOImage)jfxxThumbnails.get(i);
--                        BufferedImage jfxxThumbnail =
--                            (BufferedImage)img.getRenderedImage();
--                        thumbnails.add(jfxxThumbnail);
--                    }
--                }
--
--                // EXIF thumbnail
--                if(exifData != null) {
--                    try {
--                        Iterator tiffReaders =
--                            ImageIO.getImageReadersByFormatName("TIFF");
--                        if(tiffReaders != null && tiffReaders.hasNext()) {
--                            ImageReader tiffReader =
--                                (ImageReader)tiffReaders.next();
--                            ByteArrayInputStream bais =
--                                new ByteArrayInputStream(exifData);
--                            ImageInputStream exifStream =
--                                new MemoryCacheImageInputStream(bais);
--                            tiffReader.setInput(exifStream);
--                            if(tiffReader.getNumImages(true) > 1) {
--                                BufferedImage exifThumbnail =
--                                    tiffReader.read(1, null);
--                                thumbnails.add(exifThumbnail);
--                            }
--                            tiffReader.reset();
--                        }
--                    } catch(IOException ioe) {
--                        // Ignore it.
--                    }
--                }
--
--                thumbnailsInitialized = true;
--            } // if(!thumbnailsInitialized)
--        } // sychronized
--    }
--
--    int getNumThumbnails() throws IOException {
--        initializeThumbnails();
--        return thumbnails.size();
--    }
--
--    BufferedImage getThumbnail(int thumbnailIndex) throws IOException {
--        if(thumbnailIndex < 0) {
--            throw new IndexOutOfBoundsException("thumbnailIndex < 0!");
--        }
--
--        initializeThumbnails();
--
--        if(thumbnailIndex >= thumbnails.size()) {
--            throw new IndexOutOfBoundsException
--                ("thumbnailIndex > getNumThumbnails()");
--        }
--
--        return (BufferedImage)thumbnails.get(thumbnailIndex);
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderCodecLib.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderCodecLib.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,507 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: J2KImageReaderCodecLib.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.4 $
-- * $Date: 2006/09/29 20:19:55 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.jpeg2000;
--
--import com.sun.media.imageio.plugins.jpeg2000.J2KImageReadParam;
--
--import java.awt.Point;
--import java.awt.image.ColorModel;
--import java.awt.image.Raster;
--import java.awt.image.RenderedImage;
--import java.awt.image.SampleModel;
--import java.awt.image.WritableRaster;
--import java.io.IOException;
--import java.util.Hashtable;
--
--import javax.imageio.IIOException;
--import javax.imageio.ImageReader;
--import javax.imageio.ImageReadParam;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.metadata.IIOMetadata;
--import javax.imageio.spi.ImageReaderSpi;
--import javax.imageio.stream.ImageInputStream;
--
--import java.util.ArrayList;
--import java.util.Iterator;
--import javax.imageio.metadata.IIOMetadata;
--import java.awt.image.BufferedImage;
--
--import com.sun.media.imageioimpl.common.SimpleRenderedImage;
--
--import com.sun.medialib.codec.jp2k.Decoder;
--import com.sun.medialib.codec.jp2k.Size;
--import com.sun.medialib.codec.jiio.*;
--
--public class J2KImageReaderCodecLib extends ImageReader {
--    /** Wrapper for the protected method <code>processImageUpdate</code>
--     *  So it can be access from the classes which are not in
--     *  <code>ImageReader</code> hierachy.
--     */
--    public void processImageUpdateWrapper(BufferedImage theImage,
--                                          int minX, int minY,
--                                          int width, int height,
--                                          int periodX, int periodY,
--                                          int[] bands) {
--        processImageUpdate(theImage,
--                           minX, minY,
--                           width, height,
--                           periodX, periodY,
--                           bands);
--    }
--
--    /** Wrapper for the protected method <code>processImageProgress</code>
--     *  So it can be access from the classes which are not in
--     *  <code>ImageReader</code> hierachy.
--     */
--    public void processImageProgressWrapper(float percentageDone) {
--        processImageProgress(percentageDone);
--    }
--
--    /** The input stream where reads from */
--    private ImageInputStream iis = null;
--
--    /** Stream position when setInput() was called. */
--    private long streamPosition0;
--
--    /** Indicates whether the header is read. */
--    private boolean gotHeader = false;
--
--    /** The image width. */
--    private int width = -1;
--
--    /** The image height. */
--    private int height = -1;
--
--    /** The image tile width. */
--    private int tileWidth = -1;
--
--    /** The image tile height. */
--    private int tileHeight = -1;
--
--    /** The image tile grid X offset. */
--    private int tileGridXOffset = 0;
--
--    /** The image tile grid Y offset. */
--    private int tileGridYOffset = 0;
--
--    /** Image metadata, valid for the imageMetadataIndex only. */
--    private J2KMetadata imageMetadata = null;
--
--    /** The RenderedImage decoded from the stream. */
--    SimpleRenderedImage image = null;
--
--    public J2KImageReaderCodecLib(ImageReaderSpi originator) {
--          super(originator);
--    }
--
--    /** Overrides the method defined in the superclass. */
--    public void setInput(Object input,
--                         boolean seekForwardOnly,
--                         boolean ignoreMetadata) {
--        super.setInput(input, seekForwardOnly, ignoreMetadata);
--        this.ignoreMetadata = ignoreMetadata;
--        iis = (ImageInputStream) input; // Always works
--        iis.mark(); // Mark the initial position.
--        imageMetadata = null;
--        try {
--            this.streamPosition0 = iis.getStreamPosition();
--        } catch(IOException e) {
--            // XXX ignore
--        }
--    }
--
--    public ImageReadParam getDefaultReadParam() {
--        return new J2KImageReadParam();
--    }
--    public int getNumImages(boolean allowSearch) throws java.io.IOException {
--        if(input == null) {
--            throw new IllegalStateException(I18N.getString("J2KImageReader6"));
--        } else if(seekForwardOnly) {
--            throw new IllegalStateException(I18N.getString("J2KImageReader7"));
--        }
--
--        return 1;
--    }
--
--    public Iterator getImageTypes(int imageIndex) throws java.io.IOException {
--        checkIndex(imageIndex);
--	readHeader();
--        if (image != null) {
--            ArrayList list = new ArrayList();
--            list.add(new ImageTypeSpecifier(image.getColorModel(),
--                                            image.getSampleModel()));
--            return list.iterator();
--        }
--        return null;
--    }
--
--    public int getWidth(int imageIndex) throws java.io.IOException {
--        checkIndex(imageIndex);
--        readHeader();
--        return width;
--    }
--
--    public int getHeight(int imageIndex) throws java.io.IOException {
--        checkIndex(imageIndex);
--        readHeader();
--        return height;
--    }
--
--    public int getTileGridXOffset(int imageIndex) throws IOException {
--        checkIndex(imageIndex);
--        readHeader();
--        return tileGridXOffset;
--    }
--
--    public int getTileGridYOffset(int imageIndex) throws IOException {
--        checkIndex(imageIndex);
--        readHeader();
--        return tileGridYOffset;
--    }
--
--    public int getTileWidth(int imageIndex) throws IOException {
--        checkIndex(imageIndex);
--        readHeader();
--        return tileWidth;
--    }
--
--    public int getTileHeight(int imageIndex) throws IOException {
--        checkIndex(imageIndex);
--        readHeader();
--        return tileHeight;
--    }
--
--    /**
--     * Returns <code>true</code> if the image is organized into
--     * <i>tiles</i>, that is, equal-sized non-overlapping rectangles.
--     *
--     * <p> A reader plug-in may choose whether or not to expose tiling
--     * that is present in the image as it is stored.  It may even
--     * choose to advertise tiling when none is explicitly present.  In
--     * general, tiling should only be advertised if there is some
--     * advantage (in speed or space) to accessing individual tiles.
--     * Regardless of whether the reader advertises tiling, it must be
--     * capable of reading an arbitrary rectangular region specified in
--     * an <code>ImageReadParam</code>.
--     *
--     * <p> A reader for which all images are guaranteed to be tiled,
--     * or are guaranteed not to be tiled, may return <code>true</code>
--     * or <code>false</code> respectively without accessing any image
--     * data.  In such cases, it is not necessary to throw an exception
--     * even if no input source has been set or the image index is out
--     * of bounds.
--     *
--     * <p> The default implementation just returns <code>false</code>.
--     *
--     * @param imageIndex the index of the image to be queried.
--     *
--     * @return <code>true</code> if the image is tiled.
--     *
--     * @exception IllegalStateException if an input source is required
--     * to determine the return value, but none has been set.
--     * @exception IndexOutOfBoundsException if an image must be
--     * accessed to determine the return value, but the supplied index
--     * is out of bounds.
--     * @exception IOException if an error occurs during reading.
--     */
--    public boolean isImageTiled(int imageIndex) throws IOException {
--        int w = getWidth(imageIndex);
--        int tw = getTileWidth(imageIndex);
--        if(tw > 0 && ((w + tw - 1)/tw) > 1) {
--            return true;
--        }
--
--        int h = getHeight(imageIndex);
--        int th = getTileHeight(imageIndex);
--        if(th > 0 && ((h + th - 1)/th) > 1) {
--            return true;
--        }
--
--        return false;
--    }
--
--    public IIOMetadata getStreamMetadata() throws java.io.IOException {
--        return null;
--    }
--
--    public IIOMetadata getImageMetadata(int imageIndex) throws
--                                                        java.io.IOException {
--        if (ignoreMetadata)
--            return null;
--
--        checkIndex(imageIndex);
--
--        if (imageMetadata == null) {
--            try {
--                iis.reset(); // Reset to initial position.
--                iis.mark(); // Re-mark initial position.
--                if (image == null ||
--                    !(image instanceof J2KRenderedImageCodecLib))
--                    image = new J2KRenderedImageCodecLib(iis, this, null);
--                imageMetadata =
--                    ((J2KRenderedImageCodecLib)image).readImageMetadata();
--            } catch(IOException ioe) {
--                throw ioe;
--            } catch(RuntimeException re) {
--                throw re;
--            } finally {
--                iis.reset(); // Reset to initial position.
--                iis.mark(); // Re-mark initial position.
--            }
--        }
--        return imageMetadata;
--    }
--
--    public boolean isRandomAccessEasy(int imageIndex) throws IOException {
--        // No check done because neither input source nor image is
--        // required to determine the return value.
--        return true;
--    }
--
--    public RenderedImage readAsRenderedImage(int imageIndex,
--                                            ImageReadParam param)
--                                            throws java.io.IOException {
--        checkIndex(imageIndex);
--        if (param == null)
--            param = getDefaultReadParam();
--        clearAbortRequest();
--        processImageStarted(0);
--
--        if(param instanceof J2KImageReadParam &&
--           ((J2KImageReadParam)param).getResolution() >= 0) {
--            // XXX Workaround for java.sun.com change request 5089981:
--            // fall back to Java reader for lower resolution levels.
--            // This code should be removed when this problem is fixed
--            // in the codecLib JPEG2000 decoder.
--            ImageReader jreader = new J2KImageReader(null);
--            iis.seek(streamPosition0);
--            jreader.setInput(iis);
--            image =
--                (SimpleRenderedImage)jreader.readAsRenderedImage(imageIndex,
--                                                                 param);
--        } else {
--            image = new J2KRenderedImageCodecLib(iis,
--                                                 this,
--                                                 param);
--        }
--        if (abortRequested())
--            processReadAborted();
--        else
--            processImageComplete();
--        return image;
--    }
--
--    public BufferedImage read(int imageIndex,
--                              ImageReadParam param) throws java.io.IOException {
--        checkIndex(imageIndex);
--        clearAbortRequest();
--        if (param == null)
--            param = getDefaultReadParam();
--        processImageStarted(imageIndex);
--
--        if(param instanceof J2KImageReadParam &&
--           ((J2KImageReadParam)param).getResolution() >= 0) {
--            // XXX Workaround for java.sun.com change request 5089981:
--            // fall back to Java reader for lower resolution levels.
--            // This code should be removed when this problem is fixed
--            // in the codecLib JPEG2000 decoder.
--            ImageReader jreader = new J2KImageReader(null);
--            iis.seek(streamPosition0);
--            jreader.setInput(iis);
--            if (abortRequested())
--                processReadAborted();
--            else
--                processImageComplete();
--            return jreader.read(imageIndex, param);
--        }
--
--        BufferedImage bi = param.getDestination();
--        iis.reset(); // Reset to initial position.
--        iis.mark(); // Re-mark initial position.
--        // XXX Need to add a try-catch IOException block and reset/mark iis.
--        image = new J2KRenderedImageCodecLib(iis,
--                                             this,
--                                             param);
--        J2KRenderedImageCodecLib jclibImage = (J2KRenderedImageCodecLib)image;
--        Point offset = param.getDestinationOffset();
--        WritableRaster raster;
--
--        if (bi == null) {
--            ColorModel colorModel = jclibImage.getColorModel();
--            SampleModel sampleModel = jclibImage.getSampleModel();
--
--            // If the destination type is specified, use the color model of it.
--            ImageTypeSpecifier type = param.getDestinationType();
--            if (type != null)
--                colorModel = type.getColorModel();
--
--            raster = Raster.createWritableRaster(
--                sampleModel.createCompatibleSampleModel(jclibImage.getMinX()+
--                                                        jclibImage.getWidth(),
--                                                        jclibImage.getMinY() +
--                                                        jclibImage.getHeight()),
--                new Point(0, 0));
--
--            bi = new BufferedImage(colorModel,
--                                   raster,
--                                   colorModel != null ?
--                                   colorModel.isAlphaPremultiplied() : false,
--                                   new Hashtable());
--        } else {
--            raster = bi.getWritableTile(0, 0);
--        }
--
--        jclibImage.setDestImage(bi);
--        jclibImage.readAsRaster(raster);
--        jclibImage.clearDestImage();
--
--        if (abortRequested())
--            processReadAborted();
--        else
--            processImageComplete();
--        return bi;
--    }
--
--    public Raster readRaster(int imageIndex,
--                             ImageReadParam param) throws IOException {
--        BufferedImage bi = read(imageIndex, param);
--        return bi.getWritableTile(0, 0);
--    }
--
--    public void readHeader() throws java.io.IOException {
--        if (gotHeader)
--            return;
--
--        try {
--            iis.reset(); // Reset to initial position.
--            iis.mark(); // Re-mark initial position.
--
--            if (image == null)
--                image = new J2KRenderedImageCodecLib(iis, this, null);
--
--            this.width = image.getWidth();
--            this.height = image.getHeight();
--            this.tileWidth = image.getTileWidth();
--            this.tileHeight = image.getTileHeight();
--            this.tileGridXOffset = image.getTileGridXOffset();
--            this.tileGridYOffset = image.getTileGridYOffset();
--        } catch(IOException ioe) {
--            throw ioe;
--        } catch(RuntimeException re) {
--            throw re;
--        } finally {
--            iis.reset(); // Reset to initial position.
--            iis.mark(); // Re-mark initial position.
--        }
--
--        this.gotHeader = true;
--    }
--
--    private void checkIndex(int imageIndex) {
--        if(input == null) {
--            throw new IllegalStateException(I18N.getString("J2KImageReader6"));
--        }
--        if (imageIndex != 0) {
--            throw new IndexOutOfBoundsException(I18N.getString("J2KImageReader4"));
--        }
--    }
--
--    /** This method wraps the protected method <code>abortRequested</code>
--     *  to allow the abortions be monitored by <code>J2KReadState</code>.
--     */
--    public boolean getAbortRequest() {
--        return abortRequested();
--    }
--
--    public void reset() {
--        super.reset();
--        iis = null;
--        gotHeader = false;
--        width = -1;
--        height = -1;
--        tileWidth = -1;
--        tileHeight = -1;
--        tileGridXOffset = 0;
--        tileGridYOffset = 0;
--        imageMetadata = null;
--        image = null;
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderCodecLibSpi.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderCodecLibSpi.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,207 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: J2KImageReaderCodecLibSpi.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.2 $
-- * $Date: 2006/03/31 19:43:39 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.jpeg2000;
--
--import java.util.Locale;
--import javax.imageio.spi.ImageReaderSpi;
--import javax.imageio.stream.ImageInputStream;
--import javax.imageio.spi.IIORegistry;
--import javax.imageio.spi.ServiceRegistry;
--import java.io.IOException;
--import javax.imageio.ImageReader;
--import javax.imageio.IIOException;
--
--import com.sun.media.imageioimpl.common.PackageUtil;
--
--public class J2KImageReaderCodecLibSpi extends ImageReaderSpi {
--
--    private static String [] writerSpiNames =
--        {"com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriterCodecLibSpi"};
--    private static String[] formatNames =
--        {"jpeg 2000", "JPEG 2000", "jpeg2000", "JPEG2000"};
--    private static String[] extensions =
--        {"jp2"}; // Should add jpx or jpm
--    private static String[] mimeTypes = {"image/jp2", "image/jpeg2000"};
--    private boolean registered = false;
--
--    public J2KImageReaderCodecLibSpi() {
--        super(PackageUtil.getVendor(),
--              PackageUtil.getVersion(),
--              formatNames,
--              extensions,
--              mimeTypes,
--              "com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderCodecLib",
--              STANDARD_INPUT_TYPE,
--              writerSpiNames,
--              false,
--              null, null,
--              null, null,
--              true,
--              "com_sun_media_imageio_plugins_jpeg2000_image_1.0",
--              "com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat",
--              null, null);
--    }
--
--    public void onRegistration(ServiceRegistry registry,
--                               Class category) {
--        if (registered) {
--            return;
--        }
--	
--        registered = true;
--
--        // Branch based on codecLib availability.
--        if(!PackageUtil.isCodecLibAvailable()) {
--            // Deregister provider.
--            registry.deregisterServiceProvider(this);
--        } else {
--            // Set pairwise ordering to give codecLib reader precedence.
--            Class javaReaderSPIClass = null;
--            try {
--                javaReaderSPIClass =
--                    Class.forName("com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderSpi");
--            } catch(Throwable t) {
--                // Ignore it.
--            }
--
--            if(javaReaderSPIClass != null) {
--                Object javaReaderSPI =
--                    registry.getServiceProviderByClass(javaReaderSPIClass);
--                if(javaReaderSPI != null) {
--                    registry.setOrdering(category, this, javaReaderSPI);
--                }
--            }
--        }
--    }
--
--    public String getDescription(Locale locale) {
--	String desc = PackageUtil.getSpecificationTitle() + 
--	    " natively-accelerated JPEG 2000 Image Reader";
--	return desc;
--    }
--
--    public boolean canDecodeInput(Object source) throws IOException {
--        if (!(source instanceof ImageInputStream)) {
--            return false;
--        }
--
--        ImageInputStream stream = (ImageInputStream)source;
--
--	//fix of 4938421
--        stream.mark();
--	int marker = (stream.read() << 8) | stream.read();
--
--	if (marker == 0xFF4F) {
--	    stream.reset();
--	    return true;
--	}
--
--	stream.reset();
--        stream.mark();
--        byte[] b = new byte[12];
--        stream.readFully(b);
--        stream.reset();
--
--        //Verify the signature box
--
--        // The length of the signature box is 12
--        if (b[0] !=0 || b[1]!=0 || b[2] != 0 || b[3] != 12)
--            return false;
--
--        // The signature box type is "jP  "
--        if ((b[4] & 0xff) != 0x6A || (b[5] & 0xFF) != 0x50 ||
--            (b[6] & 0xFF) !=0x20 || (b[7] & 0xFF) != 0x20)
--            return false;
--
--        // The signture content is 0x0D0A870A
--        if ((b[8] & 0xFF) != 0x0D || (b[9] & 0xFF) != 0x0A ||
--            (b[10] & 0xFF) != 0x87 || (b[11] &0xFF) != 0x0A)
--            return false;
--
--        return true;
--    }
--
--    public ImageReader createReaderInstance(Object extension)
--        throws IIOException {
--        return new J2KImageReaderCodecLib(this);
--    }
--}
--
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderSpi.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderSpi.java	2012-08-22 20:24:05.000000000 +0000
-+++ bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageReaderSpi.java	2012-09-20 08:16:06.724187619 +0000
-@@ -91,8 +91,6 @@
- 
- import com.sun.media.imageioimpl.common.PackageUtil;
- 
--import com.sun.medialib.codec.jiio.Util;
--
- public class J2KImageReaderSpi extends ImageReaderSpi {
- 
-     private static String [] writerSpiNames =
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterCodecLib.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterCodecLib.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,915 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: J2KImageWriterCodecLib.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.3 $
-- * $Date: 2006/09/22 23:07:25 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.jpeg2000;
--
--import java.awt.Point;
--import java.awt.Rectangle;
--import java.awt.image.ColorModel;
--import java.awt.image.DataBuffer;
--import java.awt.image.DataBufferByte;
--import java.awt.image.IndexColorModel;
--import java.awt.image.Raster;
--import java.awt.image.RenderedImage;
--import java.awt.image.SampleModel;
--import java.awt.image.WritableRaster;
--
--import java.io.IOException;
--
--import java.util.Arrays;
--import java.util.List;
--
--import javax.imageio.IIOImage;
--import javax.imageio.IIOException;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.ImageWriteParam;
--import javax.imageio.ImageWriter;
--import javax.imageio.metadata.IIOMetadata;
--import javax.imageio.metadata.IIOMetadataFormatImpl;
--import javax.imageio.metadata.IIOMetadataNode;
--import javax.imageio.metadata.IIOInvalidTreeException;
--import javax.imageio.spi.ImageWriterSpi;
--import javax.imageio.stream.ImageOutputStream;
--
--import com.sun.media.imageio.plugins.jpeg2000.J2KImageWriteParam;
--import com.sun.media.imageioimpl.common.ImageUtil;
--import org.w3c.dom.Node;
--import org.w3c.dom.NodeList;
--
--import com.sun.medialib.codec.jp2k.CompParams;
--import com.sun.medialib.codec.jp2k.Constants;
--import com.sun.medialib.codec.jp2k.Encoder;
--import com.sun.medialib.codec.jp2k.Params;
--import com.sun.medialib.codec.jp2k.Size;
--import com.sun.medialib.codec.jiio.*;
--
--public class J2KImageWriterCodecLib extends ImageWriter {
--    /** When the writing is aborted, <code>RenderedImageSrc</code> throws a
--     *  <code>RuntimeException</code>.
--     */
--    public static String WRITE_ABORTED = "Write aborted.";
--
--    /** The output stream to write into */
--    private ImageOutputStream stream = null;
--
--    /** The metadata format object. */
--    private J2KMetadataFormat format;
--
--    /** medialib encoder. */
--    private Encoder encoder;
--
--    /** size parameters for medialib. */
--    private Size size;
--
--    /** The tile width for encoding */
--    private int tileWidth;
--
--    /** The tile height for encoding */
--    private int tileHeight;
--
--    /** The tile grid offset for encoding */
--    private int tileXOffset, tileYOffset;
--
--    /** The source -> destination transformation */
--    private int scaleX, scaleY, xOffset, yOffset;
--
--    /** The source bands to be encoded. */
--    private int[] sourceBands = null;
--
--    /** The number of components in the image */
--    private int numComp;
--
--    private RenderedImage input;
--    private J2KImageWriteParam param;
--
--    /** The input source raster. */
--    private Raster inputRaster;
--
--    private Rectangle destinationRegion = null;
--
--    private SampleModel sampleModel;
--
--    /** Coordinate transform or sub selection is needed before encoding. */
--    private boolean noTransform = true;
--    private boolean noSubband = true;
--
--    /** Indicates a <code>raster</code> rather than a <code>RenderedImage</code>
--     *  to be encoded.
--     */
--    private boolean writeRaster = false;
--
--    /** Constructs <code>J2KImageWriter</code> based on the provided
--     *  <code>ImageWriterSpi</code>.
--     */
--    public J2KImageWriterCodecLib(ImageWriterSpi originator) {
--        super(originator);
--    }
--
--    public void setOutput(Object output) {
--        super.setOutput(output); // validates output
--        if (output != null) {
--            if (!(output instanceof ImageOutputStream))
--                throw new IllegalArgumentException(I18N.getString("J2KImageWriter0"));
--            this.stream = (ImageOutputStream)output;
--        } else
--            this.stream = null;
--    }
--
--    public ImageWriteParam getDefaultWriteParam() {
--        return new J2KImageWriteParam();
--    }
--
--    public IIOMetadata convertStreamMetadata(IIOMetadata inData,
--                                             ImageWriteParam param) {
--        return null;
--    }
--
--    public void write(IIOMetadata streamMetadata,
--                      IIOImage image,
--                      ImageWriteParam param) throws java.io.IOException {
--        if (stream == null) {
--            throw new IllegalStateException(I18N.getString("J2KImageWriterMedialib1"));
--        }
--        if (image == null) {
--            throw new IllegalArgumentException(I18N.getString("J2KImageWriterMedialib2"));
--        }
--        clearAbortRequest();
--        processImageStarted(0);
--        encoder = new Encoder(stream);
--
--        writeRaster = image.hasRaster();
--        ColorModel colorModel = null;
--
--        if (writeRaster) {
--            inputRaster = image.getRaster();
--            sampleModel = inputRaster.getSampleModel();
--        } else {
--            input = image.getRenderedImage();
--            sampleModel = input.getSampleModel();
--            colorModel = input.getColorModel();
--        }
--
--        if (param == null)
--            param = new J2KImageWriteParam();
--
--        if(param instanceof J2KImageWriteParam) {
--            J2KImageWriteParam j2kParam = (J2KImageWriteParam)param;
--            if (!writeRaster &&
--                input.getColorModel() instanceof IndexColorModel) {
--                j2kParam.setLossless(true);
--                j2kParam.setEncodingRate(Double.MAX_VALUE);
--                j2kParam.setFilter(J2KImageWriteParam.FILTER_53);
--            } else if (j2kParam.getEncodingRate() ==
--                       Double.MAX_VALUE) {
--                j2kParam.setLossless(true);
--                j2kParam.setFilter(J2KImageWriteParam.FILTER_53);
--            }
--        }
--        setParameters(param);
--
--        Rectangle sourceRegion = param.getSourceRegion();
--        if (sourceRegion == null) {
--            if (writeRaster)
--                sourceRegion = inputRaster.getBounds();
--            else
--                sourceRegion = new Rectangle(input.getMinX(), input.getMinY(),
--                                             input.getWidth(),
--                                             input.getHeight());
--        } else {
--            if (writeRaster)
--                sourceRegion =
--                    sourceRegion.intersection(inputRaster.getBounds());
--            else
--                sourceRegion =
--                    sourceRegion.intersection(new Rectangle(input.getMinX(),
--                                                            input.getMinY(),
--                                                            input.getWidth(),
--                                                            input.getHeight()));
--        }
--
--        if (sourceRegion.isEmpty())
--            throw new RuntimeException(I18N.getString("J2KImageWriterCodecLib0"));
--
--        try {
--            tileWidth = param.getTileWidth();
--            tileHeight = param.getTileHeight();
--            tileXOffset = param.getTileGridXOffset();
--            tileYOffset = param.getTileGridYOffset();
--        } catch (IllegalStateException e) {
--            param.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
--            if (writeRaster) {
--                param.setTiling(inputRaster.getWidth(),
--                                inputRaster.getHeight(),
--                                inputRaster.getMinX(),
--                                inputRaster.getMinY());
--            } else {
--                param.setTiling(input.getTileWidth(),
--                                input.getTileHeight(),
--                                input.getTileGridXOffset(),
--                                input.getTileGridYOffset());
--            }
--            tileWidth = param.getTileWidth();
--            tileHeight = param.getTileHeight();
--            tileXOffset = param.getTileGridXOffset();
--            tileYOffset = param.getTileGridYOffset();
--        }
--
--        scaleX = param.getSourceXSubsampling();
--        scaleY = param.getSourceYSubsampling();
--        xOffset = param.getSubsamplingXOffset();
--        yOffset = param.getSubsamplingYOffset();
--
--        sourceRegion.translate(xOffset, yOffset);
--        sourceRegion.width -= xOffset;
--        sourceRegion.height -= yOffset;
--
--	xOffset = sourceRegion.x % scaleX;
--	yOffset = sourceRegion.y % scaleY;
--
--        int minX = sourceRegion.x / scaleX;
--        int minY = sourceRegion.y / scaleY;
--
--        int w = (sourceRegion.width + scaleX - 1) / scaleX;
--        int h = (sourceRegion.height + scaleY - 1) / scaleY;
--
--        tileXOffset += (minX - tileXOffset)/tileWidth * tileWidth;
--        tileYOffset += (minY - tileYOffset)/tileHeight * tileHeight;
--
--        destinationRegion = new Rectangle(minX, minY, w, h);
--
--        if (!destinationRegion.equals(sourceRegion) ||
--            tileWidth != sampleModel.getWidth() ||
--            tileHeight != sampleModel.getHeight() ||
--            (!writeRaster &&
--             (tileXOffset != input.getTileGridXOffset() ||
--             tileYOffset != input.getTileGridYOffset())) ||
--            (writeRaster &&
--             (tileXOffset != inputRaster.getMinX() ||
--             tileYOffset != inputRaster.getMinY())))
--            noTransform = false;
--
--        numComp = sampleModel.getNumBands();
--        sourceBands = param.getSourceBands();
--        if (sourceBands != null) {
--            sampleModel = sampleModel.createSubsetSampleModel(sourceBands);
--            colorModel = null;
--            noSubband = false;
--        } else {
--            sourceBands = new int[numComp];
--            for (int i = 0; i < numComp; i++)
--                sourceBands[i] = i;
--        }
--
--        numComp = sourceBands.length;
--
--        sampleModel =
--            sampleModel.createCompatibleSampleModel(tileWidth, tileHeight);
--
--        setSize();
--
--        setCompParameters(colorModel, sampleModel, param);
--
--        encoder.setMode(Constants.JP2K_COMPOSITE_TILE);
--
--        /* XXX
--        J2KMetadata metadata = (J2KMetadata)image.getMetadata();
--        ImageTypeSpecifier type = null;
--        if (colorModel != null)
--            type = new ImageTypeSpecifier(colorModel, sampleModel);
--
--        J2KMetadata metadata1 =
--            new J2KMetadata(colorModel, sampleModel, destinationRegion.width,
--                            destinationRegion.height, param, this);
--
--        if (metadata == null)
--            metadata = metadata1;
--        else
--            metadata.mergeTree("com_sun_media_imageio_plugins_jpeg2000_image_1.0",
--                               metadata1.getAsTree("com_sun_media_imageio_plugins_jpeg2000_image_1.0"));
--        */
--
--        //write the metadata
--        if (!((J2KImageWriteParam)param).getWriteCodeStreamOnly()) {
--            IIOMetadata inMetadata = image.getMetadata();
--
--            J2KMetadata metadata1 = new J2KMetadata(colorModel,
--                                                    sampleModel,
--                                                    destinationRegion.width,
--                                                    destinationRegion.height,
--                                                    param,
--                                                    this);
--
--            J2KMetadata metadata = null;
--
--            if (inMetadata == null) {
--                metadata = metadata1;
--            } else {
--                // Convert the input metadata tree to a J2KMetadata.
--                if(colorModel != null) {
--                    ImageTypeSpecifier imageType = 
--                        new ImageTypeSpecifier(colorModel, sampleModel);
--                    metadata =
--                        (J2KMetadata)convertImageMetadata(inMetadata,
--                                                          imageType,
--                                                          param);
--                } else {
--                    String metaFormat = null;
--                    List metaFormats =
--                        Arrays.asList(inMetadata.getMetadataFormatNames());
--                    if(metaFormats.contains(J2KMetadata.nativeMetadataFormatName)) {
--                        // Initialize from native image metadata format.
--                        metaFormat = J2KMetadata.nativeMetadataFormatName;
--                    } else if(inMetadata.isStandardMetadataFormatSupported()) {
--                        // Initialize from standard metadata form of the
--                        // input tree.
--                        metaFormat = 
--                            IIOMetadataFormatImpl.standardMetadataFormatName;
--                    }
--
--                    metadata = new J2KMetadata();
--                    if(metaFormat != null) {
--                        metadata.setFromTree(metaFormat,
--                                             inMetadata.getAsTree(metaFormat));
--                    }
--                }
--
--                metadata.mergeTree(J2KMetadata.nativeMetadataFormatName,
--                                   metadata1.getAsTree(J2KMetadata.nativeMetadataFormatName));
--            }
--
--            writeMetadata(metadata);
--	} else {
--	    encoder.setEncodeCodeStreamOnly();
--        }
--
--        for (int y = getMinTileY(); y <= getMaxTileY(); y++) {
--            for (int x = getMinTileX(); x <= getMaxTileX(); x++) {
--                Raster currentTile = getTile(x, y);
--                int sourceFormatTag =
--                    MediaLibAccessor.findCompatibleTag(currentTile);
--
--                MediaLibAccessor accessor =
--                    new MediaLibAccessor(currentTile,
--                                         currentTile.getBounds(),
--                                         sourceFormatTag, true);
--                mediaLibImage[] mlImage = accessor.getMediaLibImages();
--
--                encoder.encode(mlImage, x + y * size.nxtiles);
--                float percentage =
--                    (x + y * size.nxtiles + 1.0F) / (size.nxtiles * size.nytiles);
--                processImageProgress(percentage * 100.0F);
--            }
--        }
--    }
--
--    public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType,
--                                               ImageWriteParam param) {
--        return new J2KMetadata(imageType, param, this);
--    }
--
--    public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
--        return null;
--    }
--
--    public IIOMetadata convertImageMetadata(IIOMetadata inData,
--                                            ImageTypeSpecifier imageType,
--                                            ImageWriteParam param) {
--        // Check arguments.
--        if(inData == null) {
--            throw new IllegalArgumentException("inData == null!");
--        }
--        if(imageType == null) {
--            throw new IllegalArgumentException("imageType == null!");
--        }
--
--        // If it's one of ours, return a clone.
--        if (inData instanceof J2KMetadata) {
--            return (IIOMetadata)((J2KMetadata)inData).clone();
--        }
--
--        try {
--            J2KMetadata outData = new J2KMetadata();
--
--            List formats = Arrays.asList(inData.getMetadataFormatNames());
--
--            String format = null;
--            if(formats.contains(J2KMetadata.nativeMetadataFormatName)) {
--                // Initialize from native image metadata format.
--                format = J2KMetadata.nativeMetadataFormatName;
--            } else if(inData.isStandardMetadataFormatSupported()) {
--                // Initialize from standard metadata form of the input tree.
--                format = IIOMetadataFormatImpl.standardMetadataFormatName;
--            }
--
--            if(format != null) {
--                outData.setFromTree(format, inData.getAsTree(format));
--                return outData;
--            }
--        } catch(IIOInvalidTreeException e) {
--            return null;
--        }
--
--        return null;
--    }
--
--    public boolean canWriteRasters() {
--        return true;
--    }
--
--    public synchronized void abort() {
--        super.abort();
--    }
--
--    public void reset() {
--        // reset local Java structures
--        super.reset();
--        stream = null;
--    }
--
--    /** This method wraps the protected method <code>abortRequested</code>
--     *  to allow the abortions be monitored by <code>J2KRenderedImage</code>.
--     */
--    public boolean getAbortRequest() {
--        return abortRequested();
--    }
--
--    private void checkSampleModel(SampleModel sm) {
--        int type = sm.getDataType();
--
--        if (type < DataBuffer.TYPE_BYTE || type > DataBuffer.TYPE_INT)
--            throw new IllegalArgumentException(I18N.getString("J2KImageWriter5"));
--        if (sm.getNumBands() > 16384)
--            throw new IllegalArgumentException(I18N.getString("J2KImageWriter6"));
--    }
--
--    private void writeMetadata(J2KMetadata metadata) throws IOException {
--        if (metadata == null)
--            return;
--
--        IIOMetadataNode root =
--            (IIOMetadataNode)metadata.getAsTree("com_sun_media_imageio_plugins_jpeg2000_image_1.0");
--        if (root == null)
--            return;
--        format =
--            (J2KMetadataFormat)metadata.getMetadataFormat("com_sun_media_imageio_plugins_jpeg2000_image_1.0");
--        writeSuperBox(root);
--    }
--
--    private void writeSuperBox(IIOMetadataNode node) throws IOException {
--        NodeList list = node.getChildNodes();
--
--        String name = node.getNodeName();
--        if (name.startsWith("JPEG2000")) {
--/*
--            int length = computeLength(node);
--            byte[] data = new byte[length];
--            generateSuperBoxContent(node, data, 0);
--            com.sun.medialib.codec.jp2k.Box box =
--                new com.sun.medialib.codec.jp2k.Box();
--            box.data = data;
--            box.type = Box.getTypeInt((String)Box.getTypeByName(name));
--            encoder.encodeSuperBox(box.type, new com.sun.medialib.codec.jp2k.Box[]{box});
--            return;
--*/
--/*
--            com.sun.medialib.codec.jp2k.Box box =
--                new com.sun.medialib.codec.jp2k.Box();
--            box.type = Box.getTypeInt((String)Box.getTypeByName(name));
--            encoder.encodeSuperBox(box.type, null);
--*/
--        }
--
--        for (int i = 0; i < list.getLength(); i++) {
--            IIOMetadataNode child = (IIOMetadataNode)list.item(i);
--
--            name = child.getNodeName();
--            if (name.startsWith("JPEG2000") && format.isLeaf(name))
--                writeBox(child);
--            else
--                writeSuperBox(child);
--        }
--    }
--
--    private void writeBox(IIOMetadataNode node) throws IOException {
--        com.sun.medialib.codec.jp2k.Box mlibBox =
--            new com.sun.medialib.codec.jp2k.Box();
--        mlibBox.type = Box.getTypeInt((String)Box.getAttribute(node, "Type"));
--        Box box = Box.createBox(mlibBox.type, node);
--        mlibBox.data = box.getContent();
--        encoder.encodeBox(mlibBox);
--    }
--
--    private int computeLength(IIOMetadataNode root) {
--        NodeList list = root.getChildNodes();
--        int length = 0;
--        for (int i = 0; i < list.getLength(); i++) {
--            IIOMetadataNode node = (IIOMetadataNode)list.item(i);
--            String name = node.getNodeName();
--
--            if (format.isLeaf(name)) {
--                String s = (String)Box.getAttribute(node, "Length");
--                length += new Integer(s).intValue();
--            } else
--                length += computeLength(node);
--
--        }
--
--        return length + (root.getNodeName().startsWith("JPEG2000") ? 8 : 0) ;
--    }
--
--    private int generateSuperBoxContent(IIOMetadataNode root,
--                                        byte[] data,
--                                        int pos) throws IOException {
--        String name = root.getNodeName();
--        if (name.startsWith("JPEG2000")) {
--            int length = computeLength(root);
--            Box.copyInt(data, pos, length);
--            pos += 4;
--            int type = Box.getTypeInt((String)Box.getTypeByName(name));
--            Box.copyInt(data, pos, type);
--            pos += 4;
--        }
--
--        NodeList list = root.getChildNodes();
--        for (int i = 0; i < list.getLength(); i++) {
--            IIOMetadataNode node = (IIOMetadataNode)list.item(i);
--            name = node.getNodeName();
--
--            if (format.isLeaf(name)) {
--                int type =
--                    Box.getTypeInt((String)Box.getAttribute(node, "Type"));
--                Box box = Box.createBox(type, node);
--                byte[] data1 = box.getContent();
--                Box.copyInt(data, pos, data1.length + 8);
--                pos += 4;
--
--                Box.copyInt(data, pos, type);
--                pos += 4;
--                System.arraycopy(data1, 0, data, pos, data1.length);
--                pos += data1.length;
--            } else {
--                pos = generateSuperBoxContent(node, data, pos);
--            }
--        }
--
--        return pos;
--    }
--
--    private Raster getTile(int tileX, int tileY) {
--        int sx = tileXOffset + tileX * tileWidth;
--        int sy = tileYOffset + tileY * tileHeight;
--        Rectangle bounds = new Rectangle(sx, sy, tileWidth, tileHeight);
--
--        if (writeRaster) {
--            bounds = bounds.intersection(destinationRegion);
--            if (noTransform) {
--                return inputRaster.createChild(bounds.x, bounds.y,
--                                           bounds.width, bounds.height,
--                                           bounds.x, bounds.y, sourceBands);
--            }
--
--            sx = bounds.x;
--            sy = bounds.y;
--            WritableRaster ras =
--                Raster.createWritableRaster(sampleModel, new Point(sx, sy));
--
--            int x = mapToSourceX(sx);
--            int y = mapToSourceY(sy);
--
--            int minY = inputRaster.getMinY();
--            int maxY = inputRaster.getMinY() + inputRaster.getHeight();
--
--            int cTileWidth = bounds.width;
--
--            int length = (cTileWidth - 1) * scaleX + 1;
--
--            for (int j = 0; j < bounds.height; j++, sy++, y += scaleY) {
--                if (y < minY || y >= maxY)
--                    continue;
--                Raster source =
--                    inputRaster.createChild(x, y, length, 1,
--                                            x, y, null);
--                int tempX = sx;
--                for (int i = 0, offset = x; i < cTileWidth;
--                    i++, tempX++, offset += scaleX) {
--                    for (int k = 0; k < numComp; k++) {
--                        int p = source.getSample(offset, y, sourceBands[k]);
--                        ras.setSample(tempX, sy, k, p);
--                    }
--                }
--            }
--
--            return ras;
--
--        } else {
--            if (noTransform) {
--                Raster ras = input.getTile(tileX, tileY);
--                if (destinationRegion.contains(bounds) && noSubband)
--                    return ras;
--                else {
--                    bounds = bounds.intersection(destinationRegion);
--                    return ras.createChild(bounds.x, bounds.y,
--                                           bounds.width, bounds.height,
--                                           bounds.x, bounds.y, sourceBands);
--                }
--            }
--
--            bounds = bounds.intersection(destinationRegion);
--            sx = bounds.x;
--            sy = bounds.y;
--
--            WritableRaster ras =
--                Raster.createWritableRaster(sampleModel, new Point(sx, sy));
--
--            int x = mapToSourceX(sx);
--            int y = mapToSourceY(sy);
--
--            int minY = input.getMinY();
--            int maxY = input.getMinY() + input.getHeight();
--
--            int cTileWidth = bounds.width;
--            int length = (cTileWidth -1) * scaleX + 1;
--
--            for (int j = 0; j < bounds.height; j++, sy++, y += scaleY) {
--                if (y < minY || y >= maxY)
--                    continue;
--
--                Raster source =
--                    input.getData(new Rectangle(x, y, length, 1));
--
--                int tempX = sx;
--                for (int i = 0, offset = x; i < cTileWidth;
--                    i++, tempX++, offset += scaleX) {
--                    for (int k = 0; k < numComp; k++) {
--                        int p = source.getSample(offset, y, sourceBands[k]);
--                        ras.setSample(tempX, sy, k, p);
--                    }
--                }
--            }
--            return ras;
--        }
--    }
--
--    private int mapToSourceX(int x) {
--        return x * scaleX + xOffset;
--    }
--
--    private int mapToSourceY(int y) {
--        return y * scaleY + yOffset;
--    }
--
--    private int getMinTileX() {
--        return ToTile(destinationRegion.x, tileXOffset, tileWidth);
--    }
--
--    private int getMaxTileX() {
--        return ToTile(destinationRegion.x + destinationRegion.width - 1,
--                      tileXOffset, tileWidth);
--    }
--
--    private int getMinTileY() {
--        return ToTile(destinationRegion.y, tileYOffset, tileHeight);
--    }
--
--    private int getMaxTileY() {
--        return ToTile(destinationRegion.y + destinationRegion.height - 1,
--                      tileYOffset, tileHeight);
--    }
--
--    private static int ToTile(int pos, int tileOffset, int tileSize) {
--        pos -= tileOffset;
--        if (pos < 0) {
--            pos += 1 - tileSize;         // force round to -infinity (ceiling)
--        }
--        return pos/tileSize;
--    }
--
--    private void setSize() {
--        size = new Size();
--        size.csize = numComp;
--        size.nxtiles = getMaxTileX() - getMinTileX() + 1;
--        size.nytiles = getMaxTileY() - getMinTileY() + 1;
--
--        size.xosize = destinationRegion.x;
--        size.yosize = destinationRegion.y;
--        size.xsize = destinationRegion.width + destinationRegion.x;
--        size.ysize = destinationRegion.height + destinationRegion.y;
--        size.xtosize = tileXOffset;
--        size.ytosize = tileYOffset;
--        size.xtsize = tileWidth;
--        size.ytsize = tileHeight;
--
--        encoder.setSize(size);
--    }
--
--    private void setCompParameters(ColorModel colorModel,
--                                   SampleModel sampleModel,
--                                   ImageWriteParam compParamArg) {
--        // Check the parameters.
--        if (colorModel == null && sampleModel == null &&
--            (compParamArg == null ||
--             !(compParamArg instanceof J2KImageWriteParam))) {
--            return;
--        }
--
--        // Get the bit depths.
--        int[] bitDepths = null;
--        boolean isSigned = false;
--        if(colorModel != null) {
--            bitDepths = colorModel.getComponentSize();
--            isSigned = colorModel.getTransferType() == DataBuffer.TYPE_SHORT;
--        } else if(sampleModel != null) {
--            bitDepths = sampleModel.getSampleSize();
--            isSigned = sampleModel.getDataType() == DataBuffer.TYPE_SHORT;
--        }
--
--        // Get the number of decomposition levels.
--        int numDecompositionLevels = -1;
--        if(compParamArg != null) {
--            // Cast is safe due to parameter check above.
--            numDecompositionLevels =
--                ((J2KImageWriteParam)compParamArg).getNumDecompositionLevels();
--        }
--
--        // Return if nothing to set.
--        if(bitDepths == null && numDecompositionLevels == -1) return;
--
--        // Check for unequal bit depths.
--        boolean bitDepthVaries = false;
--        if(bitDepths != null) {
--            for(int i = 1; i < bitDepths.length; i++) {
--                if(bitDepths[i] != bitDepths[0]) {
--                    bitDepthVaries = true;
--                    break;
--                }
--            }
--        }
--
--        CompParams cp = encoder.getCompParams(null, -1);
--
--        // Update the COD segment if needed.
--        if((numDecompositionLevels != -1 &&
--            numDecompositionLevels != cp.maxlvls) ||
--           (bitDepths != null &&
--            ((isSigned ? 0x80 : 0x00) | (bitDepths[0] - 1)) != cp.depth)) {
--
--            if(numDecompositionLevels != -1) {
--                cp.maxlvls = numDecompositionLevels;
--            }
--
--            // Set the main COD bit depth to bitDepths[0].
--            if(bitDepths != null) {
--                cp.depth = (isSigned ? 0x80 : 0x00) | (bitDepths[0] - 1);
--            }
--
--            encoder.setCompParams(cp, -1);
--        }
--
--        // Update COC segments if needed.
--        if(bitDepthVaries) { // only true if bitDepths != null
--            // Loop over component zero even though unnecessary.
--            for(int i = 0; i < numComp; i++) {
--                cp = encoder.getCompParams(null, i);
--
--                if(numDecompositionLevels != -1) {
--                    cp.maxlvls = numDecompositionLevels;
--                }
--
--                cp.depth = (isSigned ? 0x80 : 0x00) | (bitDepths[i] - 1);
--
--                encoder.setCompParams(cp, i);
--            }
--        }
--    }
--
--    private void setParameters(ImageWriteParam paramArg) {
--        if (paramArg == null ||
--            !(paramArg instanceof J2KImageWriteParam)) {
--            return;
--        }
--
--        J2KImageWriteParam param = (J2KImageWriteParam)paramArg;
--
--        // set the rate
--        double rate = param.getEncodingRate();
--        if (rate != Double.MAX_VALUE) {
--            // convert the rate to the medialib definition
--            rate /= ImageUtil.getElementSize(sampleModel);
--            encoder.setRate(rate, 0);
--        } else
--            encoder.setRate(0.0, 0);
--
--        Params params = new Params();
--
--        // set the component transformation flag
--        params.enablemct = param.getComponentTransformation() ?
--                            Constants.JP2K_MCT_ENABLE :
--                            Constants.JP2K_MCT_DISABLE;
--
--        // set coding style
--        if (param.getEPH())
--            params.cstyle |= Constants.JP2K_COD_EPH;
--        if (param.getSOP())
--            params.cstyle |= Constants.JP2K_COD_SOP;
--
--        // set the wavelet filter type
--        if (J2KImageWriteParam.FILTER_53.equals(param.getFilter()))
--            params.wavemode = Constants.JP2K_WAVEMODE_53;
--        else if (J2KImageWriteParam.FILTER_97.equals(param.getFilter()))
--            params.wavemode = Constants.JP2K_WAVEMODE_97;
--
--        //Set the progressive mode
--        String progressiveType = param.getProgressionType();
--
--        if ("layer".equals(progressiveType))
--            params.prgorder = Constants.JP2K_COD_LRCPPRG;
--        if ("res".equals(progressiveType))
--            params.prgorder = Constants.JP2K_COD_RLCPPRG;
--        if ("res-pos".equals(progressiveType))
--            params.prgorder = Constants.JP2K_COD_RPCLPRG;
--        if ("pos-comp".equals(progressiveType))
--            params.prgorder = Constants.JP2K_COD_PCRLPRG;
--        if ("comp-pos".equals(progressiveType))
--            params.prgorder = Constants.JP2K_COD_CPRLPRG;
--
--        encoder.setParams(params);
--    }
--}
--
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterCodecLibSpi.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterCodecLibSpi.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,180 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: J2KImageWriterCodecLibSpi.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.2 $
-- * $Date: 2006/03/31 19:43:39 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.jpeg2000;
--
--import java.awt.image.DataBuffer;
--import java.awt.image.SampleModel;
--
--import javax.imageio.spi.ImageWriterSpi;
--import javax.imageio.spi.ServiceRegistry;
--import javax.imageio.spi.IIORegistry;
--import javax.imageio.ImageWriter;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.IIOException;
--
--import java.awt.image.ColorModel;
--import java.awt.image.IndexColorModel;
--import java.util.Locale;
--
--import com.sun.media.imageioimpl.common.PackageUtil;
--
--public class J2KImageWriterCodecLibSpi extends ImageWriterSpi {
--    private static String [] readerSpiNames =
--        {"com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderCodecLibSpi"};
--    private static String[] formatNames =
--        {"jpeg 2000", "JPEG 2000", "jpeg2000", "JPEG2000"};
--    private static String[] extensions =
--        {"jp2"}; // Should add jpx or jpm
--    private static String[] mimeTypes = {"image/jp2", "image/jpeg2000"};
--
--    private boolean registered = false;
--
--    public J2KImageWriterCodecLibSpi() {
--        super(PackageUtil.getVendor(),
--              PackageUtil.getVersion(),
--              formatNames,
--              extensions,
--              mimeTypes,
--              "com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriterCodecLib",
--              STANDARD_OUTPUT_TYPE,
--              readerSpiNames,
--              false,
--              null, null,
--              null, null,
--              true,
--              "com_sun_media_imageio_plugins_jpeg2000_image_1.0",
--              "com.sun.media.imageioimpl.plugins.jpeg2000.J2KMetadataFormat",
--              null, null);
--    }
--
--    public String getDescription(Locale locale) {
--	String desc = PackageUtil.getSpecificationTitle() + 
--	    " natively-accelerated JPEG 2000 Image Writer";
--	return desc;
--    }
--
--    public void onRegistration(ServiceRegistry registry,
--                               Class category) {
--        if (registered) {
--            return;
--        }
--	
--        registered = true;
--
--        // Branch based on codecLib availability.
--        if(!PackageUtil.isCodecLibAvailable()) {
--            // Deregister provider.
--            registry.deregisterServiceProvider(this);
--        } else {
--            // Set pairwise ordering to give codecLib writer precedence.
--            Class javaWriterSPIClass = null;
--            try {
--                javaWriterSPIClass =
--                    Class.forName("com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriterSpi");
--            } catch(Throwable t) {
--                // Ignore it.
--            }
--
--            if(javaWriterSPIClass != null) {
--                Object javaWriterSPI =
--                    registry.getServiceProviderByClass(javaWriterSPIClass);
--                if(javaWriterSPI != null) {
--                    registry.setOrdering(category, this, javaWriterSPI);
--                }
--            }
--        }
--    }
--
--    public boolean canEncodeImage(ImageTypeSpecifier type) {
--        SampleModel sm = type.getSampleModel();
--        if (sm.getNumBands() > 16384)
--            return false;
--        if (sm.getDataType() < DataBuffer.TYPE_BYTE ||
--            sm.getDataType() > DataBuffer.TYPE_INT)
--            return false;
--        return true;
--    }
--
--    public ImageWriter createWriterInstance(Object extension)
--        throws IIOException {
--        return new J2KImageWriterCodecLib(this);
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterSpi.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterSpi.java	2012-08-22 20:24:05.000000000 +0000
-+++ bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KImageWriterSpi.java	2012-09-20 08:16:06.724187619 +0000
-@@ -96,8 +96,6 @@
- 
- import com.sun.media.imageioimpl.common.PackageUtil;
- 
--import com.sun.medialib.codec.jiio.Util;
--
- public class J2KImageWriterSpi extends ImageWriterSpi {
-     private static String [] readerSpiNames =
-         {"com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReaderSpi"};
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KRenderedImageCodecLib.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/J2KRenderedImageCodecLib.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,1056 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: J2KRenderedImageCodecLib.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.4 $
-- * $Date: 2006/10/03 23:40:14 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.jpeg2000;
--
--import javax.imageio.IIOException;
--import javax.imageio.ImageReadParam;
--import javax.imageio.stream.ImageInputStream;
--
--import java.awt.Point;
--import java.awt.Rectangle;
--import java.awt.Transparency;
--import java.awt.color.ColorSpace;
--import java.awt.color.ICC_ColorSpace;
--import java.awt.color.ICC_Profile;
--import java.awt.image.BufferedImage;
--import java.awt.image.ColorModel;
--import java.awt.image.ComponentColorModel;
--import java.awt.image.ComponentSampleModel;
--import java.awt.image.DataBuffer;
--import java.awt.image.DirectColorModel;
--import java.awt.image.IndexColorModel;
--import java.awt.image.MultiPixelPackedSampleModel;
--import java.awt.image.PixelInterleavedSampleModel;
--import java.awt.image.SinglePixelPackedSampleModel;
--import java.awt.image.Raster;
--import java.awt.image.RenderedImage;
--import java.awt.image.SampleModel;
--import java.awt.image.WritableRaster;
--
--import java.io.IOException;
--
--import java.lang.reflect.Constructor;
--import java.lang.reflect.Method;
--import java.lang.reflect.InvocationTargetException;
--
--import com.sun.medialib.codec.jp2k.CompParams;
--import com.sun.medialib.codec.jp2k.Constants;
--import com.sun.medialib.codec.jp2k.Decoder;
--import com.sun.medialib.codec.jp2k.Size;
--import com.sun.medialib.codec.jiio.mediaLibImage;
--
--import com.sun.media.imageio.plugins.jpeg2000.J2KImageReadParam;
--import com.sun.media.imageioimpl.common.SimpleRenderedImage;
--import com.sun.media.imageioimpl.common.ImageUtil;
--
--// XXX Overall documentation
--
--public class J2KRenderedImageCodecLib extends SimpleRenderedImage {
--    /** The sample model for the original image. */
--    private SampleModel originalSampleModel;
--
--    private Raster currentTile;
--    private Point currentTileGrid;
--    private J2KMetadata metadata;
--
--    /** The input stream we read from */
--    private ImageInputStream iis = null;
--
--    /** Caches the <code>J2KImageReader</code> which creates this object.  This
--     *  variable is used to monitor the abortion.
--     */
--    private J2KImageReaderCodecLib reader;
--
--    /** The <code>J2KImageReadParam</code> to create this
--     *  <code>renderedImage</code>.
--     */
--    private J2KImageReadParam param = null;
--
--    /** Caches the medialib decoder. */
--    private Decoder decoder;
--    private Size size;
--    private CompParams compParam;
--    private int xStep, yStep; // JPEG 2000 internal subsampling parameters
--
--    /** The destination bounds. */
--    Rectangle destinationRegion;
--    Rectangle originalRegion;
--    Point sourceOrigin;
--
--    /** The subsampling parameters. */
--    private int scaleX, scaleY, xOffset, yOffset;
--    private int[] destinationBands = null;
--    private int[] sourceBands = null;
--    private int nComp;
--    private int[] channelMap;
--
--    /** Coordinate transform is not needed from the source (image stream)
--     *  to the destination.
--     */
--    private boolean noTransform = true;
--
--    /** The raster for medialib tiles to share. */
--    private WritableRaster rasForATile;
--
--    private BufferedImage destImage;
--
--    public J2KRenderedImageCodecLib(ImageInputStream iis,
--                                    J2KImageReaderCodecLib reader,
--                                    ImageReadParam param) throws IOException {
--        this.iis = iis;
--        this.reader = reader;
--
--        // Ensure the ImageReadParam is a J2KImageReadParam
--        boolean allowZeroDestOffset = true;
--        if(param == null) {
--            // Use the default
--            param = (J2KImageReadParam)reader.getDefaultReadParam();
--            allowZeroDestOffset = false;
--        } else if(!(param instanceof J2KImageReadParam)) {
--            // Create a new one
--            param = new J2KImageReadParamJava(param);
--            allowZeroDestOffset = false;
--        }
--        this.param = (J2KImageReadParam)param;
--
--        decoder = new Decoder(iis);
--
--        decoder.setMode(Constants.JP2K_COMPOSITE_TILE);
--
--        //set resolution before any calling of any calling for decode/decodeSize
--        int resolution = ((J2KImageReadParam)param).getResolution();
--        if (resolution != -1)
--            decoder.setMaxLevels(resolution);
--
--        size = decoder.decodeSize(null);
--
--        compParam = new CompParams();
--        for (int i = 0; i < size.csize; i++) {
--            decoder.decodeCompParams(compParam, i);
--            if(i == 0) {
--                xStep = compParam.xstep;
--                yStep = compParam.ystep;
--            } else if(compParam.xstep != xStep || compParam.ystep != yStep) {
--                // All components must have same subsampling along each axis.
--                throw new IIOException
--                    ("All components must have the same subsampling factors!");
--            }
--        }
--
--        // Set source sub-banding.
--        sourceBands = param.getSourceBands();
--        if (sourceBands == null) {
--            nComp = size.csize;
--            sourceBands = new int[nComp];
--            for (int i = 0; i < nComp; i++)
--                sourceBands[i] = i;
--        } else {
--            for(int i = 0; i < sourceBands.length; i++) {
--                if(sourceBands[i] < 0 ||
--                   sourceBands[i] >= size.csize) {
--                    throw new IIOException
--                        ("Source band out of range!");
--                }
--            }
--        }
--
--        // Cache number of components.
--        nComp = sourceBands.length;
--
--        // Set destination sub-banding.
--        destinationBands = param.getDestinationBands();
--        if (destinationBands == null) {
--            destinationBands = new int[nComp];
--            for (int i = 0; i < nComp; i++)
--                destinationBands[i] = i;
--        } else {
--            for(int i = 0; i < destinationBands.length; i++) {
--                if(destinationBands[i] < 0 ||
--                   destinationBands[i] >= size.csize) {
--                    throw new IIOException
--                        ("Destination band out of range!");
--                }
--            }
--        }
--
--        // Check number of source and dest bands.
--        if(destinationBands.length != sourceBands.length) {
--                throw new IIOException
--                    ("Number of source and destination bands must be equal!");
--        }
--
--        this.width = (size.xosize + size.xsize + xStep - 1)/xStep;
--        this.height = (size.yosize + size.ysize + yStep - 1)/yStep;
--
--        Rectangle sourceRegion =
--                new Rectangle(0, 0, this.width, this.height);
--
--        originalRegion = (Rectangle)sourceRegion.clone();
--
--        destinationRegion = (Rectangle)sourceRegion.clone();
--
--        J2KImageReader.computeRegionsWrapper(param,
--                                             allowZeroDestOffset,
--                                             this.width, this.height,
--                                             param.getDestination(),
--                                             sourceRegion,
--                                             destinationRegion);
--        scaleX = param.getSourceXSubsampling();
--        scaleY = param.getSourceYSubsampling();
--        xOffset = param.getSubsamplingXOffset();
--        yOffset = param.getSubsamplingYOffset();
--
--        sourceOrigin = new Point(sourceRegion.x, sourceRegion.y);
--        if (!destinationRegion.equals(originalRegion))
--            noTransform = false;
--
--        this.tileWidth = (size.xtsize + xStep - 1)/xStep;
--        this.tileHeight = (size.ytsize + yStep - 1)/yStep;
--        this.tileGridXOffset =
--            (size.xtosize + xStep - 1)/xStep - (size.xosize + xStep - 1)/xStep;
--        this.tileGridYOffset =
--            (size.ytosize + yStep - 1)/yStep - (size.yosize + yStep - 1)/yStep;
--
--        this.width = destinationRegion.width;
--        this.height = destinationRegion.height;
--        this.minX = destinationRegion.x;
--        this.minY = destinationRegion.y;
--
--        originalSampleModel = createOriginalSampleModel();
--        sampleModel = createSampleModel();
--        colorModel = createColorModel();
--        tileGridXOffset +=
--          (XToTileX(minX) - XToTileX(tileGridXOffset)) * tileWidth;
--        tileGridYOffset +=
--          (YToTileY(minY) - YToTileY(tileGridYOffset)) * tileHeight;
--
--        // sets the resolution and decoding rate to the medialib decoder
--        // Java decoding rate is in bit-per-pixel; the medialib rate is in
--        // percentage; so convert first.
--        double rate = ((J2KImageReadParam)param).getDecodingRate();
--        if (rate != Double.MAX_VALUE) {
--            // XXX Obtain bits per sample from elsewhere, e.g., ColorModel.
--            rate /= ImageUtil.getElementSize(sampleModel);
--            decoder.setRate(rate, 0);
--        }
--    }
--
--    public synchronized Raster getTile(int tileX, int tileY) {
--        if (currentTile != null &&
--            currentTileGrid.x == tileX &&
--            currentTileGrid.y == tileY)
--            return currentTile;
--
--        if (tileX < getMinTileX() || tileY < getMinTileY() ||
--            tileX > getMaxTileX() || tileY > getMaxTileY())
--            throw new IllegalArgumentException(I18N.getString("J2KReadState1"));
--
--        int x = tileXToX(tileX);
--        int y = tileYToY(tileY);
--        currentTile = Raster.createWritableRaster(sampleModel,
--                                                  new Point(x, y));
--
--        try {
--            readAsRaster((WritableRaster)currentTile);
--        } catch(IOException ioe) {
--            throw new RuntimeException(ioe);
--        }
--
--        if (currentTileGrid == null)
--            currentTileGrid = new Point(tileX, tileY);
--        else {
--            currentTileGrid.x = tileX;
--            currentTileGrid.y = tileY;
--        }
--
--        return currentTile;
--    }
--
--    synchronized WritableRaster readAsRaster(WritableRaster raster)
--        throws IOException {
--        int x = raster.getMinX();
--        int y = raster.getMinY();
--
--        try {
--            if (noTransform) {
--                int E2c = (size.xosize + xStep - 1)/xStep;
--                int E1c = (size.yosize + yStep - 1)/yStep;
--
--                int tXStart =
--                    ((x + E2c)*xStep - size.xtosize)/size.xtsize;
--                int tXEnd =
--                    ((x + raster.getWidth() - 1 + E2c)*xStep - size.xtosize)/
--                    size.xtsize;
--                int tYStart =
--                    ((y + E2c)*yStep - size.ytosize)/size.ytsize;
--                int tYEnd =
--                    ((y + raster.getHeight() - 1 + E2c)*yStep - size.ytosize)/
--                    size.ytsize;
--
--                int sourceFormatTag =
--                    MediaLibAccessor.findCompatibleTag(raster);
--
--                if(tXStart == tXEnd && tYStart == tYEnd) {
--                    MediaLibAccessor accessor =
--                        new MediaLibAccessor(raster,
--                                             raster.getBounds().intersection(originalRegion),
--                                             sourceFormatTag, true);
--
--                    mediaLibImage[] mlImage = accessor.getMediaLibImages();
--
--                    //this image may be a subregion of the image in the stream
--                    // So use the original tile number.
--                    int tileNo = tXStart + tYStart*size.nxtiles;
--                    decoder.decode(mlImage, tileNo);
--                    accessor.copyDataToRaster(channelMap);
--                } else {
--                    for(int ty = tYStart; ty <= tYEnd; ty++) {
--                        for(int tx = tXStart; tx <= tXEnd; tx++) {
--                            int sx = (size.xtosize + tx*size.xtsize +
--                                      xStep - 1)/xStep - E2c;
--                            int sy = (size.ytosize + ty*size.ytsize +
--                                      yStep - 1)/yStep - E1c;
--                            int ex = (size.xtosize + (tx + 1)*size.xtsize +
--                                      xStep - 1)/xStep - E2c;
--                            int ey = (size.ytosize + (ty + 1)*size.ytsize +
--                                      yStep - 1)/yStep - E1c;
--                            Rectangle subRect =
--                                new Rectangle(sx, sy, ex - sx, ey - sy);
--                            if(subRect.isEmpty()) {
--                                continue;
--                            }
--                            if (rasForATile == null) {
--                                rasForATile =
--                                    Raster.createWritableRaster
--                                    (originalSampleModel, null);
--                            }
--                            WritableRaster subRaster =
--                                rasForATile.createWritableChild
--                                (rasForATile.getMinX(),
--                                 rasForATile.getMinY(),
--                                 subRect.width, subRect.height,
--                                 subRect.x, subRect.y, null);
--                            MediaLibAccessor accessor =
--                                new MediaLibAccessor(subRaster,
--                                                     subRect,
--                                                     sourceFormatTag, true);
--
--                            mediaLibImage[] mlImage =
--                                accessor.getMediaLibImages();
--
--                            int tileNo = tx + ty*size.nxtiles;
--                            decoder.decode(mlImage, tileNo);
--                            accessor.copyDataToRaster(channelMap);
--
--                            Rectangle rasBounds = raster.getBounds();
--                            Rectangle childRect =
--                                rasBounds.intersection(subRect);
--                            if(childRect.isEmpty()) {
--                                continue;
--                            }
--
--                            Raster childRaster =
--                                subRaster.createChild(childRect.x, childRect.y,
--                                                      childRect.width,
--                                                      childRect.height,
--                                                      childRect.x, childRect.y,
--                                                      null);
--                            ((WritableRaster)raster).setRect(childRaster);
--                        }
--                    }
--                }
--            } else {
--                readSubsampledRaster(raster);
--            }
--        } catch (IOException e) {
--            throw new RuntimeException(e);
--        }
--
--        return raster;
--    }
--
--    private void readSubsampledRaster(WritableRaster raster)
--        throws IOException {
--
--        int numBands = sourceBands.length;
--
--        Rectangle destRect = raster.getBounds().intersection(destinationRegion);
--
--        int offx = destinationRegion.x;
--        int offy = destinationRegion.y;
--
--        int sourceSX = (destRect.x - offx) * scaleX + sourceOrigin.x;
--        int sourceSY = (destRect.y - offy) * scaleY + sourceOrigin.y;
--        int sourceEX = (destRect.width - 1) * scaleX + sourceSX;
--        int sourceEY = (destRect.height - 1)* scaleY + sourceSY;
--
--        int E2c = (size.xosize + xStep - 1)/xStep;
--        int E1c = (size.yosize + yStep - 1)/yStep;
--
--        int startXTile =
--            ((sourceSX + E2c)*xStep - size.xtosize)/size.xtsize;
--        int endXTile =
--            ((sourceEX + E2c)*xStep - size.xtosize)/size.xtsize;
--        int startYTile =
--            ((sourceSY + E1c)*yStep - size.ytosize)/size.ytsize;
--        int endYTile =
--            ((sourceEY + E1c)*yStep - size.ytosize)/size.ytsize;
--
--        startXTile = clip(startXTile, 0,  size.nxtiles - 1);
--        startYTile = clip(startYTile, 0, size.nytiles - 1);
--        endXTile = clip(endXTile, 0,  size.nxtiles - 1);
--        endYTile = clip(endYTile, 0, size.nytiles - 1);
--
--        int totalXTiles = endXTile - startXTile + 1;
--        int totalYTiles = endYTile - startYTile + 1;
--        int totalTiles = totalXTiles * totalYTiles;
--
--        int[] pixbuf = null;  // integer buffer for the decoded pixels.
--
--        // Start the data delivery to the cached consumers tile by tile
--        for(int y=startYTile; y <= endYTile; y++){
--            if (reader.getAbortRequest())
--                break;
--
--            // Loop on horizontal tiles
--            for(int x=startXTile; x <= endXTile; x++){
--                if (reader.getAbortRequest())
--                    break;
--
--                float percentage = // XXX Incorrect?
--                    (x - startXTile + 1.0F + y * totalXTiles) / totalTiles;
--
--                int startX =
--                    (x * size.xtsize + size.xtosize + xStep - 1)/xStep - E2c;
--                int startY =
--                    (y * size.ytsize + size.ytosize + yStep - 1)/yStep - E1c;
--                int endX =
--                    ((x + 1)*size.xtsize + size.xtosize + xStep - 1)/
--                    xStep - E2c;
--                int endY =
--                    ((y + 1)*size.ytsize + size.ytosize + yStep - 1)/
--                    yStep - E1c;
--
--                if (rasForATile == null) {
--                    rasForATile =
--                        Raster.createWritableRaster(originalSampleModel,
--                                                    new Point(startX, startY));
--                } else {
--                    rasForATile =
--                        rasForATile.createWritableTranslatedChild(startX, startY);
--                }
--
--                int tw = endX - startX;
--                int th = endY - startY;
--                WritableRaster targetRas;
--                if(tw != tileWidth || th != tileHeight) {
--                    targetRas = rasForATile.createWritableChild
--                        (startX, startY, tw, th, startX, startY, null);
--                } else {
--                    targetRas = rasForATile;
--                }
--
--                int sourceFormatTag =
--                    MediaLibAccessor.findCompatibleTag(targetRas);
--
--                MediaLibAccessor accessor =
--                    new MediaLibAccessor(targetRas,
--//                                         targetRas.getBounds(),
--                                         targetRas.getBounds().intersection(originalRegion),
--                                         sourceFormatTag, true);
--
--                mediaLibImage[] mlImage = accessor.getMediaLibImages();
--                decoder.decode(mlImage, x + y * size.nxtiles);
--                accessor.copyDataToRaster(channelMap);
--
--                int cTileHeight = th;
--                int cTileWidth = tw;
--
--                if (startY + cTileHeight >= originalRegion.height)
--                    cTileHeight = originalRegion.height - startY;
--
--                if (startX + cTileWidth >= originalRegion.width)
--                    cTileWidth = originalRegion.width - startX;
--
--                int tx = startX;
--                int ty = startY;
--
--                if (sourceSX > startX) {
--                    cTileWidth += startX - sourceSX;
--                    tx = sourceSX;
--                    startX = sourceSX;
--                }
--
--                if (sourceSY > startY) {
--                    cTileHeight += startY - sourceSY;
--                    ty = sourceSY;
--                    startY = sourceSY;
--                }
--
--                if (sourceEX < startX + cTileWidth - 1) {
--                    cTileWidth += sourceEX - startX - cTileWidth + 1;
--                }
--
--                if (sourceEY < startY + cTileHeight - 1) {
--                    cTileHeight += sourceEY - startY - cTileHeight + 1;
--                }
--
--                // The start X in the destination
--                int x1 = (startX + scaleX - 1 - sourceOrigin.x) / scaleX;
--                int x2 = (startX + scaleX -1 + cTileWidth - sourceOrigin.x) / scaleX;
--                int lineLength = x2 - x1;
--                // Suppress further processing if lineLength is non-positive
--                // XXX (which it should never be).
--                if(lineLength <= 0) continue;
--                x2 = (x2 - 1) * scaleX + sourceOrigin.x;
--
--                int y1 = (startY + scaleY -1 - sourceOrigin.y) /scaleY;
--                startY = y1 * scaleY + sourceOrigin.y;
--                startX = x1 * scaleX + sourceOrigin.x;
--
--                x1 += offx;
--                y1 += offy;
--
--                if (pixbuf == null || pixbuf.length < lineLength)
--                    pixbuf = new int[lineLength]; // line buffer for pixel data
--
--                // Deliver in lines to reduce memory usage
--                for (int l = startY, m = y1; l < ty + cTileHeight; l += scaleY, m++) {
--                    if (reader.getAbortRequest())
--                        break;
--
--                    // Request line data
--                    for (int i = 0; i < numBands; i++) {
--                        for (int j = lineLength - 1, k1 = x2; j >= 0; j--, k1-=scaleX) {
--                            pixbuf[j] = targetRas.getSample(k1, l, i);
--                        }
--
--                        // Send the line data to the BufferedImage
--                        raster.setSamples(x1, m, lineLength, 1, destinationBands[i], pixbuf);
--                    }
--
--                    if (destImage != null)
--                        reader.processImageUpdateWrapper(destImage, x1, m,
--                                                         cTileWidth, 1, 1, 1,
--                                                         destinationBands);
--
--                    reader.processImageProgressWrapper(percentage +
--                                                (l - startY + 1.0F) /
--                                                cTileHeight / totalTiles);
--		}
--            } // End loop on horizontal tiles
--        } // End loop on vertical tiles
--    }
--
--    public void setDestImage(BufferedImage image) {
--        destImage = image;
--    }
--
--    public void clearDestImage() {
--        destImage = null;
--    }
--
--    private int getTileNum(int x, int y) {
--        int num = (y - getMinTileY()) * getNumXTiles() + x - getMinTileX();
--
--        if (num < 0 || num >= getNumXTiles() * getNumYTiles())
--            throw new IllegalArgumentException(I18N.getString("J2KReadState1"));
--
--        return num;
--    }
--
--    private int clip(int value, int min, int max) {
--        if (value < min)
--            value = min;
--        if (value > max)
--            value = max;
--        return value;
--    }
--
--    private SampleModel createSampleModel() throws IOException {
--        if (sampleModel != null)
--            return sampleModel;
--
--        if (metadata == null)
--            readImageMetadata();
--
--        HeaderBox header = (HeaderBox)metadata.getElement("JPEG2000HeaderBox");
--        int maxDepth = 0;
--        boolean isSigned = false;
--        if (header != null) {
--            maxDepth = header.getBitDepth();
--            isSigned = (maxDepth & 0x80) > 0;
--            maxDepth = (maxDepth & 0x7F) + 1;
--        } else {
--            CompParams compParam = new CompParams();
--            for (int i = 0; i < size.csize; i++) {
--                decoder.decodeCompParams(compParam, i);
--                maxDepth = (compParam.depth & 0x7F) + 1;
--                isSigned = (compParam.depth & 0x80) > 0 ? true : false;
--            }
--        }
--
--        BitsPerComponentBox bits =
--            (BitsPerComponentBox)metadata.getElement("JPEG2000BitsPerComponentBox");
--
--        if (bits != null) {
--            byte[] depths = bits.getBitDepth();
--            maxDepth = (depths[0] & 0x7F) + 1;
--            isSigned = (depths[0] & 0x80) > 0;
--            for (int i = 1; i < nComp; i++)
--                if (maxDepth > depths[sourceBands[i]])
--                    maxDepth = (depths[sourceBands[i]] & 0x7F) + 1;
--        }
--
--        int[] bandOffsets = new int[nComp];
--        for (int i = 0; i < nComp; i++)
--            bandOffsets[i] = i;
--
--        ChannelDefinitionBox cdb=
--            (ChannelDefinitionBox)metadata.getElement("JPEG2000ChannelDefinitionBox");
--
--        if (cdb != null &&
--            metadata.getElement("JPEG2000PaletteBox") == null) {
--            short[] assoc = cdb.getAssociation();
--            short[] types = cdb.getTypes();
--            short[] channels = cdb.getChannel();
--
--            for (int i = 0; i < types.length; i++)
--                if (types[i] == 0)
--                    bandOffsets[sourceBands[channels[i]]] = assoc[i] - 1;
--                else if (types[i] == 1 || types[i] == 2)
--                    bandOffsets[sourceBands[channels[i]]] = channels[i];
--        }
--
--        return createSampleModel(nComp, maxDepth, bandOffsets,
--                                 isSigned, tileWidth, tileHeight);
--    }
--
--    private SampleModel createOriginalSampleModel() throws IOException {
--        if (metadata == null)
--            readImageMetadata();
--
--        HeaderBox header = (HeaderBox)metadata.getElement("JPEG2000HeaderBox");
--        int maxDepth = 0;
--        boolean isSigned = false;
--        int nc = size.csize;
--        if (header != null) {
--            maxDepth = header.getBitDepth();
--            isSigned = (maxDepth & 0x80) > 0;
--            maxDepth = (maxDepth & 0x7F) + 1;
--        } else {
--            CompParams compParam = new CompParams();
--            for (int i = 0; i < size.csize; i++) {
--                decoder.decodeCompParams(compParam, i);
--                maxDepth = (compParam.depth & 0x7F) + 1;
--                isSigned = (compParam.depth & 0x80) > 0 ? true : false;
--            }
--        }
--
--        BitsPerComponentBox bits =
--            (BitsPerComponentBox)metadata.getElement("JPEG2000BitsPerComponentBox");
--
--        if (bits != null) {
--            byte[] depths = bits.getBitDepth();
--            maxDepth = (depths[0] & 0x7F) + 1;
--            isSigned = (depths[0] & 0x80) > 0;
--            for (int i = 1; i < nc; i++)
--                if (maxDepth > depths[i])
--                    maxDepth = (depths[i] & 0x7F) + 1;
--        }
--
--        int[] bandOffsets = new int[nc];
--        for (int i = 0; i < nc; i++)
--            bandOffsets[i] = i;
--
--        ChannelDefinitionBox cdb=
--            (ChannelDefinitionBox)metadata.getElement("JPEG2000ChannelDefinitionBox");
--        if (cdb != null &&
--            metadata.getElement("JPEG2000PaletteBox") == null) {
--            short[] assoc = cdb.getAssociation();
--            short[] types = cdb.getTypes();
--            short[] channels = cdb.getChannel();
--
--            channelMap = new int[nc];
--
--            for (int i = 0; i < types.length; i++)
--                if (types[i] == 0) {
--                    bandOffsets[channels[i]] = assoc[i] - 1;
--                    channelMap[assoc[i] - 1] = channels[i];
--                }
--                else if (types[i] == 1 || types[i] == 2) {
--                    bandOffsets[channels[i]] = channels[i];
--                    channelMap[channels[i]] = channels[i];
--                }
--        }
--
--        return createSampleModel(nc, maxDepth, bandOffsets, isSigned,
--                                 tileWidth, tileHeight);
--    }
--
--    private SampleModel createSampleModel(int nc, int maxDepth,
--                                   int[] bandOffsets, boolean isSigned,
--                                   int tw, int th) {
--        SampleModel sm = null;
--        if (nc == 1 && (maxDepth == 1 || maxDepth == 2 || maxDepth == 4))
--            sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
--                                                    tw, th, maxDepth);
--        else if (maxDepth <= 8)
--            sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
--                                       tw, th, nc, tw * nc, bandOffsets);
--        else if (maxDepth <=16)
--            sm = new PixelInterleavedSampleModel(isSigned ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT,
--                                       tw, th, nc, tw * nc, bandOffsets);
--        else if (maxDepth <= 32)
--            sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_INT,
--                                       tw, th, nComp, tw * nComp,
--                                       bandOffsets);
--        else
--            throw new IllegalArgumentException(I18N.getString("J2KReadState11") + " " +
--						+ maxDepth);
--
--        return sm;
--    }
--
--    private ColorModel createColorModel() throws IOException {
--        if (colorModel != null)
--            return colorModel;
--
--        PaletteBox pBox = (PaletteBox)metadata.getElement("JPEG2000PaletteBox");
--        ChannelDefinitionBox cdef =
--            (ChannelDefinitionBox)metadata.getElement("JPEG2000ChannelDefinitionBox");
--
--        // Check 'nComp' instance variable here in case there is an
--        // embedded palette such as in the pngsuite images pp0n2c16.png
--        // and pp0n6a08.png.
--        if (pBox != null && nComp == 1) {
--            byte[][] lut = pBox.getLUT();
--            int numComp = pBox.getNumComp();
--
--            int[] mapping = new int[numComp];
--
--            for (int i = 0; i < numComp; i++)
--                mapping[i] = i;
--
--            ComponentMappingBox cmap =
--                (ComponentMappingBox)metadata.getElement("JPEG2000ComponentMappingBox");
--
--            short[] comps = null;
--            byte[] type = null;
--            byte[] maps = null;
--
--            if (cmap != null) {
--                comps = cmap.getComponent();
--                type = cmap.getComponentType();
--                maps = cmap.getComponentAssociation();
--            }
--
--            if (comps != null)
--                for (int i = 0; i < numComp; i++)
--                    if (type[i] == 1)
--                        mapping[i] = maps[i];
--
--            if (numComp == 3)
--                colorModel = new IndexColorModel(sampleModel.getSampleSize(0), lut[0].length,
--                                                 lut[mapping[0]],
--                                                 lut[mapping[1]],
--                                                 lut[mapping[2]]);
--            else if (numComp == 4)
--                colorModel = new IndexColorModel(sampleModel.getSampleSize(0), lut[0].length,
--                                                 lut[mapping[0]],
--                                                 lut[mapping[1]],
--                                                 lut[mapping[2]],
--                                                 lut[mapping[3]]);
--        } else if (cdef != null){
--            HeaderBox header =
--                (HeaderBox)metadata.getElement("JPEG2000HeaderBox");
--            int numComp = header.getNumComponents();
--            int bitDepth = header.getBitDepth();
--
--            boolean hasAlpha = false;
--            int alphaChannel = numComp - 1;
--
--            short[] channels = cdef.getChannel();
--            short[] cType = cdef.getTypes();
--            short[] associations = cdef.getAssociation();
--
--            for (int i = 0; i < channels.length; i++) {
--                if (cType[i] == 1 && channels[i] == alphaChannel)
--                    hasAlpha = true;
--            }
--
--            boolean[] isPremultiplied = new boolean[] {false};
--
--            if (hasAlpha) {
--                isPremultiplied = new boolean[alphaChannel];
--
--                for (int i = 0; i < alphaChannel; i++)
--                    isPremultiplied[i] = false;
--
--                for (int i = 0; i < channels.length; i++) {
--                    if (cType[i] == 2)
--                        isPremultiplied[associations[i] - 1] = true;
--                }
--
--                for (int i = 1; i < alphaChannel; i++)
--                    isPremultiplied[0] &= isPremultiplied[i];
--            }
--
--            ColorSpecificationBox cBox =
--                (ColorSpecificationBox)metadata.getElement("JPEG2000ColorSpecificationBox");
--            ICC_Profile profile = null;
--            int colorSpaceType = 0;
--
--            if (cBox != null) {
--                profile = cBox.getICCProfile();
--                colorSpaceType = cBox.getEnumeratedColorSpace();
--            }
--
--            ColorSpace cs = null;
--            if (profile != null)
--                cs = new ICC_ColorSpace(profile);
--            else if (colorSpaceType == ColorSpecificationBox.ECS_sRGB)
--                cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
--            else if (colorSpaceType == ColorSpecificationBox.ECS_GRAY)
--                cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
--            else if (colorSpaceType == ColorSpecificationBox.ECS_YCC)
--                cs = ColorSpace.getInstance(ColorSpace.CS_PYCC);
--
--            byte[] bitDepths = null;
--            boolean isSigned = ((bitDepth & 0x80) == 0x80) ? true : false;
--
--            BitsPerComponentBox bitBox =
--                (BitsPerComponentBox)metadata.getElement("JPEG2000BitsPerComponentBox");
--            if (bitBox != null)
--                bitDepths = bitBox.getBitDepth();
--
--            int[] bits = new int[numComp];
--            for (int i = 0; i < numComp; i++)
--                if (bitDepths != null)
--                    bits[i] = (bitDepths[i] & 0x7F) + 1;
--                else
--                    bits[i] = (bitDepth &0x7F) + 1;
--
--            int maxBitDepth = 1 + (bitDepth & 0x7F);
--            if (bitDepths != null)
--                for (int i = 0; i < numComp; i++)
--                    if (bits[i] > maxBitDepth)
--                        maxBitDepth = bits[i];
--
--            int type = -1;
--
--            if (maxBitDepth <= 8)
--                type = DataBuffer.TYPE_BYTE;
--            else if (maxBitDepth <= 16)
--                type = isSigned ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT;
--            else if (maxBitDepth <= 32)
--                type = DataBuffer.TYPE_INT;
--
--            if (type == -1)
--                return null;
--
--            if (cs != null) {
--                colorModel = new ComponentColorModel(cs,
--                                                 bits,
--                                                 hasAlpha,
--                                                 isPremultiplied[0],
--                                                 hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE ,
--                                                 type);
--            }
--        }
--
--        if (colorModel != null)
--            return colorModel;
--
--        if(nComp <= 4) {
--            // XXX: Code essentially duplicated from FileFormatReader.getColorModel().
--            // Create the ColorModel from the SIZ marker segment parameters.
--            ColorSpace cs;
--            if(nComp > 2) {
--                cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
--            } else {
--                cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
--            }
--
--            int[] bitsPerComponent = new int[nComp];
--            boolean isSigned = false;
--            int maxBitDepth = -1;
--            for(int i = 0; i < nComp; i++) {
--                bitsPerComponent[i] = (compParam.depth & 0x7f) + 1;
--                if(maxBitDepth < bitsPerComponent[i]) {
--                    maxBitDepth = bitsPerComponent[i];
--                }
--                isSigned |= (compParam.depth & 0x80) != 0;
--            }
--
--            boolean hasAlpha = nComp % 2 == 0;
--
--            int type = -1;
--
--            if (maxBitDepth <= 8) {
--                type = DataBuffer.TYPE_BYTE;
--            } else if (maxBitDepth <= 16) {
--                type = isSigned ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT;
--            } else if (maxBitDepth <= 32) {
--                type = DataBuffer.TYPE_INT;
--            }
--
--            if (type != -1) {
--                if (nComp == 1 &&
--                    (maxBitDepth == 1 || maxBitDepth == 2 ||
--                     maxBitDepth == 4)) {
--                    colorModel = ImageUtil.createColorModel(getSampleModel());
--                } else {
--                    colorModel = new ComponentColorModel(cs,
--                                                         bitsPerComponent,
--                                                         hasAlpha,
--                                                         false,
--                                                         hasAlpha ?
--                                                         Transparency.TRANSLUCENT :
--                                                         Transparency.OPAQUE ,
--                                                         type);
--                }
--
--                return colorModel;
--            }
--        }
--
--        return ImageUtil.createColorModel(null, getSampleModel());
--    }
--
--    public J2KMetadata readImageMetadata() throws IOException {
--        if (metadata == null) {
--            metadata = new J2KMetadata();
--            com.sun.medialib.codec.jp2k.Box mlibBox = null;
--            com.sun.media.imageioimpl.plugins.jpeg2000.Box box = null;
--
--            while ((mlibBox = decoder.decodeBox()) != null) {
--		box = null;
--                Class c = com.sun.media.imageioimpl.plugins.jpeg2000.Box.getBoxClass(mlibBox.type);
--                if (c != null) {
--                    try {
--                        Constructor cons = c.getConstructor(new Class[]{byte[].class});
--                        if (cons != null) {
--                             box = (Box)cons.newInstance(new Object[]{mlibBox.data});
--                        }
--                    } catch(NoSuchMethodException e) {
--                        try {
--                            Constructor cons = c.getConstructor(new Class[]{int.class, byte[].class});
--                            if (cons != null) {
--                                box = (com.sun.media.imageioimpl.plugins.jpeg2000.Box)
--                                      cons.newInstance(new Object[]{new Integer(mlibBox.type), mlibBox.data});
--                            }
--                        } catch (NoSuchMethodException e1) {
--                            box = createUnknowBox(mlibBox);
--                        } catch(InvocationTargetException e1) {
--                            box = createUnknowBox(mlibBox);
--                        } catch (IllegalAccessException e1) {
--                            box = createUnknowBox(mlibBox);
--                        } catch (InstantiationException e1) {
--                            box = createUnknowBox(mlibBox);
--                        }
--                    } catch(InvocationTargetException e) {
--                        box = createUnknowBox(mlibBox);
--                    } catch (IllegalAccessException e) {
--                        box = createUnknowBox(mlibBox);
--                    } catch (InstantiationException e) {
--                        box = createUnknowBox(mlibBox);
--                    }
--                } else {
--                    if (mlibBox.data != null)
--                        box = createUnknowBox(mlibBox);
--                }
--                if (box != null)
--                    metadata.addNode(box);
--            }
--        }
--
--        return metadata;
--    }
--
--    private com.sun.media.imageioimpl.plugins.jpeg2000.Box
--        createUnknowBox(com.sun.medialib.codec.jp2k.Box mlibBox) {
--        return
--            new com.sun.media.imageioimpl.plugins.jpeg2000.Box(8 + mlibBox.data.length,
--                                                           mlibBox.type,
--                                                           mlibBox.data);
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/MediaLibAccessor.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/jpeg2000/MediaLibAccessor.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,1258 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: MediaLibAccessor.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.1 $
-- * $Date: 2005/02/11 05:01:36 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.jpeg2000;
--import java.awt.Rectangle;
--import java.awt.image.ColorModel;
--import java.awt.image.ComponentSampleModel;
--import java.awt.image.ComponentColorModel;
--import java.awt.image.DataBuffer;
--import java.awt.image.DataBufferByte;
--import java.awt.image.DataBufferDouble;
--import java.awt.image.DataBufferFloat;
--import java.awt.image.DataBufferInt;
--import java.awt.image.DataBufferShort;
--import java.awt.image.DataBufferUShort;
--import java.awt.image.MultiPixelPackedSampleModel;
--import java.awt.image.Raster;
--import java.awt.image.SampleModel;
--import java.awt.image.WritableRaster;
--import java.awt.image.RenderedImage;
--import java.awt.image.renderable.ParameterBlock;
--import java.io.FileNotFoundException;
--import java.io.FilePermission;
--import java.io.InputStream;
--import java.io.IOException;
--import java.lang.NoClassDefFoundError;
--import java.security.AccessControlException;
--import java.security.AccessController;
--import java.security.PrivilegedAction;
--
--import com.sun.media.imageioimpl.common.ImageUtil;
--import com.sun.medialib.codec.jiio.Util;
--import com.sun.medialib.codec.jiio.Constants;
--import com.sun.medialib.codec.jiio.mediaLibImage;
--
--/**
-- *  An adapter class for presenting image data in a mediaLibImage
-- *  format, even if the data isn't stored that way.  MediaLibAccessor
-- *  is meant to make the common case (ComponentRasters) and allow
-- *  them to be accelerated via medialib.  Note that unlike RasterAccessor,
-- *  MediaLibAccessor does not work with all cases.  In the event that
-- *  MediaLibAccessor can not deal with a give collection of Rasters,
-- *  findCompatibleTag will return the value MediaLibAccessor.TAG_INCOMPATIBLE.
-- *  OpImages that use MediaLibAccessor should be paired with RIF's
-- *  which check that findCompatibleTag returns a valid tag before
-- *  actually constructing the Mlib OpImage.
-- */
--
--public class MediaLibAccessor {
--    /**
--     *  Value indicating how far COPY_MASK info is shifted to avoid
--     *  interfering with the data type info
--     */
--    private static final int COPY_MASK_SHIFT = 7;
--
--    /* Value indicating how many bits the COPY_MASK is */
--    private static final int COPY_MASK_SIZE = 1;
--
--    /** The bits of a FormatTag associated with how dataArrays are obtained. */
--    public static final int COPY_MASK = 0x1 << COPY_MASK_SHIFT;
--
--    /** Flag indicating data is raster's data. */
--    public static final int UNCOPIED = 0x0 << COPY_MASK_SHIFT;
--
--    /** Flag indicating data is a copy of the raster's data. */
--    public static final int COPIED = 0x01 << COPY_MASK_SHIFT;
--
--    /** The bits of a FormatTag associated with pixel datatype. */
--    public static final int DATATYPE_MASK = (0x1 << COPY_MASK_SHIFT) - 1;
--
--    /**
--     * Value indicating how far BINARY_MASK info is shifted to avoid
--     * interfering with the data type and copying info.
--     */
--    private static final int BINARY_MASK_SHIFT =
--        COPY_MASK_SHIFT+COPY_MASK_SIZE;
--
--    /** Value indicating how many bits the BINARY_MASK is */
--    private static final int BINARY_MASK_SIZE = 1;
--
--    /** The bits of a FormatTag associated with binary data. */
--    public static final int BINARY_MASK =
--        ((1 << BINARY_MASK_SIZE) - 1) << BINARY_MASK_SHIFT;
--
--    /** Flag indicating data are not binary. */
--    public static final int NONBINARY = 0x0 << BINARY_MASK_SHIFT;
--
--    /** Flag indicating data are binary. */
--    public static final int BINARY = 0x1 << BINARY_MASK_SHIFT;
--
--    /** FormatTag indicating data in byte arrays and uncopied. */
--    public static final int
--        TAG_BYTE_UNCOPIED = DataBuffer.TYPE_BYTE | UNCOPIED;
--
--    /** FormatTag indicating data in unsigned short arrays and uncopied. */
--    public static final int
--        TAG_USHORT_UNCOPIED = DataBuffer.TYPE_USHORT | UNCOPIED;
--
--    /** FormatTag indicating data in short arrays and uncopied. */
--    public static final int
--        TAG_SHORT_UNCOPIED = DataBuffer.TYPE_SHORT | UNCOPIED;
--
--    /** FormatTag indicating data in integer arrays and uncopied. */
--    public static final int
--        TAG_INT_UNCOPIED = DataBuffer.TYPE_INT | UNCOPIED;
--
--    /** FormatTag indicating data in float arrays and uncopied. */
--    public static final int
--        TAG_FLOAT_UNCOPIED = DataBuffer.TYPE_FLOAT | UNCOPIED;
--
--    /** FormatTag indicating data in double arrays and uncopied. */
--    public static final int
--        TAG_DOUBLE_UNCOPIED = DataBuffer.TYPE_DOUBLE | UNCOPIED;
--
--    /** FormatTag indicating data in byte arrays and uncopied. */
--    public static final int
--        TAG_BYTE_COPIED = DataBuffer.TYPE_BYTE | COPIED;
--
--    /** FormatTag indicating data in unsigned short arrays and copied. */
--    public static final int
--        TAG_USHORT_COPIED = DataBuffer.TYPE_USHORT | COPIED;
--
--    /** FormatTag indicating data in short arrays and copied. */
--    public static final int
--        TAG_SHORT_COPIED = DataBuffer.TYPE_SHORT | COPIED;
--
--    /** FormatTag indicating data in short arrays and copied. */
--    public static final int
--        TAG_INT_COPIED = DataBuffer.TYPE_INT | COPIED;
--
--    /** FormatTag indicating data in float arrays and copied. */
--    public static final int
--        TAG_FLOAT_COPIED = DataBuffer.TYPE_FLOAT | COPIED;
--
--    /** FormatTag indicating data in double arrays and copied. */
--    public static final int
--        TAG_DOUBLE_COPIED = DataBuffer.TYPE_DOUBLE | COPIED;
--
--    /** The raster that is the source of pixel data. */
--    protected Raster raster;
--
--    /** The rectangle of the raster that MediaLibAccessor addresses. */
--    protected Rectangle rect;
--
--    /** The number of bands per pixel in the data array. */
--    protected int numBands;
--
--    /** The offsets of each band in the src image */
--    protected int bandOffsets[];
--
--    /** Tag indicating the data type of the data and whether its copied */
--    protected int formatTag;
--
--    /** Area of mediaLib images that represent image data */
--    protected mediaLibImage mlimages[] = null;
--
--    /**
--     * Whether packed data are preferred when processing binary images.
--     * This tag is ignored if the data are not binary.
--     */
--    private boolean areBinaryDataPacked = false;
--
--    /**
--     *  Returns the most efficient FormatTag that is compatible with
--     *  the destination raster and all source rasters.
--     *
--     *  @param srcs the source <code>Raster</code>; may be <code>null</code>.
--     *  @param dst  the destination <code>Raster</code>.
--     */
--    public static int findCompatibleTag(Raster src) {
--        SampleModel dstSM = src.getSampleModel();
--        int dstDT = dstSM.getDataType();
--
--        int defaultDataType = dstSM.getDataType();
--
--        boolean allComponentSampleModel =
--             dstSM instanceof ComponentSampleModel;
--        boolean allBinary = ImageUtil.isBinary(dstSM);
--
--        if(allBinary) {
--            // The copy flag is not set until the mediaLibImage is
--            // created as knowing this information requires too much
--            // processing to determine here.
--            return DataBuffer.TYPE_BYTE | BINARY;
--        }
--
--        if (!allComponentSampleModel) {
--            if ((defaultDataType == DataBuffer.TYPE_BYTE) ||
--                (defaultDataType == DataBuffer.TYPE_USHORT) ||
--                (defaultDataType == DataBuffer.TYPE_SHORT)) {
--                defaultDataType = DataBuffer.TYPE_INT;
--            }
--        }
--
--        int tag = defaultDataType | COPIED;
--
--        if (!allComponentSampleModel) {
--            return tag;
--        }
--
--        if (isPixelSequential(dstSM))
--            return dstDT | UNCOPIED;
--        return tag;
--    }
--
--    /**
--     *  Determines if the SampleModel stores data in a way that can
--     *  be represented by a mediaLibImage without copying
--     */
--    public static boolean isPixelSequential(SampleModel sm) {
--        ComponentSampleModel csm = null;
--        if (sm instanceof ComponentSampleModel) {
--            csm = (ComponentSampleModel)sm;
--        } else {
--            return false;
--        }
--        int pixelStride = csm.getPixelStride();
--        int bandOffsets[] = csm.getBandOffsets();
--        int bankIndices[] = csm.getBankIndices();
--        if (pixelStride != bandOffsets.length) {
--            return false;
--        }
--
--        //XXX: for band-selection result
--        if (pixelStride != sm.getNumBands())
--            return false;
--
--        for (int i = 0; i < bandOffsets.length; i++) {
--            if (bandOffsets[i] >= pixelStride ||
--                bankIndices[i] != bankIndices[0]) {
--                return false;
--            }
--            for (int j = i+1; j < bandOffsets.length; j++) {
--               if (bandOffsets[i] == bandOffsets[j]) {
--                   return false;
--               }
--
--               //XXX: for BGR images
--               if (bandOffsets[i] != i)
--                  return false;
--            }
--        }
--        return true;
--    }
--
--    public static int getMediaLibDataType(int formatTag) {
--        int dataType = formatTag & DATATYPE_MASK;
--        switch (dataType) {
--            case DataBuffer.TYPE_BYTE:
--                return Constants.MLIB_BYTE;
--            case DataBuffer.TYPE_USHORT:
--                return Constants.MLIB_USHORT;
--            case DataBuffer.TYPE_SHORT:
--                return Constants.MLIB_SHORT;
--            case DataBuffer.TYPE_INT:
--                return Constants.MLIB_INT;
--            case DataBuffer.TYPE_DOUBLE:
--                return Constants.MLIB_DOUBLE;
--            case DataBuffer.TYPE_FLOAT:
--                return Constants.MLIB_FLOAT;
--        }
--        return -1;
--    }
--
--    /**
--     *  Constructs a MediaLibAccessor object out of a Raster, Rectangle
--     *  and formatTag returned from MediaLibAccessor.findCompatibleTag().
--     *
--     *  In the case of binary data the copy mask bits of the formatTag
--     *  will be reset within the constructor according to whether the
--     *  data are in fact copied. This cannot be easily determined before
--     *  the data are actually copied.
--     */
--    public MediaLibAccessor(Raster raster, Rectangle rect, int formatTag,
--                            boolean preferPacked) {
--        areBinaryDataPacked = preferPacked;
--
--        this.raster = raster;
--        this.rect = new Rectangle(rect);
--        this.formatTag = formatTag;
--
--        if(isBinary()) {
--            // Set binary-specific fields and return.
--            numBands = 1;
--            bandOffsets = new int[] {0};
--
--            int mlibType;
--            int scanlineStride;
--            byte[] bdata;
--            mlimages = new mediaLibImage[1];
--
--            if(areBinaryDataPacked) {
--                mlibType = Constants.MLIB_BIT;
--                scanlineStride = (rect.width+7)/8;
--                bdata = ImageUtil.getPackedBinaryData(raster, rect);
--
--                // Update format tag depending on whether the data were copied.
--                if(bdata ==
--                   ((DataBufferByte)raster.getDataBuffer()).getData()) {
--                    this.formatTag |= UNCOPIED;
--                } else {
--                    this.formatTag |= COPIED;
--                }
--            } else { // unpacked
--                mlibType = Constants.MLIB_BYTE;
--                scanlineStride = rect.width;
--                bdata = ImageUtil.getUnpackedBinaryData(raster, rect);
--                this.formatTag |= COPIED;
--            }
--
--            mlimages[0] = new mediaLibImage(mlibType,
--                                            1,
--                                            rect.width,
--                                            rect.height,
--                                            scanlineStride,
--                                            0,
--                                            bdata);
--
--            return;
--        }
--
--        if ((formatTag & COPY_MASK) == UNCOPIED) {
--            ComponentSampleModel csm =
--                (ComponentSampleModel)raster.getSampleModel();
--
--            numBands = csm.getNumBands();
--            bandOffsets = csm.getBandOffsets();
--            int dataOffset = raster.getDataBuffer().getOffset();
--            dataOffset +=
--             (rect.y-raster.getSampleModelTranslateY())*csm.getScanlineStride()+
--             (rect.x-raster.getSampleModelTranslateX())*csm.getPixelStride();
--
--            // dataoffset should and is in terms of dataElements
--
--            // scanline stride should be in terms of dataElements
--            int scanlineStride = csm.getScanlineStride();
--
--            switch (formatTag & DATATYPE_MASK) {
--            case DataBuffer.TYPE_BYTE:
--                DataBufferByte dbb = (DataBufferByte)raster.getDataBuffer();
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_BYTE,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      dataOffset,
--                                      dbb.getData());
--                break;
--
--            case DataBuffer.TYPE_USHORT:
--                DataBufferUShort dbus =
--                    (DataBufferUShort)raster.getDataBuffer();
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_USHORT,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      dataOffset,
--                                      dbus.getData());
--                break;
--            case DataBuffer.TYPE_SHORT:
--                DataBufferShort dbs = (DataBufferShort)raster.getDataBuffer();
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_SHORT,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      dataOffset,
--                                      dbs.getData());
--                break;
--            case DataBuffer.TYPE_INT:
--                DataBufferInt dbi = (DataBufferInt)raster.getDataBuffer();
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_INT,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      dataOffset,
--                                      dbi.getData());
--                break;
--            case DataBuffer.TYPE_FLOAT:
--                DataBufferFloat dbf = (DataBufferFloat)raster.getDataBuffer();
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_FLOAT,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      dataOffset,
--                                      dbf.getData());
--                break;
--            case DataBuffer.TYPE_DOUBLE:
--                DataBufferDouble dbd = (DataBufferDouble)raster.getDataBuffer();
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_DOUBLE,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      dataOffset,
--                                      dbd.getData());
--                break;
--            default:
--                throw new IllegalArgumentException((formatTag & DATATYPE_MASK) +
--                    "MediaLibAccessor does not recognize this datatype.");
--            }
--        } else {
--            // Copying the data because we can't deal with it
--            numBands = raster.getNumBands();
--            bandOffsets = new int[numBands];
--            for (int i = 0; i < numBands; i++) {
--                bandOffsets[i] = i;
--            }
--            int scanlineStride = rect.width*numBands;
--
--            switch (formatTag & DATATYPE_MASK) {
--            case DataBuffer.TYPE_BYTE:
--                byte bdata[] = new byte[rect.width*rect.height*numBands];
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_BYTE,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      0,
--                                      bdata);
--                break;
--            case DataBuffer.TYPE_USHORT:
--                short usdata[] = new short[rect.width*rect.height*numBands];
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_USHORT,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      0,
--                                      usdata);
--                break;
--            case DataBuffer.TYPE_SHORT:
--                short sdata[] = new short[rect.width*rect.height*numBands];
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_SHORT,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      0,
--                                      sdata);
--                break;
--            case DataBuffer.TYPE_INT:
--                int idata[] = new int[rect.width*rect.height*numBands];
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_INT,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      0,
--                                      idata);
--                break;
--            case DataBuffer.TYPE_FLOAT:
--                float fdata[] = new float[rect.width*rect.height*numBands];
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_FLOAT,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      0,
--                                      fdata);
--                break;
--            case DataBuffer.TYPE_DOUBLE:
--                double ddata[] = new double[rect.width*rect.height*numBands];
--                mlimages = new mediaLibImage[1];
--                mlimages[0] =
--                    new mediaLibImage(Constants.MLIB_DOUBLE,
--                                      numBands,
--                                      rect.width,
--                                      rect.height,
--                                      scanlineStride,
--                                      0,
--                                      ddata);
--                break;
--            default:
--                throw new IllegalArgumentException((formatTag & DATATYPE_MASK) +
--                    "MediaLibAccessor does not recognize this datatype.");
--            }
--            copyDataFromRaster();
--        }
--    }
--
--    /**
--     * Returns <code>true</code> if the <code>MediaLibAccessor</code>
--     * represents binary data.
--     */
--    public boolean isBinary() {
--        return ((formatTag & BINARY_MASK) == BINARY);
--    }
--
--    /**
--     *  Returns an array of mediaLibImages which represents the input raster.
--     *  An array is returned instead of a single mediaLibImage because
--     *  in some cases, an input Raster can't be represented by one
--     *  mediaLibImage (unless copying is done) but can be represented
--     *  by several mediaLibImages without copying.
--     */
--    public mediaLibImage[] getMediaLibImages() {
--        return mlimages;
--    }
--
--    /**
--     *  Returns the data type of the RasterAccessor object. Note that
--     *  this datatype is not necessarily the same data type as the
--     *  underlying raster.
--     */
--    public int getDataType() {
--        return formatTag & DATATYPE_MASK;
--    }
--
--    /**
--     *  Returns true if the MediaLibAccessors's data is copied from it's
--     *  raster.
--     */
--    public boolean isDataCopy() {
--        return ((formatTag & COPY_MASK) == COPIED);
--    }
--
--    /** Returns the bandOffsets. */
--    public int[] getBandOffsets() {
--        return bandOffsets;
--    }
--
--    /**
--     *  Returns parameters in the appropriate order if MediaLibAccessor
--     *  has reordered the bands or is attempting to make a
--     *  BandSequential image look like multiple PixelSequentialImages
--     */
--    public int[] getIntParameters(int band, int params[]) {
--        int returnParams[] = new int[numBands];
--        for (int i = 0; i < numBands; i++) {
--            returnParams[i] = params[bandOffsets[i+band]];
--        }
--        return returnParams;
--    }
--
--    /**
--     *  Returns parameters in the appropriate order if MediaLibAccessor
--     *  has reordered the bands or is attempting to make a
--     *  BandSequential image look like multiple PixelSequentialImages
--     */
--    public int[][] getIntArrayParameters(int band, int[][] params) {
--        int returnParams[][] = new int[numBands][];
--        for (int i = 0; i < numBands; i++) {
--            returnParams[i] = params[bandOffsets[i+band]];
--        }
--        return returnParams;
--    }
--
--    /**
--     *  Returns parameters in the appropriate order if MediaLibAccessor
--     *  has reordered the bands or is attempting to make a
--     *  BandSequential image look like multiple PixelSequentialImages
--     */
--    public double[] getDoubleParameters(int band, double params[]) {
--        double returnParams[] = new double[numBands];
--        for (int i = 0; i < numBands; i++) {
--            returnParams[i] = params[bandOffsets[i+band]];
--        }
--        return returnParams;
--    }
--
--
--    /**
--     *  Copy data from Raster to MediaLib image
--     */
--    private void copyDataFromRaster() {
--        // Writeback should only be necessary on destRasters which
--        // should be writable so this cast should succeed.
--
--        if (raster.getSampleModel() instanceof ComponentSampleModel) {
--            ComponentSampleModel csm =
--               (ComponentSampleModel)raster.getSampleModel();
--            int rasScanlineStride = csm.getScanlineStride();
--            int rasPixelStride = csm.getPixelStride();
--
--            int subRasterOffset =
--             (rect.y-raster.getSampleModelTranslateY())*rasScanlineStride+
--             (rect.x-raster.getSampleModelTranslateX())*rasPixelStride;
--
--            int rasBankIndices[] = csm.getBankIndices();
--            int rasBandOffsets[] = csm.getBandOffsets();
--            int rasDataOffsets[] = raster.getDataBuffer().getOffsets();
--
--            if (rasDataOffsets.length == 1) {
--                for (int i = 0; i < numBands; i++) {
--                    rasBandOffsets[i] += rasDataOffsets[0] +
--                       subRasterOffset;
--                }
--            } else if (rasDataOffsets.length == rasBandOffsets.length) {
--                for (int i = 0; i < numBands; i++) {
--                    rasBandOffsets[i] += rasDataOffsets[i] +
--                        subRasterOffset;
--                }
--            }
--
--            Object mlibDataArray = null;
--            switch (getDataType()) {
--            case DataBuffer.TYPE_BYTE:
--                byte bArray[][] = new byte[numBands][];
--                for (int i = 0; i < numBands; i++) {
--                    bArray[i] = mlimages[0].getByteData();
--                }
--                mlibDataArray = bArray;
--                break;
--            case DataBuffer.TYPE_USHORT:
--                short usArray[][] = new short[numBands][];
--                for (int i = 0; i < numBands; i++) {
--                    usArray[i] = mlimages[0].getUShortData();
--                }
--                mlibDataArray = usArray;
--                break;
--            case DataBuffer.TYPE_SHORT:
--                short sArray[][] = new short[numBands][];
--                for (int i = 0; i < numBands; i++) {
--                    sArray[i] = mlimages[0].getShortData();
--                }
--                mlibDataArray = sArray;
--                break;
--            case DataBuffer.TYPE_INT:
--                int iArray[][] = new int[numBands][];
--                for (int i = 0; i < numBands; i++) {
--                    iArray[i] = mlimages[0].getIntData();
--                }
--                mlibDataArray = iArray;
--                break;
--            case DataBuffer.TYPE_FLOAT:
--                float fArray[][] = new float[numBands][];
--                for (int i = 0; i < numBands; i++) {
--                    fArray[i] = mlimages[0].getFloatData();
--                }
--                mlibDataArray = fArray;
--                break;
--            case DataBuffer.TYPE_DOUBLE:
--                double dArray[][] = new double[numBands][];
--                for (int i = 0; i < numBands; i++) {
--                    dArray[i] = mlimages[0].getDoubleData();
--                }
--                mlibDataArray = dArray;
--                break;
--            }
--
--
--
--            Object rasDataArray = null;
--            switch (csm.getDataType()) {
--                case DataBuffer.TYPE_BYTE: {
--                    DataBufferByte dbb =
--                        (DataBufferByte)raster.getDataBuffer();
--                    byte rasByteDataArray[][] = new byte[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        rasByteDataArray[i] =
--                            dbb.getData(rasBankIndices[i]);
--                    }
--                    rasDataArray = rasByteDataArray;
--                    }
--                    break;
--                case DataBuffer.TYPE_USHORT: {
--                    DataBufferUShort dbus =
--                        (DataBufferUShort)raster.getDataBuffer();
--                    short rasUShortDataArray[][] = new short[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        rasUShortDataArray[i] =
--                            dbus.getData(rasBankIndices[i]);
--                    }
--                    rasDataArray = rasUShortDataArray;
--                    }
--                    break;
--                case DataBuffer.TYPE_SHORT: {
--                    DataBufferShort dbs =
--                        (DataBufferShort)raster.getDataBuffer();
--                    short rasShortDataArray[][] = new short[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        rasShortDataArray[i] =
--                            dbs.getData(rasBankIndices[i]);
--                    }
--                    rasDataArray = rasShortDataArray;
--                    }
--                    break;
--                case DataBuffer.TYPE_INT: {
--                    DataBufferInt dbi =
--                        (DataBufferInt)raster.getDataBuffer();
--                    int rasIntDataArray[][] = new int[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        rasIntDataArray[i] =
--                            dbi.getData(rasBankIndices[i]);
--                    }
--                    rasDataArray = rasIntDataArray;
--                    }
--                    break;
--                case DataBuffer.TYPE_FLOAT: {
--                    DataBufferFloat dbf =
--                        (DataBufferFloat)raster.getDataBuffer();
--                    float rasFloatDataArray[][] = new float[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        rasFloatDataArray[i] =
--                            dbf.getData(rasBankIndices[i]);
--                    }
--                    rasDataArray = rasFloatDataArray;
--                    }
--                    break;
--                case DataBuffer.TYPE_DOUBLE: {
--                    DataBufferDouble dbd =
--                        (DataBufferDouble)raster.getDataBuffer();
--                    double rasDoubleDataArray[][] = new double[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        rasDoubleDataArray[i] =
--                            dbd.getData(rasBankIndices[i]);
--                    }
--                    rasDataArray = rasDoubleDataArray;
--                    }
--                    break;
--            }
--
--
--            // dst = mlib && src = ras
--            Util.Reformat(
--                    mlibDataArray,
--                    rasDataArray,
--                    numBands,
--                    rect.width,rect.height,
--                    getMediaLibDataType(this.getDataType()),
--                    bandOffsets,
--                    rect.width*numBands,
--                    numBands,
--                    getMediaLibDataType(csm.getDataType()),
--                    rasBandOffsets,
--                    rasScanlineStride,
--                    rasPixelStride);
--        } else {
--            // If COPIED and the raster doesn't have ComponentSampleModel
--            // data is moved with getPixel/setPixel (even byte/short)
--            switch (getDataType()) {
--            case DataBuffer.TYPE_INT:
--                raster.getPixels(rect.x,rect.y,
--                                 rect.width,rect.height,
--                                 mlimages[0].getIntData());
--                break;
--            case DataBuffer.TYPE_FLOAT:
--                raster.getPixels(rect.x,rect.y,
--                                 rect.width,rect.height,
--                                 mlimages[0].getFloatData());
--                break;
--            case DataBuffer.TYPE_DOUBLE:
--                raster.getPixels(rect.x,rect.y,
--                                 rect.width,rect.height,
--                                 mlimages[0].getDoubleData());
--                break;
--            }
--        }
--    }
--
--
--    /**
--     *  Copies data back into the MediaLibAccessor's raster.  Note that
--     *  the data is casted from the intermediate data format to
--     *  the raster's format.  If clamping is needed, the call
--     *  clampDataArrays() method needs to be called before
--     *  calling the copyDataToRaster() method.
--     */
--    public void copyDataToRaster(int[] channelMap) {
--        if (isDataCopy()) {
--
--            if(isBinary()) {
--                if(areBinaryDataPacked) {
--                    ImageUtil.setPackedBinaryData(mlimages[0].getBitData(),
--                                                  (WritableRaster)raster,
--                                                  rect);
--                } else { // unpacked
--                    ImageUtil.setUnpackedBinaryData(mlimages[0].getByteData(),
--                                                    (WritableRaster)raster,
--                                                    rect);
--                }
--                return;
--            }
--
--            // Writeback should only be necessary on destRasters which
--            // should be writable so this cast should succeed.
--            WritableRaster wr = (WritableRaster)raster;
--
--            if (wr.getSampleModel() instanceof ComponentSampleModel) {
--                ComponentSampleModel csm =
--                   (ComponentSampleModel)wr.getSampleModel();
--                int rasScanlineStride = csm.getScanlineStride();
--                int rasPixelStride = csm.getPixelStride();
--
--                int subRasterOffset =
--                 (rect.y-raster.getSampleModelTranslateY())*rasScanlineStride+
--                 (rect.x-raster.getSampleModelTranslateX())*rasPixelStride;
--
--                int rasBankIndices[] = csm.getBankIndices();
--                int rasBandOffsets[] = csm.getBandOffsets();
--                int rasDataOffsets[] = raster.getDataBuffer().getOffsets();
--
--                if (rasDataOffsets.length == 1) {
--                    for (int i = 0; i < numBands; i++) {
--                        rasBandOffsets[i] += rasDataOffsets[0] +
--                           subRasterOffset;
--                    }
--                } else if (rasDataOffsets.length == rasBandOffsets.length) {
--                    for (int i = 0; i < numBands; i++) {
--                        rasBandOffsets[i] += rasDataOffsets[i] +
--                            subRasterOffset;
--                    }
--                }
--
--                Object mlibDataArray = null;
--                switch (getDataType()) {
--                case DataBuffer.TYPE_BYTE:
--                    byte bArray[][] = new byte[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        bArray[i] = mlimages[0].getByteData();
--                    }
--                    mlibDataArray = bArray;
--                    break;
--                case DataBuffer.TYPE_USHORT:
--                    short usArray[][] = new short[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        usArray[i] = mlimages[0].getUShortData();
--                    }
--                    mlibDataArray = usArray;
--                    break;
--                case DataBuffer.TYPE_SHORT:
--                    short sArray[][] = new short[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        sArray[i] = mlimages[0].getShortData();
--                    }
--                    mlibDataArray = sArray;
--                    break;
--                case DataBuffer.TYPE_INT:
--                    int iArray[][] = new int[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        iArray[i] = mlimages[0].getIntData();
--                    }
--                    mlibDataArray = iArray;
--                    break;
--                case DataBuffer.TYPE_FLOAT:
--                    float fArray[][] = new float[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        fArray[i] = mlimages[0].getFloatData();
--                    }
--                    mlibDataArray = fArray;
--                    break;
--                case DataBuffer.TYPE_DOUBLE:
--                    double dArray[][] = new double[numBands][];
--                    for (int i = 0; i < numBands; i++) {
--                        dArray[i] = mlimages[0].getDoubleData();
--                    }
--                    mlibDataArray = dArray;
--                    break;
--                }
--
--
--		byte tmpDataArray[] = null;
--                Object rasDataArray = null;
--                switch (csm.getDataType()) {
--                    case DataBuffer.TYPE_BYTE: {
--                        DataBufferByte dbb =
--                            (DataBufferByte)raster.getDataBuffer();
--                        byte rasByteDataArray[][] = new byte[numBands][];
--                        for (int i = 0; i < numBands; i++) {
--                            rasByteDataArray[i] =
--                                dbb.getData(rasBankIndices[i]);
--                        }
--			tmpDataArray =  rasByteDataArray[0];
--                        rasDataArray = rasByteDataArray;
--                        }
--                        break;
--                    case DataBuffer.TYPE_USHORT: {
--                        DataBufferUShort dbus =
--                            (DataBufferUShort)raster.getDataBuffer();
--                        short rasUShortDataArray[][] = new short[numBands][];
--                        for (int i = 0; i < numBands; i++) {
--                            rasUShortDataArray[i] =
--                                dbus.getData(rasBankIndices[i]);
--                        }
--                        rasDataArray = rasUShortDataArray;
--                        }
--                        break;
--                    case DataBuffer.TYPE_SHORT: {
--                        DataBufferShort dbs =
--                            (DataBufferShort)raster.getDataBuffer();
--                        short rasShortDataArray[][] = new short[numBands][];
--                        for (int i = 0; i < numBands; i++) {
--                            rasShortDataArray[i] =
--                                dbs.getData(rasBankIndices[i]);
--                        }
--                        rasDataArray = rasShortDataArray;
--                        }
--                        break;
--                    case DataBuffer.TYPE_INT: {
--                        DataBufferInt dbi =
--                            (DataBufferInt)raster.getDataBuffer();
--                        int rasIntDataArray[][] = new int[numBands][];
--                        for (int i = 0; i < numBands; i++) {
--                            rasIntDataArray[i] =
--                                dbi.getData(rasBankIndices[i]);
--                        }
--                        rasDataArray = rasIntDataArray;
--                        }
--                        break;
--                    case DataBuffer.TYPE_FLOAT: {
--                        DataBufferFloat dbf =
--                            (DataBufferFloat)raster.getDataBuffer();
--                        float rasFloatDataArray[][] = new float[numBands][];
--                        for (int i = 0; i < numBands; i++) {
--                            rasFloatDataArray[i] =
--                                dbf.getData(rasBankIndices[i]);
--                        }
--                        rasDataArray = rasFloatDataArray;
--                        }
--                        break;
--                    case DataBuffer.TYPE_DOUBLE: {
--                        DataBufferDouble dbd =
--                            (DataBufferDouble)raster.getDataBuffer();
--                        double rasDoubleDataArray[][] = new double[numBands][];
--                        for (int i = 0; i < numBands; i++) {
--                            rasDoubleDataArray[i] =
--                                dbd.getData(rasBankIndices[i]);
--                        }
--                        rasDataArray = rasDoubleDataArray;
--                        }
--                        break;
--                }
--
--                int[] bandOffsetCopy = (int[])bandOffsets.clone();
--                if (channelMap != null) {
--                    for (int i = 0; i < bandOffsetCopy.length; i++)
--                        bandOffsetCopy[i] = channelMap[bandOffsetCopy[i]];
--                }
--
--                // src = mlib && dst = ras
--                Util.Reformat(
--                        rasDataArray,
--                        mlibDataArray,
--                        numBands,
--                        rect.width,rect.height,
--                        getMediaLibDataType(csm.getDataType()),
--                        rasBandOffsets,
--                        rasScanlineStride,
--                        rasPixelStride,
--                        getMediaLibDataType(this.getDataType()),
--                        bandOffsetCopy,
--                        rect.width*numBands,
--                        numBands);
--            } else {
--                // If COPIED and the raster doesn't have ComponentSampleModel
--                // data is moved with getPixel/setPixel (even byte/short)
--                switch (getDataType()) {
--                case DataBuffer.TYPE_INT:
--                    wr.setPixels(rect.x,rect.y,
--                                 rect.width,rect.height,
--                                 mlimages[0].getIntData());
--                    break;
--                case DataBuffer.TYPE_FLOAT:
--                    wr.setPixels(rect.x,rect.y,
--                                 rect.width,rect.height,
--                                 mlimages[0].getFloatData());
--                    break;
--                case DataBuffer.TYPE_DOUBLE:
--                    wr.setPixels(rect.x,rect.y,
--                                 rect.width,rect.height,
--                                 mlimages[0].getDoubleData());
--                    break;
--                }
--            }
--        }
--    }
--
--    /**
--     * Clamps data array values to a range that the underlying raster
--     * can deal with.  For example, if the underlying raster stores
--     * data as bytes, but the samples ares unpacked into integer arrays by
--     * the RasterAccessor object for an operation, the operation will
--     * need to call clampDataArrays() so that the data in the int
--     * arrays is restricted to the range 0..255 before a setPixels()
--     * call is made on the underlying raster.  Note that some
--     * operations (for example, lookup) can guarantee that their
--     * results don't need clamping so they can call
--     * RasterAccessor.copyDataToRaster() without first calling this
--     * function.
--     */
--    public void clampDataArrays () {
--        if (!isDataCopy()) {
--            return;
--        }
--
--        // additonal medialib check:  If it's a componentSampleModel
--        // we get a free cast when we call medialibWrapper.Reformat
--        // to copy the data to the source.  So we don't need to cast
--        // here.
--        if (raster.getSampleModel() instanceof ComponentSampleModel) {
--            return;
--        }
--
--        int bits[] = raster.getSampleModel().getSampleSize();
--
--        // Do we even need a clamp?  We do if there's any band
--        // of the source image stored in that's less than 32 bits
--        // and is stored in a byte, short or int format.  (The automatic
--        // cast's between floats/doubles and 32-bit ints in setPixel()
--        // generall do what we want.)
--
--        boolean needClamp = false;
--        boolean uniformBitSize = true;
--        for (int i = 0; i < bits.length; i++) {
--            int bitSize = bits[0];
--            if (bits[i] < 32) {
--                needClamp = true;
--            }
--            if (bits[i] != bitSize) {
--               uniformBitSize = false;
--            }
--        }
--
--        if (!needClamp) {
--            return;
--        }
--
--        int dataType = raster.getDataBuffer().getDataType();
--        double hiVals[] = new double[bits.length];
--        double loVals[] = new double[bits.length];
--
--        if (dataType == DataBuffer.TYPE_USHORT &&
--            uniformBitSize && bits[0] == 16) {
--            for (int i = 0; i < bits.length; i++) {
--                hiVals[i] = (double)0xFFFF;
--                loVals[i] = (double)0;
--            }
--        } else if (dataType == DataBuffer.TYPE_SHORT &&
--            uniformBitSize && bits[0] == 16) {
--            for (int i = 0; i < bits.length; i++) {
--                hiVals[i] = (double)Short.MAX_VALUE;
--                loVals[i] = (double)Short.MIN_VALUE;
--            }
--        } else if (dataType == DataBuffer.TYPE_INT &&
--            uniformBitSize && bits[0] == 32) {
--            for (int i = 0; i < bits.length; i++) {
--                hiVals[i] = (double)Integer.MAX_VALUE;
--                loVals[i] = (double)Integer.MIN_VALUE;
--            }
--        } else {
--            for (int i = 0; i < bits.length; i++) {
--                hiVals[i] = (double)((1 << bits[i]) - 1);
--                loVals[i] = (double)0;
--            }
--        }
--        clampDataArray(hiVals,loVals);
--    }
--
--    private void clampDataArray(double hiVals[], double loVals[]) {
--        switch (getDataType()) {
--        case DataBuffer.TYPE_INT:
--            clampIntArrays(toIntArray(hiVals),toIntArray(loVals));
--            break;
--        case DataBuffer.TYPE_FLOAT:
--            clampFloatArrays(toFloatArray(hiVals),toFloatArray(loVals));
--            break;
--        case DataBuffer.TYPE_DOUBLE:
--            clampDoubleArrays(hiVals,loVals);
--            break;
--        }
--    }
--
--    private int[] toIntArray(double vals[]) {
--        int returnVals[] = new int[vals.length];
--        for (int i = 0; i < vals.length; i++) {
--            returnVals[i] = (int)vals[i];
--        }
--        return returnVals;
--    }
--
--    private float[] toFloatArray(double vals[]) {
--        float returnVals[] = new float[vals.length];
--        for (int i = 0; i < vals.length; i++) {
--            returnVals[i] = (float)vals[i];
--        }
--        return returnVals;
--    }
--
--    private void clampIntArrays(int hiVals[], int loVals[]) {
--        int width = rect.width;
--        int height = rect.height;
--        int scanlineStride = numBands*width;
--        for (int k = 0; k < numBands; k++)  {
--            int data[] = mlimages[0].getIntData();
--            int scanlineOffset = k;
--            int hiVal = hiVals[k];
--            int loVal = loVals[k];
--            for (int j = 0; j < height; j++)  {
--                int pixelOffset = scanlineOffset;
--                for (int i = 0; i < width; i++)  {
--                    int tmp = data[pixelOffset];
--                    if (tmp < loVal) {
--                        data[pixelOffset] = loVal;
--                    } else if (tmp > hiVal) {
--                        data[pixelOffset] = hiVal;
--                    }
--                    pixelOffset += numBands;
--                }
--                scanlineOffset += scanlineStride;
--            }
--        }
--    }
--
--    private void clampFloatArrays(float hiVals[], float loVals[]) {
--        int width = rect.width;
--        int height = rect.height;
--        int scanlineStride = numBands*width;
--        for (int k = 0; k < numBands; k++)  {
--            float data[] =  mlimages[0].getFloatData();
--            int scanlineOffset = k;
--            float hiVal = hiVals[k];
--            float loVal = loVals[k];
--            for (int j = 0; j < height; j++)  {
--                int pixelOffset = scanlineOffset;
--                for (int i = 0; i < width; i++)  {
--                    float tmp = data[pixelOffset];
--                    if (tmp < loVal) {
--                        data[pixelOffset] = loVal;
--                    } else if (tmp > hiVal) {
--                        data[pixelOffset] = hiVal;
--                    }
--                    pixelOffset += numBands;
--                }
--                scanlineOffset += scanlineStride;
--            }
--        }
--    }
--
--    private void clampDoubleArrays(double hiVals[], double loVals[]) {
--        int width = rect.width;
--        int height = rect.height;
--        int scanlineStride = numBands*width;
--        for (int k = 0; k < numBands; k++)  {
--            double data[] = mlimages[0].getDoubleData();
--            int scanlineOffset = k;
--            double hiVal = hiVals[k];
--            double loVal = loVals[k];
--            for (int j = 0; j < height; j++)  {
--                int pixelOffset = scanlineOffset;
--                for (int i = 0; i < width; i++)  {
--                    double tmp = data[pixelOffset];
--                    if (tmp < loVal) {
--                        data[pixelOffset] = loVal;
--                    } else if (tmp > hiVal) {
--                        data[pixelOffset] = hiVal;
--                    }
--                    pixelOffset += numBands;
--                }
--                scanlineOffset += scanlineStride;
--            }
--        }
--    }
--
--}
--
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGImageReader.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGImageReader.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,285 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibPNGImageReader.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.5 $
-- * $Date: 2006/02/24 01:03:28 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.png;
--
--import java.awt.color.ColorSpace;
--import java.awt.color.ICC_ColorSpace;
--import java.awt.color.ICC_Profile;
--import java.io.InputStream;
--import java.io.IOException;
--import java.util.ArrayList;
--import java.util.HashMap;
--import java.util.Iterator;
--import javax.imageio.IIOException;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.metadata.IIOMetadata;
--import javax.imageio.spi.ImageReaderSpi;
--import com.sun.media.imageioimpl.plugins.clib.CLibImageReader;
--import com.sun.medialib.codec.png.Decoder;
--import com.sun.medialib.codec.jiio.mediaLibImage;
--
--final class CLibPNGImageReader extends CLibImageReader {
--    private Decoder decoder;
--    private HashMap imageTypes = new HashMap();
--
--    CLibPNGImageReader(ImageReaderSpi originatingProvider) {
--        super(originatingProvider);
--    }
--
--    // Implement abstract method defined in superclass.
--    protected final synchronized mediaLibImage decode(InputStream stream)
--        throws IOException {
--        try {
--            decoder = new Decoder(stream);
--            decoder.decode();
--        } catch(Throwable t) {
--            throw new IIOException("codecLib error", t);
--        }
--
--        /* XXX Get significant bits (sBIT chunk).
--        byte[] bits = decoder.getSignificantBits();
--        if(bits != null) {
--            System.out.println("getSignificantBits():");
--            for(int i = 0; i < bits.length; i++) {
--                System.out.println((bits[i]&0xff));
--            }
--        }
--        */
--
--        mediaLibImage mlImage = null;
--        try {
--            mlImage = decoder.getImage();
--        } catch(Throwable t) {
--            throw new IIOException("codecLib error", t);
--        }
--
--        if(mlImage == null) {
--            throw new IIOException(I18N.getString("CLibPNGImageReader0"));
--        }
--
--        return mlImage;
--    }
--
--    public synchronized Iterator getImageTypes(int imageIndex)
--        throws IOException {
--        seekToImage(imageIndex);
--
--        ArrayList types = null;
--        Integer key = new Integer(imageIndex);
--        if(imageTypes.containsKey(key)) {
--            types = (ArrayList)imageTypes.get(key);
--        } else {
--            types = new ArrayList();
--
--            // Get the mediaLibImage from the Decoder.
--            mediaLibImage image = getImage(imageIndex);
--
--            // Get the palette.
--            byte[] rgbPalette = null;
--            try {
--                // Note: the 'decoder' instance variable is set by
--                // decode() which is called by getImage() above.
--                rgbPalette = decoder.getPalette();
--            } catch(Throwable t) {
--                throw new IIOException("codecLib error", t);
--            }
--
--            if(rgbPalette != null) {
--                // Indexed image: set up the RGB palette arrays.
--                int paletteLength = rgbPalette.length/3;
--                byte[] r = new byte[paletteLength];
--                byte[] g = new byte[paletteLength];
--                byte[] b = new byte[paletteLength];
--                for(int i = 0, j = 0; i < paletteLength; i++) {
--                    r[i] = rgbPalette[j++];
--                    g[i] = rgbPalette[j++];
--                    b[i] = rgbPalette[j++];
--                }
--
--                // Set up the alpha palette array if needed.
--                int[] alphaPalette = null;
--                try {
--                    alphaPalette = decoder.getTransparency();
--                } catch(Throwable t) {
--                    throw new IIOException("codecLib error", t);
--                }
--                byte[] a = null;
--                if(alphaPalette != null) {
--                    // Load beginning of palette from the chunk
--                    a = new byte[paletteLength];
--                    for(int i = 0; i < alphaPalette.length; i++) {
--                        a[i] = (byte)(alphaPalette[i] & 0x000000ff);
--                    }
--
--                    // Fill rest of palette with 255
--                    for(int i = alphaPalette.length; i < paletteLength; i++) {
--                        a[i] = (byte)0xff;
--                    }
--                }
--
--                types.add(createImageType(image, null, decoder.getBitDepth(),
--                                          r, g, b, a));
--            } else {
--                // Attempt to use the iCCP chunk if present, no sRGB
--                // chunk is present, and the ICC color space type matches
--                // the image type.
--                ColorSpace cs = null;
--                if(decoder.getStandardRGB() ==
--                   Decoder.PNG_sRGB_NOT_DEFINED) {
--                    // Get the profile data.
--                    byte[] iccProfileData =
--                        decoder.getEmbeddedICCProfile();
--                    if(iccProfileData != null) {
--                        // Create the ColorSpace.
--                        ICC_Profile iccProfile =
--                            ICC_Profile.getInstance(iccProfileData);
--                        ICC_ColorSpace icccs =
--                            new ICC_ColorSpace(iccProfile);
--
--                        // Check the color space type against the
--                        // number of bands and the palette.
--                        int numBands = image.getChannels();
--                        if((icccs.getType() == ColorSpace.TYPE_RGB &&
--                            (numBands >= 3 || rgbPalette != null)) ||
--                           (icccs.getType() == ColorSpace.TYPE_GRAY &&
--                            numBands < 3 && rgbPalette == null)) {
--                            cs = icccs;
--                        }
--                    }
--                }
--
--                int bitDepth = decoder.getBitDepth();
--
--                ImageTypeSpecifier type =
--                    createImageType(image, cs, bitDepth,
--                                    null, null, null, null);
--                types.add(type);
--
--                if(type.getColorModel().getColorSpace().equals(cs)) {
--                    types.add(createImageType(image, null, bitDepth,
--                                              null, null, null, null));
--                }
--            }
--
--            imageTypes.put(key, types);
--        }
--
--        // XXX Need also to use getBackground() to save the background
--        // color somewhere, eventually as an image property with the
--        // name "background_color" and with a java.awt.Color value.
--        // See PNGImageDecoder or the PNG ImageReader for more info.
--        // Looks like this needs to be set as a metadata entry. It is
--        // obtained from the decoder using getBackground().
--
--        return types.iterator();
--    }
--
--    // Override superclass method.
--    protected void resetLocal() {
--        decoder = null;
--        imageTypes.clear();
--        super.resetLocal();
--    }
--
--    public synchronized IIOMetadata getImageMetadata(int imageIndex)
--        throws IIOException {
--        if(input == null) {
--            throw new IllegalStateException("input == null");
--        }
--        seekToImage(imageIndex);
--
--        CLibPNGMetadata im = new CLibPNGMetadata();
--        try {
--            getImage(imageIndex);
--        } catch(IOException e) {
--            throw new IIOException("codecLib error", e);
--        }
--        im.readMetadata(this, decoder);
--        return im;
--    }
--
--    /**
--     * Package scope method to classes in package to emit warning messages.
--     */
--    void forwardWarningMessage(String warning) {
--        processWarningOccurred(warning);
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGImageReaderSpi.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGImageReaderSpi.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,185 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibPNGImageReaderSpi.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.2 $
-- * $Date: 2006/03/31 19:43:40 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.png;
--
--import java.util.List;
--import java.util.Locale;
--import javax.imageio.spi.ImageReaderSpi;
--import javax.imageio.stream.ImageInputStream;
--import javax.imageio.spi.ServiceRegistry;
--import java.io.IOException;
--import javax.imageio.ImageReader;
--import javax.imageio.IIOException;
--import com.sun.media.imageioimpl.common.PackageUtil;
--import com.sun.media.imageioimpl.common.ImageUtil;
--
--public class CLibPNGImageReaderSpi extends ImageReaderSpi {
--
--    private static final String[] names = {"png", "PNG"};
--
--    private static final String[] suffixes = {"png"};
--    
--    private static final String[] MIMETypes = {"image/png", "image/x-png"};
--
--    private static final String readerClassName =
--        "com.sun.media.imageioimpl.plugins.png.CLibPNGImageReader";
--
--    private static final String[] writerSpiNames = {
--        "com.sun.media.imageioimpl.plugins.png.CLibPNGImageWriterSpi"
--    };
--
--    private boolean registered = false;
--
--    public CLibPNGImageReaderSpi() {
--        super(PackageUtil.getVendor(),
--              PackageUtil.getVersion(),
--              names,
--              suffixes,
--              MIMETypes,
--              readerClassName,
--              STANDARD_INPUT_TYPE,
--              writerSpiNames,
--              false,
--              null, null,
--              null, null,
--              true,
--              CLibPNGMetadata.nativeMetadataFormatName,
--              "com.sun.media.imageioimpl.plugins.png.CLibPNGMetadataFormat",
--              null, null);
--    }
--
--    public void onRegistration(ServiceRegistry registry,
--                               Class category) {
--        if (registered) {
--            return;
--        }
--	
--        registered = true;
--
--        // Branch as a function of codecLib availability.
--        if(!PackageUtil.isCodecLibAvailable()) {
--            // Deregister provider.
--            registry.deregisterServiceProvider(this);
--        } else {
--
--	    List list = 
--		ImageUtil.getJDKImageReaderWriterSPI(registry, "PNG", true);
--
--	    for (int i=0; i<list.size(); i++) {
--		// Set pairwise ordering to give codecLib reader precedence
--		// over Sun core J2SE reader.
--		registry.setOrdering(category, this, list.get(i));
--	    }
--        }
--    }
--
--    public String getDescription(Locale locale) {
--	String desc = PackageUtil.getSpecificationTitle() + 
--	    " natively-accelerated PNG Image Reader";
--	return desc;
--    }
--
--    public boolean canDecodeInput(Object source) throws IOException {
--        if (!(source instanceof ImageInputStream)) {
--            return false;
--        }
--
--        ImageInputStream stream = (ImageInputStream)source;
--        byte[] b = new byte[8];
--        stream.mark();
--        stream.readFully(b);
--        stream.reset();
--        
--        return (b[0] == (byte)137 &&
--                b[1] == (byte)80 &&
--                b[2] == (byte)78 &&
--                b[3] == (byte)71 &&
--                b[4] == (byte)13 &&
--                b[5] == (byte)10 &&
--                b[6] == (byte)26 &&
--                b[7] == (byte)10);
--    }
--    
--    public ImageReader createReaderInstance(Object extension) 
--        throws IIOException {
--        return new CLibPNGImageReader(this);
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGImageWriter.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGImageWriter.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,448 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibPNGImageWriter.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.7 $
-- * $Date: 2006/11/01 22:37:00 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.png;
--
--import java.awt.Color;
--import java.awt.color.ColorSpace;
--import java.awt.color.ICC_ColorSpace;
--import java.awt.color.ICC_Profile;
--import java.awt.image.ColorModel;
--import java.awt.image.IndexColorModel;
--import java.awt.image.RenderedImage;
--import java.awt.image.SampleModel;
--import java.io.IOException;
--import java.io.OutputStream;
--import java.util.Arrays;
--import java.util.Locale;
--import javax.imageio.IIOException;
--import javax.imageio.IIOImage;
--import javax.imageio.ImageWriter;
--import javax.imageio.ImageWriteParam;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.metadata.IIOInvalidTreeException;
--import javax.imageio.metadata.IIOMetadata;
--import javax.imageio.metadata.IIOMetadataFormatImpl;
--import javax.imageio.spi.ImageWriterSpi;
--import javax.imageio.stream.ImageOutputStream;
--import com.sun.media.imageioimpl.common.ImageUtil;
--import com.sun.media.imageioimpl.plugins.clib.CLibImageWriter;
--import com.sun.media.imageioimpl.plugins.clib.OutputStreamAdapter;
--import com.sun.medialib.codec.png.Constants;
--import com.sun.medialib.codec.png.Encoder;
--import com.sun.medialib.codec.jiio.mediaLibImage;
--
--final class CLibPNGImageWriter extends CLibImageWriter {
--
--    CLibPNGImageWriter(ImageWriterSpi originatingProvider) {
--        super(originatingProvider);
--    }
--
--    public ImageWriteParam getDefaultWriteParam() {
--        return new CLibPNGImageWriteParam(getLocale());
--    }
--
--    public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType,
--                                               ImageWriteParam param) {
--        CLibPNGMetadata m = new CLibPNGMetadata();
--        if(param != null && param.getDestinationType() != null) {
--            imageType = param.getDestinationType();
--        }
--        if(imageType != null) {
--            m.initialize(imageType,
--                         imageType.getSampleModel().getNumBands(),
--                         param, 0);
--        }
--        return m;
--    }
--
--    public IIOMetadata
--        convertImageMetadata(IIOMetadata inData,
--                             ImageTypeSpecifier imageType,
--                             ImageWriteParam param) {
--        // Check arguments.
--        if(inData == null) {
--            throw new IllegalArgumentException("inData == null!");
--        }
--        if(imageType == null) {
--            throw new IllegalArgumentException("imageType == null!");
--        }
--
--        CLibPNGMetadata outData = null;
--
--        // Obtain a CLibPNGMetadata object.
--        if(inData instanceof CLibPNGMetadata) {
--            // Clone the input metadata.
--            outData = (CLibPNGMetadata)((CLibPNGMetadata)inData).clone();
--        } else {
--            try {
--                outData = new CLibPNGMetadata(inData);
--            } catch(IIOInvalidTreeException e) {
--                // XXX Warning
--                outData = new CLibPNGMetadata();
--            }
--        }
--
--        // Update the metadata per the image type and param.
--        outData.initialize(imageType,
--                           imageType.getSampleModel().getNumBands(),
--                           param, outData.IHDR_interlaceMethod);
--
--        return outData;
--    }
--
--    public void write(IIOMetadata streamMetadata,
--                      IIOImage image,
--                      ImageWriteParam param) throws IOException {
--        if(output == null) {
--            throw new IllegalStateException("output == null");
--        }
--
--        OutputStream stream = null;
--        if(output instanceof ImageOutputStream) {
--            stream = new OutputStreamAdapter((ImageOutputStream)output);
--        } else {
--            throw new IllegalArgumentException
--                ("!(output instanceof ImageOutputStream)");
--        }
--
--        RenderedImage renderedImage = image.getRenderedImage();
--	ImageUtil.canEncodeImage(this, renderedImage.getColorModel(),
--                                 renderedImage.getSampleModel());
--        int[] supportedFormats = new int[] {
--            Constants.MLIB_FORMAT_GRAYSCALE,
--            Constants.MLIB_FORMAT_GRAYSCALE_ALPHA,
--            Constants.MLIB_FORMAT_INDEXED,
--            Constants.MLIB_FORMAT_BGR,
--            Constants.MLIB_FORMAT_RGB,
--            Constants.MLIB_FORMAT_BGRA,
--            Constants.MLIB_FORMAT_RGBA
--        };
--        mediaLibImage mlImage = getMediaLibImage(renderedImage, param, true,
--                                                 supportedFormats);
--
--        Encoder encoder = null;
--        try {
--            encoder = new Encoder(mlImage);
--        } catch(Throwable t) {
--            throw new IIOException("codecLib error", t);
--        }
--
--        // Set the maximum length of the iDAT chunk.
--        encoder.setIDATSize(8192);
--
--        // Determine the image type.
--        ImageTypeSpecifier imageType;
--        if(param != null && param.getDestinationType() != null) {
--            imageType = param.getDestinationType();
--        } else if(mlImage.getType() == mediaLibImage.MLIB_BIT) {
--            if(renderedImage.getColorModel() instanceof IndexColorModel) {
--                imageType =
--                    new ImageTypeSpecifier(renderedImage.getColorModel(),
--                                           renderedImage.getSampleModel());
--            } else {
--                int dataType = renderedImage.getSampleModel().getDataType();
--                imageType =
--                    ImageTypeSpecifier.createGrayscale(1, dataType, false);
--            }
--        } else if(mlImage.getChannels() ==
--                  renderedImage.getSampleModel().getNumBands()) {
--            // Note: ImageTypeSpecifier.createFromRenderedImage() gave an
--            // incorrect result here for an indexed BufferedImage as the
--            // ImageTypeSpecifier generated by createFromBufferedImage()
--            // does not match the actual image.
--            imageType = new ImageTypeSpecifier(renderedImage);
--        } else {
--            SampleModel sm = renderedImage.getSampleModel();
--            int dataType = sm.getDataType();
--            int bitDepth = sm.getSampleSize(0);
--            int numBands = mlImage.getChannels();
--            switch(numBands) {
--            case 1:
--                imageType =
--                    ImageTypeSpecifier.createGrayscale(bitDepth, dataType,
--                                                       false);
--                break;
--            case 2:
--                imageType =
--                    ImageTypeSpecifier.createGrayscale(bitDepth, dataType,
--                                                       false, false);
--                break;
--            case 3:
--                ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
--                imageType =
--                    ImageTypeSpecifier.createInterleaved(cs,
--                                                         new int[] {0, 1, 2},
--                                                         dataType,
--                                                         false, false);
--                break;
--            default:
--                throw new IIOException("Cannot encode image with "+
--                                       numBands+" bands!");
--            }
--        }
--
--        // Get metadata.
--        IIOMetadata imageMetadata = image.getMetadata();
--
--        if(imageMetadata != null) {
--            // Convert metadata.
--            imageMetadata =
--                convertImageMetadata(imageMetadata, imageType, param);
--        } else {
--            // Use default.
--            imageMetadata = getDefaultImageMetadata(imageType, param);
--        }
--
--        // Set metadata on encoder.
--        ((CLibPNGMetadata)imageMetadata).writeMetadata(encoder);
--
--        ColorModel colorModel = null;
--        if(param != null) {
--            ImageTypeSpecifier destinationType = param.getDestinationType();
--            if(destinationType != null) {
--                colorModel = destinationType.getColorModel();
--            }
--
--            // Set compression level to (int)(9*(1.0F - compressionQuality)).
--            if(param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) {
--                try {
--                    int compressionLevel =
--                        (int)(9*(1.0F - param.getCompressionQuality()));
--                    encoder.setCompressionLevel(compressionLevel);
--                } catch(Throwable t) {
--                    throw new IIOException("codecLib error", t);
--                }
--
--                // Set the strategy if appropriate.
--                if(param instanceof CLibPNGImageWriteParam) {
--                    try {
--                        encoder.setStrategy(
--                            ((CLibPNGImageWriteParam)param).getStrategy());
--                    } catch(Throwable t) {
--                        throw new IIOException("codecLib error", t);
--                    }
--                }
--            }
--        } else { // null ImageWriteParam
--            try {
--                // Do not set the compression level: let it default.
--
--                // Z_DEFAULT_STRATEGY
--                encoder.setStrategy(0);
--            } catch(Throwable t) {
--                throw new IIOException("codecLib error", t);
--            }
--        }
--
--        if(colorModel == null) {
--            colorModel = renderedImage.getColorModel();
--        }
--
--        // If no iCCP chunk is already in the metadata and the color space
--        // is a non-standard ICC color space, the write it to iCCP chunk.
--        if(!((CLibPNGMetadata)imageMetadata).iCCP_present &&
--           colorModel != null &&
--           ImageUtil.isNonStandardICCColorSpace(colorModel.getColorSpace())) {
--            // Get the profile data.
--            ICC_ColorSpace iccColorSpace =
--                (ICC_ColorSpace)colorModel.getColorSpace();
--            ICC_Profile iccProfile = iccColorSpace.getProfile();
--            byte[] iccProfileData = iccColorSpace.getProfile().getData();
--
--            // Get the profile name.
--            byte[] desc =
--                iccProfile.getData(ICC_Profile.icSigProfileDescriptionTag);
--            String profileName;
--            if(desc != null) {
--                long len = ((desc[8]&0xff) << 24) | ((desc[9]&0xff) << 16) |
--                    ((desc[10]&0xff) << 8) | (desc[11]&0xff);
--                profileName = new String(desc, 12, (int)len);
--            } else {
--                profileName = "ICCProfile";
--            }
--
--            // Set the profile on the Encoder.
--            profileName = CLibPNGMetadata.toPrintableLatin1(profileName);
--            encoder.setEmbeddedICCProfile(profileName, iccProfileData);
--        }
--
--        try {
--            encoder.encode(stream);
--        } catch(Throwable t) {
--            throw new IIOException("codecLib error", t);
--        }
--    }
--}
--
--/**
-- * This differs from the core PNG ImageWriteParam in that:
-- *
-- * . 'canWriteCompressed' is set to 'true' so that canWriteCompressed()
-- * will return 'true'.
-- * . compression types are: "DEFAULT", "FILTERED", and "HUFFMAN_ONLY"
-- * and are used to set the encoder strategy to Z_DEFAULT, Z_FILTERED,
-- * and Z_HUFFMAN_ONLY as described in the PNG specification.
-- * . compression modes are: MODE_DEFAULT, MODE_EXPLICIT and
-- * MODE_COPY_FROM_METADATA); MODE_DISABLED is not allowed.
-- * . compression quality is used to set the compression level of the
-- * encoder according to:
-- *
-- *     compressionLevel = (int)(9*(1.0F - compressionQuality))
-- *
-- * As in the core PNG writer, a progressiveMode of MODE_DEFAULT sets
-- * Adam7 interlacing whereas MODE_DISABLED sets default interlacing,
-- * i.e., none.
-- */
--final class CLibPNGImageWriteParam extends ImageWriteParam {
--    private static final float DEFAULT_COMPRESSION_QUALITY = 1.0F/3.0F;
--
--    // Encoder strategies mapped to compression types.
--    private static final String DEFAULT_COMPRESSION_TYPE = "DEFAULT";
--    private static final String FILTERED_COMPRESSION_TYPE = "FILTERED";
--    private static final String HUFFMAN_COMPRESSION_TYPE = "HUFFMAN_ONLY";
--
--    // Compression descriptions
--    private static final String[] compressionQualityDescriptions =
--        new String[] {
--            I18N.getString("CLibPNGImageWriteParam0"),
--            I18N.getString("CLibPNGImageWriteParam1"),
--            I18N.getString("CLibPNGImageWriteParam2")
--        };
--
--    CLibPNGImageWriteParam(Locale locale) {
--        super(locale);
--
--        canWriteCompressed = true;
--        canWriteProgressive = true;
--        compressionTypes = new String[] {DEFAULT_COMPRESSION_TYPE,
--                                         FILTERED_COMPRESSION_TYPE,
--                                         HUFFMAN_COMPRESSION_TYPE};
--
--        compressionQuality = DEFAULT_COMPRESSION_QUALITY;
--        compressionType    = DEFAULT_COMPRESSION_TYPE;
--    }
--
--    int getStrategy() {
--        if(compressionType.equals(FILTERED_COMPRESSION_TYPE)) {
--            return 1; // Z_FILTERED
--        } else if(compressionType.equals(HUFFMAN_COMPRESSION_TYPE)) {
--            return 2; // Z_HUFFMAN_ONLY
--        } else {
--            return 0; // Z_DEFAULT_STRATEGY
--        }
--    }
--
--    public String[] getCompressionQualityDescriptions() {
--        super.getCompressionQualityDescriptions(); // Performs checks.
--
--        return compressionQualityDescriptions;
--    }
--
--    public float[] getCompressionQualityValues() {
--        super.getCompressionQualityValues(); // Performs checks.
--
--        // According to the java.util.zip.Deflater class, the Deflater
--        // level 1 gives the best speed (short of no compression). Since
--        // quality is derived from level as
--        //
--        //     quality = 1 - level/9
--        //
--        // this gives a value of 8.0/9.0 for the corresponding quality.
--        return new float[] { 0.0F,               // "Best Compression"
--                             (float)(8.0F/9.0F), // "Best Speed"
--                             1.0F };             // "No Compression"
--    }
--
--    public void setCompressionMode(int mode) {
--        if(mode == MODE_DISABLED) {
--            throw new UnsupportedOperationException("mode == MODE_DISABLED");
--        }
--
--        super.setCompressionMode(mode); // This sets the instance variable.
--    }
--
--    public void unsetCompression() {
--        super.unsetCompression(); // Performs checks.
--
--        compressionQuality = DEFAULT_COMPRESSION_QUALITY;
--        compressionType    = DEFAULT_COMPRESSION_TYPE;
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGImageWriterSpi.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGImageWriterSpi.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,209 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibPNGImageWriterSpi.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.2 $
-- * $Date: 2006/03/31 19:43:40 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.png;
--
--import java.awt.image.ColorModel;
--import java.awt.image.IndexColorModel;
--import java.awt.image.SampleModel;
--import java.util.List;
--import java.util.Locale;
--import javax.imageio.ImageWriter;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.metadata.IIOMetadataFormat;
--import javax.imageio.metadata.IIOMetadataFormatImpl;
--import javax.imageio.spi.ImageWriterSpi;
--import javax.imageio.spi.ServiceRegistry;
--import com.sun.media.imageioimpl.common.PackageUtil;
--import com.sun.media.imageioimpl.common.ImageUtil;
--
--/**
-- */
--public class CLibPNGImageWriterSpi extends ImageWriterSpi {
--
--    private static final String[] names = {"png", "PNG"};
--    
--    private static final String[] suffixes = { "png" };
--    
--    private static final String[] MIMETypes = { "image/png", "image/x-png" };
--    
--    private static final String writerClassName =
--        "com.sun.media.imageioimpl.plugins.png.CLibPNGImageWriter";
--    
--    private static final String[] readerSpiNames = {
--        "com.sun.media.imageioimpl.plugins.png.CLibPNGImageReaderSpi"
--    };
--
--    private boolean registered = false;
--
--    public CLibPNGImageWriterSpi() {
--        super(PackageUtil.getVendor(),
--              PackageUtil.getVersion(),
--              names,
--              suffixes,
--              MIMETypes,
--              writerClassName,
--              STANDARD_OUTPUT_TYPE,
--              readerSpiNames,
--              false,
--              null, null,
--              null, null,
--              true,
--              CLibPNGMetadata.nativeMetadataFormatName,
--              "com.sun.media.imageioimpl.plugins.png.CLibPNGMetadataFormat",
--              null, null);
--    }
--
--    public void onRegistration(ServiceRegistry registry,
--                               Class category) {
--        if (registered) {
--            return;
--        }
--	
--        registered = true;
--
--        // Branch as a function of codecLib availability.
--        if(!PackageUtil.isCodecLibAvailable()) {
--            // Deregister provider.
--            registry.deregisterServiceProvider(this);
--        } else {
--
--	    List list = 
--		ImageUtil.getJDKImageReaderWriterSPI(registry, "PNG", false);
--
--	    for (int i=0; i<list.size(); i++) {
--		// Set pairwise ordering to give codecLib writer precedence
--		// over Sun core J2SE writer.
--		registry.setOrdering(category, this, list.get(i));
--	    }
--        }
--    }
--
--    public boolean canEncodeImage(ImageTypeSpecifier type) {
--        SampleModel sampleModel = type.getSampleModel();
--        ColorModel colorModel = type.getColorModel();
--
--        // Ensure all channels have the same bit depth
--        int[] sampleSize = sampleModel.getSampleSize(); 
--        int bitDepth = sampleSize[0];
--        for (int i = 1; i < sampleSize.length; i++) {
--            if (sampleSize[i] != bitDepth) {
--                return false;
--            }
--        }
--
--        // Ensure bitDepth is either 1, 8, or 16.
--        // XXX If codecLib writing support is improved this might
--        // be able to accept all depths between 1 and 16 inclusive.
--        if (!(bitDepth == 1 || bitDepth == 8 || bitDepth == 16)) {
--            return false;
--        }
--
--        // Check number of bands, alpha
--        int numBands = sampleModel.getNumBands();
--        if (numBands < 1 || numBands > 4) {
--            return false;
--        }
--
--        if (colorModel instanceof IndexColorModel) {
--            return true;
--        }
--
--        boolean hasAlpha = colorModel != null && colorModel.hasAlpha();
--        if ((numBands == 1 || numBands == 3) && hasAlpha) {
--            return false;
--        }
--        if ((numBands == 2 || numBands == 4) && !hasAlpha) {
--            return false;
--        }
--
--        return true;
--    }
--
--    public String getDescription(Locale locale) {
--	String desc = PackageUtil.getSpecificationTitle() + 
--	    " natively-accelerated PNG Image Writer";
--	return desc;
--    }
--
--    public ImageWriter createWriterInstance(Object extension) {
--        return new CLibPNGImageWriter(this);
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGMetadata.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGMetadata.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,2944 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibPNGMetadata.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.3 $
-- * $Date: 2006/02/27 17:25:04 $
-- * $State: Exp $
-- */
--
--package com.sun.media.imageioimpl.plugins.png;
--
--import java.awt.image.ColorModel;
--import java.awt.image.IndexColorModel;
--import java.awt.image.SampleModel;
--import java.io.ByteArrayInputStream;
--import java.io.InputStream;
--import java.io.IOException;
--import java.io.UnsupportedEncodingException;
--import java.util.ArrayList;
--import java.util.Arrays;
--import java.util.Calendar;
--import java.util.GregorianCalendar;
--import java.util.Iterator;
--import java.util.List;
--import java.util.StringTokenizer;
--import java.util.zip.DataFormatException;
--import java.util.zip.Deflater;
--import java.util.zip.Inflater;
--import javax.imageio.IIOException;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.ImageWriteParam;
--import javax.imageio.metadata.IIOInvalidTreeException;
--import javax.imageio.metadata.IIOMetadata;
--import javax.imageio.metadata.IIOMetadataFormat;
--import javax.imageio.metadata.IIOMetadataFormatImpl;
--import javax.imageio.metadata.IIOMetadataNode;
--import javax.imageio.stream.ImageInputStream;
--import javax.imageio.stream.MemoryCacheImageInputStream;
--import org.w3c.dom.Node;
--import com.sun.medialib.codec.png.Decoder;
--import com.sun.medialib.codec.png.Encoder;
--import com.sun.medialib.codec.png.PNGChunk;
--import com.sun.medialib.codec.png.PNGTextualData;
--import com.sun.medialib.codec.jiio.mediaLibImage;
--
--//
--// Core J2SE problems fixed in this package:
--// 5109146:
--// PNG: Background color initialization from standard metadata is incomplete
--// 5109114:
--// PNG: Cannot set IHDR_bitDepth from standard metadata /Data/BitsPerSample
--// 5106305:
--// PNG standard to native image metadata conversion incorrect for pixel size
--// 5106550:
--// PNG writer merge standard metadata fails for TextEntry sans #IMPLIED
--// attributes
--// 5082756:
--// Image I/O plug-ins set metadata boolean attributes to "true" or "false"
--// 5105068:
--// PNGImageWriter.convertImageMetadata() broken for non-PNGMetadata
--//
--
--/**
-- */
--public class CLibPNGMetadata extends IIOMetadata implements Cloneable {
--
--    // package scope
--    public static final String
--        nativeMetadataFormatName = "javax_imageio_png_1.0";
--
--    protected static final String nativeMetadataFormatClassName 
--        = "com.sun.media.imageioimpl.plugins.png.CLibPNGMetadataFormat";
--
--    // Color types for IHDR chunk
--    public static final String[] IHDR_colorTypeNames = {
--        "Grayscale", null, "RGB", "Palette",
--        "GrayAlpha", null, "RGBAlpha"
--    };
--
--    public static final int[] IHDR_numChannels = {
--        1, 0, 3, 3, 2, 0, 4
--    };
--
--    // Bit depths for IHDR chunk
--    public static final String[] IHDR_bitDepths = {
--        "1", "2", "4", "8", "16"
--    };
--
--    // Compression methods for IHDR chunk
--    public static final String[] IHDR_compressionMethodNames = {
--        "deflate"
--    };
--
--    // Filter methods for IHDR chunk
--    public static final String[] IHDR_filterMethodNames = {
--        "adaptive"
--    };
--
--    // Interlace methods for IHDR chunk
--    public static final String[] IHDR_interlaceMethodNames = {
--        "none", "adam7"
--    };
--
--    // Compression methods for iCCP chunk
--    public static final String[] iCCP_compressionMethodNames = {
--        "deflate"
--    };
--
--    // Compression methods for zTXt chunk
--    public static final String[] zTXt_compressionMethodNames = {
--        "deflate"
--    };
--
--    // "Unknown" unit for pHYs chunk
--    public static final int PHYS_UNIT_UNKNOWN = 0;
--
--    // "Meter" unit for pHYs chunk
--    public static final int PHYS_UNIT_METER = 1;
--
--    // Unit specifiers for pHYs chunk
--    public static final String[] unitSpecifierNames = {
--        "unknown", "meter"
--    };
--
--    // Rendering intents for sRGB chunk
--    public static final String[] renderingIntentNames = {
--        "Perceptual", // 0
--        "Relative colorimetric", // 1
--        "Saturation", // 2
--        "Absolute colorimetric" // 3
--
--    };
--
--    // Color space types for Chroma->ColorSpaceType node
--    public static final String[] colorSpaceTypeNames = {
--        "GRAY", null, "RGB", "RGB",
--        "GRAY", null, "RGB"
--    };
--
--    // BEGIN Definitions required for reading.
--
--    // Critical chunks
--    static final int IHDR_TYPE = chunkType("IHDR");
--    static final int PLTE_TYPE = chunkType("PLTE");
--    static final int IDAT_TYPE = chunkType("IDAT");
--    static final int IEND_TYPE = chunkType("IEND");
--    
--    // Ancillary chunks
--    static final int bKGD_TYPE = chunkType("bKGD");
--    static final int cHRM_TYPE = chunkType("cHRM");
--    static final int gAMA_TYPE = chunkType("gAMA");
--    static final int hIST_TYPE = chunkType("hIST");
--    static final int iCCP_TYPE = chunkType("iCCP");
--    static final int iTXt_TYPE = chunkType("iTXt");
--    static final int pHYs_TYPE = chunkType("pHYs");
--    static final int sBIT_TYPE = chunkType("sBIT");
--    static final int sPLT_TYPE = chunkType("sPLT");
--    static final int sRGB_TYPE = chunkType("sRGB");
--    static final int tEXt_TYPE = chunkType("tEXt");
--    static final int tIME_TYPE = chunkType("tIME");
--    static final int tRNS_TYPE = chunkType("tRNS");
--    static final int zTXt_TYPE = chunkType("zTXt");
--
--    static final int PNG_COLOR_GRAY = 0;
--    static final int PNG_COLOR_RGB = 2;
--    static final int PNG_COLOR_PALETTE = 3;
--    static final int PNG_COLOR_GRAY_ALPHA = 4;
--    static final int PNG_COLOR_RGB_ALPHA = 6;
--
--    // END Definitions required for reading.
--
--    // IHDR chunk
--    public boolean IHDR_present;
--    public int IHDR_width;
--    public int IHDR_height;
--    public int IHDR_bitDepth;
--    public int IHDR_colorType;
--    public int IHDR_compressionMethod;
--    public int IHDR_filterMethod;
--    public int IHDR_interlaceMethod; // 0 == none, 1 == adam7
--
--    // PLTE chunk
--    public boolean PLTE_present;
--    public byte[] PLTE_red;
--    public byte[] PLTE_green;
--    public byte[] PLTE_blue;
--
--    // bKGD chunk
--    // If external (non-PNG sourced) data has red = green = blue,
--    // always store it as gray and promote when writing
--    public boolean bKGD_present;
--    public int bKGD_colorType; // PNG_COLOR_GRAY, _RGB, or _PALETTE
--    public int bKGD_index;
--    public int bKGD_gray;
--    public int bKGD_red;
--    public int bKGD_green;
--    public int bKGD_blue;
--
--    // cHRM chunk
--    public boolean cHRM_present;
--    public int cHRM_whitePointX;
--    public int cHRM_whitePointY;
--    public int cHRM_redX;
--    public int cHRM_redY;
--    public int cHRM_greenX;
--    public int cHRM_greenY;
--    public int cHRM_blueX;
--    public int cHRM_blueY;
--
--    // gAMA chunk
--    public boolean gAMA_present;
--    public int gAMA_gamma;
--
--    // hIST chunk
--    public boolean hIST_present;
--    public char[] hIST_histogram;
--
--    // iCCP chunk
--    public boolean iCCP_present;
--    public String iCCP_profileName;
--    public int iCCP_compressionMethod;
--    public byte[] iCCP_compressedProfile;
--
--    // iTXt chunk
--    public ArrayList iTXt_keyword = new ArrayList(); // Strings
--    public ArrayList iTXt_compressionFlag = new ArrayList(); // Integers
--    public ArrayList iTXt_compressionMethod = new ArrayList(); // Integers
--    public ArrayList iTXt_languageTag = new ArrayList(); // Strings
--    public ArrayList iTXt_translatedKeyword = new ArrayList(); // Strings
--    public ArrayList iTXt_text = new ArrayList(); // Strings
--
--    // pHYs chunk
--    public boolean pHYs_present;
--    public int pHYs_pixelsPerUnitXAxis;
--    public int pHYs_pixelsPerUnitYAxis;
--    public int pHYs_unitSpecifier; // 0 == unknown, 1 == meter
--
--    // sBIT chunk
--    public boolean sBIT_present;
--    public int sBIT_colorType; // PNG_COLOR_GRAY, _GRAY_ALPHA, _RGB, _RGB_ALPHA
--    public int sBIT_grayBits;
--    public int sBIT_redBits;
--    public int sBIT_greenBits;
--    public int sBIT_blueBits;
--    public int sBIT_alphaBits;
--    
--    // sPLT chunk
--    public boolean sPLT_present;
--    public String sPLT_paletteName; // 1-79 characters
--    public int sPLT_sampleDepth; // 8 or 16
--    public int[] sPLT_red;
--    public int[] sPLT_green;
--    public int[] sPLT_blue;
--    public int[] sPLT_alpha;
--    public int[] sPLT_frequency;
--
--    // sRGB chunk
--    public boolean sRGB_present;
--    public int sRGB_renderingIntent;
--
--    // tEXt chunk
--    public ArrayList tEXt_keyword = new ArrayList(); // 1-79 char Strings
--    public ArrayList tEXt_text = new ArrayList(); // Strings
--
--    // tIME chunk
--    public boolean tIME_present;
--    public int tIME_year;
--    public int tIME_month;
--    public int tIME_day;
--    public int tIME_hour;
--    public int tIME_minute;
--    public int tIME_second;
--
--    // tRNS chunk
--    // If external (non-PNG sourced) data has red = green = blue,
--    // always store it as gray and promote when writing
--    public boolean tRNS_present;
--    public int tRNS_colorType; // PNG_COLOR_GRAY, _RGB, or _PALETTE
--    public byte[] tRNS_alpha; // May have fewer entries than PLTE_red, etc.
--    public int tRNS_gray;
--    public int tRNS_red;
--    public int tRNS_green;
--    public int tRNS_blue;
--
--    // zTXt chunk
--    public ArrayList zTXt_keyword = new ArrayList(); // Strings
--    public ArrayList zTXt_compressionMethod = new ArrayList(); // Integers
--    public ArrayList zTXt_text = new ArrayList(); // Strings
--
--    // Unknown chunks
--    public ArrayList unknownChunkType = new ArrayList(); // Strings
--    public ArrayList unknownChunkData = new ArrayList(); // byte arrays
--
--    /**
--     * Converts its parameter to another <code>String</code> which contains
--     * only printable Latin-1 characters but not leading, trailing, or
--     * consecutive spaces.
--     *
--     * @param s the <code>String</code> to convert.
--     * @return a printable Latin-1 <code>String</code> sans superfluous spaces.
--     */
--    static String toPrintableLatin1(String s) {
--        // Pass a null right back.
--        if(s == null) return null;
--
--        // Get Latin-1 characters.
--        byte[] data = null;
--        try {
--            data = s.getBytes("ISO-8859-1");
--        } catch(UnsupportedEncodingException e) {
--            // In theory this should not happen (assert).
--            data = s.getBytes();
--        }
--
--        // Copy printable characters omitting leading spaces and
--        // all but first trailing space.
--	int len = 0;
--	int prev = 0;
--	for (int i = 0; i < data.length; i++) {
--	    int d = data[i] & 0xFF;
--	    if (prev == 32 && d == 32)
--		continue; 
--	    if ((d > 32 && d <=126) || (d >= 161 && d <=255) ||
--                (d == 32 && len != 0))
--		data[len++] = (byte)d;
--	    prev = d;
--	}
--
--        // Return an empty string if no acceptable characters.
--        if(len == 0) return "";
--
--        // Omit trailing space, if any.
--        if(data[len - 1] == 32) len--;
--
--	return new String(data, 0, len);
--    }
--
--    public CLibPNGMetadata() {
--        super(true, 
--              nativeMetadataFormatName,
--              nativeMetadataFormatClassName,
--              null, null);
--    }
--    
--    public CLibPNGMetadata(IIOMetadata metadata)
--        throws IIOInvalidTreeException {
--
--        this();
--
--        if(metadata != null) {
--            List formats = Arrays.asList(metadata.getMetadataFormatNames());
--
--            if(formats.contains(nativeMetadataFormatName)) {
--                // Initialize from native image metadata format.
--                String format = nativeMetadataFormatName;
--                setFromTree(format, metadata.getAsTree(format));
--            } else if(metadata.isStandardMetadataFormatSupported()) {
--                // Initialize from standard metadata form of the input tree.
--                String format =
--                    IIOMetadataFormatImpl.standardMetadataFormatName;
--                setFromTree(format, metadata.getAsTree(format));
--            }
--        }
--    }
--
--    /**
--     * Sets the instance variables of the IHDR and if necessary PLTE and
--     * tRNS chunks. The <code>numBands</code> parameter is necessary since
--     * we may only be writing a subset of the image bands.
--     */
--    public void initialize(ImageTypeSpecifier imageType,
--                           int numBands,
--                           ImageWriteParam param,
--                           int interlaceMethod) {
--        ColorModel colorModel = imageType.getColorModel();
--        SampleModel sampleModel = imageType.getSampleModel();
--
--        // Intialize IHDR_width and IHDR_height
--        IHDR_width = sampleModel.getWidth();
--        IHDR_height = sampleModel.getHeight();
--
--        // Initialize IHDR_bitDepth
--        int[] sampleSize = sampleModel.getSampleSize();
--        int bitDepth = sampleSize[0];
--        // Choose max bit depth over all channels
--        // Fixes bug 4413109
--        for (int i = 1; i < sampleSize.length; i++) {
--            if (sampleSize[i] > bitDepth) {
--		bitDepth = sampleSize[i];
--            }
--        }
--	// Multi-channel images must have a bit depth of 8 or 16
--	if (sampleSize.length > 1 && bitDepth < 8) {
--	    bitDepth = 8;
--	}
--        
--        // Round bit depth up to a power of 2
--        if (bitDepth > 2 && bitDepth < 4) {
--            bitDepth = 4;
--        } else if (bitDepth > 4 && bitDepth < 8) {
--            bitDepth = 8;
--        } else if (bitDepth > 8 && bitDepth < 16) {
--            bitDepth = 16;
--        } else if (bitDepth > 16) {
--            throw new RuntimeException("bitDepth > 16!");
--        }
--        IHDR_bitDepth = bitDepth;
--
--        // Initialize IHDR_colorType
--        if (colorModel instanceof IndexColorModel) {
--            IndexColorModel icm = (IndexColorModel)colorModel;
--            int size = icm.getMapSize();
--
--            byte[] reds = new byte[size];
--            icm.getReds(reds);
--            byte[] greens = new byte[size];
--            icm.getGreens(greens);
--            byte[] blues = new byte[size];
--            icm.getBlues(blues);
--
--            // Determine whether the color tables are actually a gray ramp
--            // if the color type has not been set previously
--            boolean isGray = false;
--            if (!IHDR_present ||
--                (IHDR_colorType != PNG_COLOR_PALETTE)) {
--                isGray = true;
--                int scale = 255/((1 << IHDR_bitDepth) - 1);
--                for (int i = 0; i < size; i++) {
--                    byte red = reds[i];
--                    if ((red != (byte)(i*scale)) ||
--                        (red != greens[i]) ||
--                        (red != blues[i])) {
--                        isGray = false;
--                        break;
--                    }
--                }
--            }
--
--            // Determine whether transparency exists
--            boolean hasAlpha = colorModel.hasAlpha();
--
--            byte[] alpha = null;
--            if (hasAlpha) {
--                alpha = new byte[size];
--                icm.getAlphas(alpha);
--            }
--
--            if (isGray && hasAlpha) {
--                IHDR_colorType = PNG_COLOR_GRAY_ALPHA;
--            } else if (isGray) {
--                IHDR_colorType = PNG_COLOR_GRAY;
--            } else {
--                IHDR_colorType = PNG_COLOR_PALETTE;
--
--                // Initialize PLTE chunk
--                PLTE_present = true;
--                PLTE_red = (byte[])reds.clone();
--                PLTE_green = (byte[])greens.clone();
--                PLTE_blue = (byte[])blues.clone();
--
--                if (hasAlpha) {
--                    // Initialize tRNS chunk
--                    tRNS_present = true;
--                    tRNS_colorType = PNG_COLOR_PALETTE;
--                    tRNS_alpha = (byte[])alpha.clone();
--                }
--            }
--        } else {
--            if (numBands == 1) {
--                IHDR_colorType = PNG_COLOR_GRAY;
--            } else if (numBands == 2) {
--                IHDR_colorType = PNG_COLOR_GRAY_ALPHA;
--            } else if (numBands == 3) {
--                IHDR_colorType = PNG_COLOR_RGB;
--            } else if (numBands == 4) {
--                IHDR_colorType = PNG_COLOR_RGB_ALPHA;
--            } else {
--                throw new RuntimeException("Number of bands not 1-4!");
--            }
--        }
--
--        // Initialize IHDR_compressionMethod and IHDR_filterMethod
--        IHDR_compressionMethod = IHDR_filterMethod = 0; // Only supported value
--
--        // Initialize IHDR_interlaceMethod
--        if(param != null &&
--           param.getProgressiveMode() == ImageWriteParam.MODE_DISABLED) {
--            IHDR_interlaceMethod = 0; // No interlacing.
--        } else if(param != null &&
--                  param.getProgressiveMode() == ImageWriteParam.MODE_DEFAULT) {
--            IHDR_interlaceMethod = 1; // Adam7
--        } else {
--            // param == null ||
--            // param.getProgressiveMode() ==
--            // ImageWriteParam.MODE_COPY_FROM_METADATA
--            IHDR_interlaceMethod = interlaceMethod;
--        }
--
--        IHDR_present = true;
--    }
--
--    public boolean isReadOnly() {
--        return false;
--    }
--
--    private ArrayList cloneBytesArrayList(ArrayList in) {
--        if (in == null) {
--            return null;
--        } else {
--            ArrayList list = new ArrayList(in.size());
--            Iterator iter = in.iterator();
--            while (iter.hasNext()) {
--                Object o = iter.next();
--                if (o == null) {
--                    list.add(null);
--                } else {
--                    list.add(((byte[])o).clone());
--                }
--            }
--
--            return list;
--        }
--    }
--
--    // Deep clone
--    public Object clone() {
--        CLibPNGMetadata metadata;
--        try {
--            metadata = (CLibPNGMetadata)super.clone();
--        } catch (CloneNotSupportedException e) {
--            return null;
--        }
--        
--        // unknownChunkData needs deep clone
--        metadata.unknownChunkData =
--            cloneBytesArrayList(this.unknownChunkData);
--
--        return metadata;
--    }
--
--    public Node getAsTree(String formatName) {
--        if (formatName.equals(nativeMetadataFormatName)) {
--            return getNativeTree();
--        } else if (formatName.equals
--                   (IIOMetadataFormatImpl.standardMetadataFormatName)) {
--            return getStandardTree();
--        } else {
--            throw new IllegalArgumentException("Not a recognized format!");
--        }
--    }
--
--    private Node getNativeTree() {
--        IIOMetadataNode node = null; // scratch node
--        IIOMetadataNode root = new IIOMetadataNode(nativeMetadataFormatName);
--        
--        // IHDR
--        if (IHDR_present) {
--            IIOMetadataNode IHDR_node = new IIOMetadataNode("IHDR");
--            IHDR_node.setAttribute("width", Integer.toString(IHDR_width));
--            IHDR_node.setAttribute("height", Integer.toString(IHDR_height));
--            IHDR_node.setAttribute("bitDepth",
--                                   Integer.toString(IHDR_bitDepth));
--            IHDR_node.setAttribute("colorType",
--                                   IHDR_colorTypeNames[IHDR_colorType]);
--            // IHDR_compressionMethod must be 0 in PNG 1.1
--            IHDR_node.setAttribute("compressionMethod",
--                          IHDR_compressionMethodNames[IHDR_compressionMethod]);
--            // IHDR_filterMethod must be 0 in PNG 1.1
--            IHDR_node.setAttribute("filterMethod",
--                                    IHDR_filterMethodNames[IHDR_filterMethod]);
--            IHDR_node.setAttribute("interlaceMethod",
--                              IHDR_interlaceMethodNames[IHDR_interlaceMethod]);
--            root.appendChild(IHDR_node);
--        }
--
--        // PLTE
--        if (PLTE_present) {
--            IIOMetadataNode PLTE_node = new IIOMetadataNode("PLTE");
--            int numEntries = PLTE_red.length;
--            for (int i = 0; i < numEntries; i++) {
--                IIOMetadataNode entry = new IIOMetadataNode("PLTEEntry");
--                entry.setAttribute("index", Integer.toString(i));
--                entry.setAttribute("red",
--                                   Integer.toString(PLTE_red[i] & 0xff));
--                entry.setAttribute("green",
--                                   Integer.toString(PLTE_green[i] & 0xff));
--                entry.setAttribute("blue",
--                                   Integer.toString(PLTE_blue[i] & 0xff));
--                PLTE_node.appendChild(entry);
--            }
--
--            root.appendChild(PLTE_node);
--        }
--
--        // bKGD
--        if (bKGD_present) {
--            IIOMetadataNode bKGD_node = new IIOMetadataNode("bKGD");
--            
--            if (bKGD_colorType == PNG_COLOR_PALETTE) {
--                node = new IIOMetadataNode("bKGD_Palette");
--                node.setAttribute("index", Integer.toString(bKGD_index));
--            } else if (bKGD_colorType == PNG_COLOR_GRAY) {
--                node = new IIOMetadataNode("bKGD_Grayscale");
--                node.setAttribute("gray", Integer.toString(bKGD_gray));
--            } else if (bKGD_colorType == PNG_COLOR_RGB) {
--                node = new IIOMetadataNode("bKGD_RGB");
--                node.setAttribute("red", Integer.toString(bKGD_red));
--                node.setAttribute("green", Integer.toString(bKGD_green));
--                node.setAttribute("blue", Integer.toString(bKGD_blue));
--            }
--            bKGD_node.appendChild(node);
--
--            root.appendChild(bKGD_node);
--        }
--
--        // cHRM
--        if (cHRM_present) {
--            IIOMetadataNode cHRM_node = new IIOMetadataNode("cHRM");
--            cHRM_node.setAttribute("whitePointX",
--                              Integer.toString(cHRM_whitePointX));
--            cHRM_node.setAttribute("whitePointY",
--                              Integer.toString(cHRM_whitePointY));
--            cHRM_node.setAttribute("redX", Integer.toString(cHRM_redX));
--            cHRM_node.setAttribute("redY", Integer.toString(cHRM_redY));
--            cHRM_node.setAttribute("greenX", Integer.toString(cHRM_greenX));
--            cHRM_node.setAttribute("greenY", Integer.toString(cHRM_greenY));
--            cHRM_node.setAttribute("blueX", Integer.toString(cHRM_blueX));
--            cHRM_node.setAttribute("blueY", Integer.toString(cHRM_blueY));
--
--            root.appendChild(cHRM_node);
--        }
--
--        // gAMA
--        if (gAMA_present) {
--            IIOMetadataNode gAMA_node = new IIOMetadataNode("gAMA");
--            gAMA_node.setAttribute("value", Integer.toString(gAMA_gamma));
--
--            root.appendChild(gAMA_node);
--        }
--
--        // hIST
--        if (hIST_present) {
--            IIOMetadataNode hIST_node = new IIOMetadataNode("hIST");
--
--            for (int i = 0; i < hIST_histogram.length; i++) {
--                IIOMetadataNode hist =
--                    new IIOMetadataNode("hISTEntry");
--                hist.setAttribute("index", Integer.toString(i));
--                hist.setAttribute("value",
--                                  Integer.toString(hIST_histogram[i]));
--                hIST_node.appendChild(hist);
--            }
--
--            root.appendChild(hIST_node);
--        }
--
--        // iCCP
--        if (iCCP_present) {
--            IIOMetadataNode iCCP_node = new IIOMetadataNode("iCCP");
--            iCCP_node.setAttribute("profileName", iCCP_profileName);
--            iCCP_node.setAttribute("compressionMethod",
--                          iCCP_compressionMethodNames[iCCP_compressionMethod]);
--
--            Object profile = iCCP_compressedProfile;
--            if (profile != null) {
--                profile = ((byte[])profile).clone();
--            }
--            iCCP_node.setUserObject(profile);
--
--            root.appendChild(iCCP_node);
--        }
--
--        // iTXt
--        if (iTXt_keyword.size() > 0) {
--            IIOMetadataNode iTXt_parent = new IIOMetadataNode("iTXt");
--            for (int i = 0; i < iTXt_keyword.size(); i++) {
--                Integer val;
--                
--                IIOMetadataNode iTXt_node = new IIOMetadataNode("iTXtEntry");
--                iTXt_node.setAttribute("keyword", (String)iTXt_keyword.get(i));
--                val = (Integer)iTXt_compressionFlag.get(i);
--                iTXt_node.setAttribute("compressionFlag", val.toString());
--                val = (Integer)iTXt_compressionMethod.get(i);
--                iTXt_node.setAttribute("compressionMethod", val.toString());
--                iTXt_node.setAttribute("languageTag",
--                                       (String)iTXt_languageTag.get(i));
--                iTXt_node.setAttribute("translatedKeyword",
--                                       (String)iTXt_translatedKeyword.get(i));
--                iTXt_node.setAttribute("text", (String)iTXt_text.get(i));
--                
--                iTXt_parent.appendChild(iTXt_node);
--            }
--            
--            root.appendChild(iTXt_parent);
--        }
--
--        // pHYs
--        if (pHYs_present) {
--            IIOMetadataNode pHYs_node = new IIOMetadataNode("pHYs");
--            pHYs_node.setAttribute("pixelsPerUnitXAxis",
--                              Integer.toString(pHYs_pixelsPerUnitXAxis));
--            pHYs_node.setAttribute("pixelsPerUnitYAxis",
--                                   Integer.toString(pHYs_pixelsPerUnitYAxis));
--            pHYs_node.setAttribute("unitSpecifier",
--                                   unitSpecifierNames[pHYs_unitSpecifier]);
--
--            root.appendChild(pHYs_node);
--        }
--
--        // sBIT
--        if (sBIT_present) {
--            IIOMetadataNode sBIT_node = new IIOMetadataNode("sBIT");
--
--            if (sBIT_colorType == PNG_COLOR_GRAY) {
--                node = new IIOMetadataNode("sBIT_Grayscale");
--                node.setAttribute("gray",
--                                  Integer.toString(sBIT_grayBits));
--            } else if (sBIT_colorType == PNG_COLOR_GRAY_ALPHA) {
--                node = new IIOMetadataNode("sBIT_GrayAlpha");
--                node.setAttribute("gray",
--                                  Integer.toString(sBIT_grayBits));
--                node.setAttribute("alpha",
--                                  Integer.toString(sBIT_alphaBits));
--            } else if (sBIT_colorType == PNG_COLOR_RGB) {
--                node = new IIOMetadataNode("sBIT_RGB");
--                node.setAttribute("red",
--                                  Integer.toString(sBIT_redBits));
--                node.setAttribute("green",
--                                  Integer.toString(sBIT_greenBits));
--                node.setAttribute("blue",
--                                  Integer.toString(sBIT_blueBits));
--            } else if (sBIT_colorType == PNG_COLOR_RGB_ALPHA) {
--                node = new IIOMetadataNode("sBIT_RGBAlpha");
--                node.setAttribute("red",
--                                  Integer.toString(sBIT_redBits));
--                node.setAttribute("green",
--                                  Integer.toString(sBIT_greenBits));
--                node.setAttribute("blue",
--                                  Integer.toString(sBIT_blueBits));
--                node.setAttribute("alpha",
--                                  Integer.toString(sBIT_alphaBits));
--            } else if (sBIT_colorType == PNG_COLOR_PALETTE) {
--                node = new IIOMetadataNode("sBIT_Palette");
--                node.setAttribute("red",
--                                  Integer.toString(sBIT_redBits));
--                node.setAttribute("green",
--                                  Integer.toString(sBIT_greenBits));
--                node.setAttribute("blue",
--                                  Integer.toString(sBIT_blueBits));
--            }
--            sBIT_node.appendChild(node);
--                
--            root.appendChild(sBIT_node);
--        }
--
--        // sPLT
--        if (sPLT_present) {
--            IIOMetadataNode sPLT_node = new IIOMetadataNode("sPLT");
--
--            sPLT_node.setAttribute("name", sPLT_paletteName);
--            sPLT_node.setAttribute("sampleDepth",
--                                   Integer.toString(sPLT_sampleDepth));
--
--            int numEntries = sPLT_red.length;
--            for (int i = 0; i < numEntries; i++) {
--                IIOMetadataNode entry = new IIOMetadataNode("sPLTEntry");
--                entry.setAttribute("index", Integer.toString(i));
--                entry.setAttribute("red", Integer.toString(sPLT_red[i]));
--                entry.setAttribute("green", Integer.toString(sPLT_green[i]));
--                entry.setAttribute("blue", Integer.toString(sPLT_blue[i]));
--                entry.setAttribute("alpha", Integer.toString(sPLT_alpha[i]));
--                entry.setAttribute("frequency",
--                                  Integer.toString(sPLT_frequency[i]));
--                sPLT_node.appendChild(entry);
--            }
--
--            root.appendChild(sPLT_node);
--        }
--
--        // sRGB
--        if (sRGB_present) {
--            IIOMetadataNode sRGB_node = new IIOMetadataNode("sRGB");
--            sRGB_node.setAttribute("renderingIntent",
--                                   renderingIntentNames[sRGB_renderingIntent]);
--
--            root.appendChild(sRGB_node);
--        }
--
--        // tEXt
--        if (tEXt_keyword.size() > 0) {
--            IIOMetadataNode tEXt_parent = new IIOMetadataNode("tEXt");
--            for (int i = 0; i < tEXt_keyword.size(); i++) {
--                IIOMetadataNode tEXt_node = new IIOMetadataNode("tEXtEntry");
--                tEXt_node.setAttribute("keyword" , (String)tEXt_keyword.get(i));
--                tEXt_node.setAttribute("value" , (String)tEXt_text.get(i));
--                
--                tEXt_parent.appendChild(tEXt_node);
--            }
--                
--            root.appendChild(tEXt_parent);
--        }
--
--        // tIME
--        if (tIME_present) {
--            IIOMetadataNode tIME_node = new IIOMetadataNode("tIME");
--            tIME_node.setAttribute("year", Integer.toString(tIME_year));
--            tIME_node.setAttribute("month", Integer.toString(tIME_month));
--            tIME_node.setAttribute("day", Integer.toString(tIME_day));
--            tIME_node.setAttribute("hour", Integer.toString(tIME_hour));
--            tIME_node.setAttribute("minute", Integer.toString(tIME_minute));
--            tIME_node.setAttribute("second", Integer.toString(tIME_second));
--
--            root.appendChild(tIME_node);
--        }
--
--        // tRNS
--        if (tRNS_present) {
--            IIOMetadataNode tRNS_node = new IIOMetadataNode("tRNS");
--
--            if (tRNS_colorType == PNG_COLOR_PALETTE) {
--                node = new IIOMetadataNode("tRNS_Palette");
--                
--                for (int i = 0; i < tRNS_alpha.length; i++) {
--                    IIOMetadataNode entry =
--                        new IIOMetadataNode("tRNS_PaletteEntry");
--                    entry.setAttribute("index", Integer.toString(i));
--                    entry.setAttribute("alpha",
--                                       Integer.toString(tRNS_alpha[i] & 0xff));
--                    node.appendChild(entry);
--                }
--            } else if (tRNS_colorType == PNG_COLOR_GRAY) {
--                node = new IIOMetadataNode("tRNS_Grayscale");
--                node.setAttribute("gray", Integer.toString(tRNS_gray));
--            } else if (tRNS_colorType == PNG_COLOR_RGB) {
--                node = new IIOMetadataNode("tRNS_RGB");
--                node.setAttribute("red", Integer.toString(tRNS_red));
--                node.setAttribute("green", Integer.toString(tRNS_green));
--                node.setAttribute("blue", Integer.toString(tRNS_blue));
--            }
--            tRNS_node.appendChild(node);
--            
--            root.appendChild(tRNS_node);
--        }
--
--        // zTXt
--        if (zTXt_keyword.size() > 0) {
--            IIOMetadataNode zTXt_parent = new IIOMetadataNode("zTXt");
--            for (int i = 0; i < zTXt_keyword.size(); i++) {
--                IIOMetadataNode zTXt_node = new IIOMetadataNode("zTXtEntry");
--                zTXt_node.setAttribute("keyword", (String)zTXt_keyword.get(i));
--
--                int cm = ((Integer)zTXt_compressionMethod.get(i)).intValue();
--                zTXt_node.setAttribute("compressionMethod",
--                                       zTXt_compressionMethodNames[cm]);
--
--                zTXt_node.setAttribute("text", (String)zTXt_text.get(i));
--
--                zTXt_parent.appendChild(zTXt_node);
--            }
--
--            root.appendChild(zTXt_parent);
--        }
--        
--        // Unknown chunks
--        if (unknownChunkType.size() > 0) {
--            IIOMetadataNode unknown_parent =
--                new IIOMetadataNode("UnknownChunks");
--            for (int i = 0; i < unknownChunkType.size(); i++) {
--                IIOMetadataNode unknown_node =
--                    new IIOMetadataNode("UnknownChunk");
--                unknown_node.setAttribute("type",
--                                          (String)unknownChunkType.get(i));
--                unknown_node.setUserObject((byte[])unknownChunkData.get(i));
--                
--                unknown_parent.appendChild(unknown_node);
--            }
--            
--            root.appendChild(unknown_parent);
--        }
--
--        return root;
--    }
--
--    private int getNumChannels() {
--        // Determine number of channels
--        // Be careful about palette color with transparency
--        int numChannels = IHDR_numChannels[IHDR_colorType];
--        if (IHDR_colorType == PNG_COLOR_PALETTE &&
--            tRNS_present && tRNS_colorType == IHDR_colorType) {
--            numChannels = 4;
--        }
--        return numChannels;
--    }
--
--    public IIOMetadataNode getStandardChromaNode() {
--        IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma");
--        IIOMetadataNode node = null; // scratch node
--
--        node = new IIOMetadataNode("ColorSpaceType");
--        node.setAttribute("name", colorSpaceTypeNames[IHDR_colorType]);
--        chroma_node.appendChild(node);
--
--        node = new IIOMetadataNode("NumChannels");
--        node.setAttribute("value", Integer.toString(getNumChannels()));
--        chroma_node.appendChild(node);
--
--        if (gAMA_present) {
--            node = new IIOMetadataNode("Gamma");
--            node.setAttribute("value", Float.toString(gAMA_gamma*1.0e-5F));
--            chroma_node.appendChild(node);
--        }
--
--        node = new IIOMetadataNode("BlackIsZero");
--        node.setAttribute("value", "TRUE");
--        chroma_node.appendChild(node);
--
--        if (PLTE_present) {
--            boolean hasAlpha = tRNS_present &&
--                (tRNS_colorType == PNG_COLOR_PALETTE);
--
--            node = new IIOMetadataNode("Palette");
--            for (int i = 0; i < PLTE_red.length; i++) {
--                IIOMetadataNode entry =
--                    new IIOMetadataNode("PaletteEntry");
--                entry.setAttribute("index", Integer.toString(i));
--                entry.setAttribute("red",
--                                   Integer.toString(PLTE_red[i] & 0xff));
--                entry.setAttribute("green",
--                                   Integer.toString(PLTE_green[i] & 0xff));
--                entry.setAttribute("blue",
--                                   Integer.toString(PLTE_blue[i] & 0xff));
--                if (hasAlpha) {
--		    int alpha = (i < tRNS_alpha.length) ?
--			(tRNS_alpha[i] & 0xff) : 255;
--                    entry.setAttribute("alpha", Integer.toString(alpha));
--                }
--                node.appendChild(entry);
--            }
--            chroma_node.appendChild(node);
--        }
--
--        if (bKGD_present) {
--            if (bKGD_colorType == PNG_COLOR_PALETTE) {
--                node = new IIOMetadataNode("BackgroundIndex");
--                node.setAttribute("value", Integer.toString(bKGD_index));
--            } else {
--                node = new IIOMetadataNode("BackgroundColor");
--                int r, g, b;
--
--                if (bKGD_colorType == PNG_COLOR_GRAY) {
--                    r = g = b = bKGD_gray;
--                } else {
--                    r = bKGD_red;
--                    g = bKGD_green;
--                    b = bKGD_blue;
--                }
--                node.setAttribute("red", Integer.toString(r));
--                node.setAttribute("green", Integer.toString(g));
--                node.setAttribute("blue", Integer.toString(b));
--            }
--            chroma_node.appendChild(node);
--        }
--
--        return chroma_node;
--    }
--
--    public IIOMetadataNode getStandardCompressionNode() {
--        IIOMetadataNode compression_node = new IIOMetadataNode("Compression");
--        IIOMetadataNode node = null; // scratch node
--
--        node = new IIOMetadataNode("CompressionTypeName");
--        node.setAttribute("value", "deflate");
--        compression_node.appendChild(node);
--
--        node = new IIOMetadataNode("Lossless");
--        node.setAttribute("value", "TRUE");
--        compression_node.appendChild(node);
--
--        node = new IIOMetadataNode("NumProgressiveScans");
--        node.setAttribute("value",
--                          (IHDR_interlaceMethod == 0) ? "1" : "7");
--        compression_node.appendChild(node);
--
--        return compression_node;
--    }
--
--    private String repeat(String s, int times) {
--        if (times == 1) {
--            return s;
--        }
--        StringBuffer sb = new StringBuffer((s.length() + 1)*times - 1);
--        sb.append(s);
--        for (int i = 1; i < times; i++) {
--            sb.append(" ");
--            sb.append(s);
--        }
--        return sb.toString();
--    }
--
--    public IIOMetadataNode getStandardDataNode() {
--        IIOMetadataNode data_node = new IIOMetadataNode("Data");
--        IIOMetadataNode node = null; // scratch node
--
--        node = new IIOMetadataNode("PlanarConfiguration");
--        node.setAttribute("value", "PixelInterleaved");
--        data_node.appendChild(node);
--
--        node = new IIOMetadataNode("SampleFormat");
--        node.setAttribute("value",
--                          IHDR_colorType == PNG_COLOR_PALETTE ?
--                          "Index" : "UnsignedIntegral");
--        data_node.appendChild(node);
--
--        String bitDepth = Integer.toString(IHDR_bitDepth);
--        node = new IIOMetadataNode("BitsPerSample");
--        node.setAttribute("value", repeat(bitDepth, getNumChannels()));
--        data_node.appendChild(node);
--
--        if (sBIT_present) {
--            node = new IIOMetadataNode("SignificantBitsPerSample");
--            String sbits;
--            if (sBIT_colorType == PNG_COLOR_GRAY ||
--                sBIT_colorType == PNG_COLOR_GRAY_ALPHA) {
--                sbits = Integer.toString(sBIT_grayBits);
--            } else { // sBIT_colorType == PNG_COLOR_RGB ||
--                     // sBIT_colorType == PNG_COLOR_RGB_ALPHA
--                sbits = Integer.toString(sBIT_redBits) + " " + 
--                    Integer.toString(sBIT_greenBits) + " " + 
--                    Integer.toString(sBIT_blueBits);
--            }
--
--            if (sBIT_colorType == PNG_COLOR_GRAY_ALPHA ||
--                sBIT_colorType == PNG_COLOR_RGB_ALPHA) {
--                sbits += " " + Integer.toString(sBIT_alphaBits);
--            }
--            
--            node.setAttribute("value", sbits);
--            data_node.appendChild(node);
--        }
--
--        // SampleMSB
--
--        return data_node;
--    }
--
--    public IIOMetadataNode getStandardDimensionNode() {
--        IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension");
--        IIOMetadataNode node = null; // scratch node
--
--        node = new IIOMetadataNode("PixelAspectRatio");
--        // aspect ratio is pixel width/height which is the ratio of the
--        // inverses of pixels per unit length.
--        float ratio = pHYs_present ?
--            (float)pHYs_pixelsPerUnitYAxis/pHYs_pixelsPerUnitXAxis : 1.0F;
--        node.setAttribute("value", Float.toString(ratio));
--        dimension_node.appendChild(node);
--        
--        node = new IIOMetadataNode("ImageOrientation");
--        node.setAttribute("value", "Normal");
--        dimension_node.appendChild(node);
--        
--        if (pHYs_present && pHYs_unitSpecifier == PHYS_UNIT_METER) {
--            node = new IIOMetadataNode("HorizontalPixelSize");
--            node.setAttribute("value",
--                              Float.toString(1000.0F/pHYs_pixelsPerUnitXAxis));
--            dimension_node.appendChild(node);
--
--            node = new IIOMetadataNode("VerticalPixelSize");
--            node.setAttribute("value",
--                              Float.toString(1000.0F/pHYs_pixelsPerUnitYAxis));
--            dimension_node.appendChild(node);
--        }
--
--        return dimension_node;
--    }
--
--    public IIOMetadataNode getStandardDocumentNode() {
--        if (!tIME_present) {
--            return null;
--        }
--
--        IIOMetadataNode document_node = new IIOMetadataNode("Document");
--        IIOMetadataNode node = null; // scratch node
--
--        node = new IIOMetadataNode("ImageModificationTime");
--        node.setAttribute("year", Integer.toString(tIME_year));
--        node.setAttribute("month", Integer.toString(tIME_month));
--        node.setAttribute("day", Integer.toString(tIME_day));
--        node.setAttribute("hour", Integer.toString(tIME_hour));
--        node.setAttribute("minute", Integer.toString(tIME_minute));
--        node.setAttribute("second", Integer.toString(tIME_second));
--        document_node.appendChild(node);
--
--        return document_node;
--    }
--
--    public IIOMetadataNode getStandardTextNode() {
--        int numEntries = tEXt_keyword.size() +
--            iTXt_keyword.size() + zTXt_keyword.size();
--        if (numEntries == 0) {
--            return null;
--        }
--
--        IIOMetadataNode text_node = new IIOMetadataNode("Text");
--        IIOMetadataNode node = null; // scratch node
--
--        for (int i = 0; i < tEXt_keyword.size(); i++) {
--            node = new IIOMetadataNode("TextEntry");
--            node.setAttribute("keyword", (String)tEXt_keyword.get(i));
--            node.setAttribute("value", (String)tEXt_text.get(i));
--            node.setAttribute("encoding", "ISO-8859-1");
--            node.setAttribute("compression", "none");
--            
--            text_node.appendChild(node);
--        }
--
--        for (int i = 0; i < iTXt_keyword.size(); i++) {
--            node = new IIOMetadataNode("TextEntry");
--            node.setAttribute("keyword", (String)iTXt_keyword.get(i));
--            node.setAttribute("value", (String)iTXt_text.get(i));
--            node.setAttribute("language",
--                              (String)iTXt_languageTag.get(i));
--            if (((Integer)iTXt_compressionFlag.get(i)).intValue() == 1) {
--                node.setAttribute("compression", "deflate");
--            } else {
--                node.setAttribute("compression", "none");
--            }
--            
--            text_node.appendChild(node);
--        }
--
--        for (int i = 0; i < zTXt_keyword.size(); i++) {
--            node = new IIOMetadataNode("TextEntry");
--            node.setAttribute("keyword", (String)zTXt_keyword.get(i));
--            node.setAttribute("value", (String)zTXt_text.get(i));
--            node.setAttribute("compression", "deflate");
--            
--            text_node.appendChild(node);
--        }
--
--        return text_node;
--    }
--
--    public IIOMetadataNode getStandardTransparencyNode() {
--        IIOMetadataNode transparency_node =
--            new IIOMetadataNode("Transparency");
--        IIOMetadataNode node = null; // scratch node
--
--        node = new IIOMetadataNode("Alpha");
--        boolean hasAlpha = 
--            (IHDR_colorType == PNG_COLOR_RGB_ALPHA) ||
--            (IHDR_colorType == PNG_COLOR_GRAY_ALPHA) ||
--            (IHDR_colorType == PNG_COLOR_PALETTE &&
--             tRNS_present &&
--             (tRNS_colorType == IHDR_colorType) &&
--             (tRNS_alpha != null));
--        node.setAttribute("value", hasAlpha ? "nonpremultiplied" : "none"); 
--        transparency_node.appendChild(node);
--
--        if (tRNS_present) {
--            if(tRNS_colorType == PNG_COLOR_RGB ||
--               tRNS_colorType == PNG_COLOR_GRAY) {
--                node = new IIOMetadataNode("TransparentColor");
--                if (tRNS_colorType == PNG_COLOR_RGB) {
--                    node.setAttribute("value",
--                                      Integer.toString(tRNS_red) + " " +
--                                      Integer.toString(tRNS_green) + " " +
--                                      Integer.toString(tRNS_blue));
--                } else if (tRNS_colorType == PNG_COLOR_GRAY) {
--                    node.setAttribute("value", Integer.toString(tRNS_gray));
--                }
--                transparency_node.appendChild(node);
--            }
--        }
--
--        return transparency_node;
--    }
--
--    // Shorthand for throwing an IIOInvalidTreeException
--    private void fatal(Node node, String reason)
--        throws IIOInvalidTreeException {
--        throw new IIOInvalidTreeException(reason, node);
--    }
--
--    // Get an integer-valued attribute
--    private int getIntAttribute(Node node, String name,
--                                int defaultValue, boolean required)
--        throws IIOInvalidTreeException {
--        String value = getAttribute(node, name, null, required);
--        if (value == null) {
--            return defaultValue;
--        }
--        return Integer.parseInt(value);
--    }
--
--    // Get a float-valued attribute
--    private float getFloatAttribute(Node node, String name,
--                                    float defaultValue, boolean required)
--        throws IIOInvalidTreeException {
--        String value = getAttribute(node, name, null, required);
--        if (value == null) {
--            return defaultValue;
--        }
--        return Float.parseFloat(value);
--    }
--
--    // Get a required integer-valued attribute
--    private int getIntAttribute(Node node, String name)
--        throws IIOInvalidTreeException {
--        return getIntAttribute(node, name, -1, true);
--    }
--
--    // Get a required float-valued attribute
--    private float getFloatAttribute(Node node, String name)
--        throws IIOInvalidTreeException {
--        return getFloatAttribute(node, name, -1.0F, true);
--    }
--
--    // Get a boolean-valued attribute
--    private boolean getBooleanAttribute(Node node, String name,
--                                        boolean defaultValue, 
--                                        boolean required)
--        throws IIOInvalidTreeException {
--        Node attr = node.getAttributes().getNamedItem(name);
--        if (attr == null) {
--            if (!required) {
--                return defaultValue;
--            } else {
--                fatal(node, "Required attribute " + name + " not present!");
--            }
--        }
--
--        String value = attr.getNodeValue();
--
--        if (value.equalsIgnoreCase("true")) {
--            return true;
--        } else if (value.equalsIgnoreCase("false")) {
--            return false;
--        } else {
--            fatal(node, "Attribute " + name + " must be 'true' or 'false'!");
--            return false;
--        }
--    }
--
--    // Get a required boolean-valued attribute
--    private boolean getBooleanAttribute(Node node, String name)
--        throws IIOInvalidTreeException {
--        return getBooleanAttribute(node, name, false, true);
--    }
--
--    // Get an enumerated attribute as an index into a String array
--    private int getEnumeratedAttribute(Node node,
--                                       String name, String[] legalNames,
--                                       int defaultValue, boolean required)
--        throws IIOInvalidTreeException {
--        Node attr = node.getAttributes().getNamedItem(name);
--        if (attr == null) {
--            if (!required) {
--                return defaultValue;
--            } else {
--                fatal(node, "Required attribute " + name + " not present!");
--            }
--        }
--
--        String value = attr.getNodeValue();
--
--        for (int i = 0; i < legalNames.length; i++) {
--            if (value.equals(legalNames[i])) {
--                return i;
--            }
--        }
--
--        fatal(node, "Illegal value for attribute " + name + "!");
--        return -1;
--    }
--
--    // Get a required enumerated attribute as an index into a String array
--    private int getEnumeratedAttribute(Node node,
--                                       String name, String[] legalNames)
--        throws IIOInvalidTreeException {
--        return getEnumeratedAttribute(node, name, legalNames, -1, true);
--    }
--
--    // Get a String-valued attribute
--    private String getAttribute(Node node, String name,
--                                String defaultValue, boolean required)
--        throws IIOInvalidTreeException {
--        Node attr = node.getAttributes().getNamedItem(name);
--        if (attr == null) {
--            if (!required) {
--                return defaultValue;
--            } else {
--                fatal(node, "Required attribute " + name + " not present!");
--            }
--        }
--        return attr.getNodeValue();
--    }
--
--    // Get a required String-valued attribute
--    private String getAttribute(Node node, String name)
--        throws IIOInvalidTreeException {
--            return getAttribute(node, name, null, true);
--    }
--
--    public void mergeTree(String formatName, Node root)
--        throws IIOInvalidTreeException {
--        if (formatName.equals(nativeMetadataFormatName)) {
--            if (root == null) {
--                throw new IllegalArgumentException("root == null!");
--            }
--            mergeNativeTree(root);
--        } else if (formatName.equals
--                   (IIOMetadataFormatImpl.standardMetadataFormatName)) {
--            if (root == null) {
--                throw new IllegalArgumentException("root == null!");
--            }
--            mergeStandardTree(root);
--        } else {
--            throw new IllegalArgumentException("Not a recognized format!");
--        }
--    }
--
--    private void mergeNativeTree(Node root)
--        throws IIOInvalidTreeException {
--        Node node = root;
--        if (!node.getNodeName().equals(nativeMetadataFormatName)) {
--            fatal(node, "Root must be " + nativeMetadataFormatName);
--        }
--        
--        node = node.getFirstChild();
--        while (node != null) {
--            String name = node.getNodeName();
--            
--            if (name.equals("IHDR")) {
--                IHDR_width = getIntAttribute(node, "width");
--                IHDR_height = getIntAttribute(node, "height");
--                IHDR_bitDepth = getEnumeratedAttribute(node, "bitDepth",
--                                                       IHDR_bitDepths);
--                IHDR_colorType = getEnumeratedAttribute(node, "colorType",
--                                                        IHDR_colorTypeNames);
--                IHDR_compressionMethod =
--                    getEnumeratedAttribute(node, "compressionMethod",
--                                           IHDR_compressionMethodNames);
--                IHDR_filterMethod =
--                    getEnumeratedAttribute(node,
--                                           "filterMethod",
--                                           IHDR_filterMethodNames);
--                IHDR_interlaceMethod =
--                    getEnumeratedAttribute(node, "interlaceMethod",
--                                           IHDR_interlaceMethodNames);
--                IHDR_present = true;
--            } else if (name.equals("PLTE")) {
--                byte[] red = new byte[256];
--                byte[] green  = new byte[256];
--                byte[] blue = new byte[256];
--                int maxindex = -1;
--                
--                Node PLTE_entry = node.getFirstChild();
--                if (PLTE_entry == null) {
--                    fatal(node, "Palette has no entries!");
--                }
--
--                while (PLTE_entry != null) {
--                    if (!PLTE_entry.getNodeName().equals("PLTEEntry")) {
--                        fatal(node,
--                              "Only a PLTEEntry may be a child of a PLTE!");
--                    }
--                    
--                    int index = getIntAttribute(PLTE_entry, "index");
--                    if (index < 0 || index > 255) {
--                        fatal(node,
--                              "Bad value for PLTEEntry attribute index!");
--                    }
--                    if (index > maxindex) {
--                        maxindex = index;
--                    }
--                    red[index] =
--                        (byte)getIntAttribute(PLTE_entry, "red");
--                    green[index] =
--                        (byte)getIntAttribute(PLTE_entry, "green");
--                    blue[index] =
--                        (byte)getIntAttribute(PLTE_entry, "blue");
--                    
--                    PLTE_entry = PLTE_entry.getNextSibling();
--                }
--                
--                int numEntries = maxindex + 1;
--                PLTE_red = new byte[numEntries];
--                PLTE_green = new byte[numEntries];
--                PLTE_blue = new byte[numEntries];
--                System.arraycopy(red, 0, PLTE_red, 0, numEntries);
--                System.arraycopy(green, 0, PLTE_green, 0, numEntries);
--                System.arraycopy(blue, 0, PLTE_blue, 0, numEntries);
--                PLTE_present = true;
--            } else if (name.equals("bKGD")) {
--                bKGD_present = false; // Guard against partial overwrite
--                Node bKGD_node = node.getFirstChild();
--                if (bKGD_node == null) {
--                    fatal(node, "bKGD node has no children!");
--                }
--                String bKGD_name = bKGD_node.getNodeName();
--                if (bKGD_name.equals("bKGD_Palette")) {
--                    bKGD_index = getIntAttribute(bKGD_node, "index");
--                    bKGD_colorType = PNG_COLOR_PALETTE;
--                } else if (bKGD_name.equals("bKGD_Grayscale")) {
--                    bKGD_gray = getIntAttribute(bKGD_node, "gray");
--                    bKGD_colorType = PNG_COLOR_GRAY;
--                } else if (bKGD_name.equals("bKGD_RGB")) {
--                    bKGD_red = getIntAttribute(bKGD_node, "red");
--                    bKGD_green = getIntAttribute(bKGD_node, "green");
--                    bKGD_blue = getIntAttribute(bKGD_node, "blue");
--                    bKGD_colorType = PNG_COLOR_RGB;
--                } else {
--                    fatal(node, "Bad child of a bKGD node!");
--                }
--                if (bKGD_node.getNextSibling() != null) {
--                    fatal(node, "bKGD node has more than one child!");
--                }
--
--                bKGD_present = true;
--            } else if (name.equals("cHRM")) {
--                cHRM_whitePointX = getIntAttribute(node, "whitePointX");
--                cHRM_whitePointY = getIntAttribute(node, "whitePointY");
--                cHRM_redX = getIntAttribute(node, "redX");
--                cHRM_redY = getIntAttribute(node, "redY");
--                cHRM_greenX = getIntAttribute(node, "greenX");
--                cHRM_greenY = getIntAttribute(node, "greenY");
--                cHRM_blueX = getIntAttribute(node, "blueX");
--                cHRM_blueY = getIntAttribute(node, "blueY");
--                
--                cHRM_present = true;
--            } else if (name.equals("gAMA")) {
--                gAMA_gamma = getIntAttribute(node, "value");
--                gAMA_present = true;
--            } else if (name.equals("hIST")) {
--                char[] hist = new char[256];
--                int maxindex = -1;
--                
--                Node hIST_entry = node.getFirstChild();
--                if (hIST_entry == null) {
--                    fatal(node, "hIST node has no children!");
--                }
--
--                while (hIST_entry != null) {
--                    if (!hIST_entry.getNodeName().equals("hISTEntry")) {
--                        fatal(node,
--                              "Only a hISTEntry may be a child of a hIST!");
--                    }
--                    
--                    int index = getIntAttribute(hIST_entry, "index");
--                    if (index < 0 || index > 255) {
--                        fatal(node,
--                              "Bad value for histEntry attribute index!");
--                    }
--                    if (index > maxindex) {
--                        maxindex = index;
--                    }
--                    hist[index] =
--                        (char)getIntAttribute(hIST_entry, "value");
--                    
--                    hIST_entry = hIST_entry.getNextSibling();
--                }
--                
--                int numEntries = maxindex + 1;
--                hIST_histogram = new char[numEntries];
--                System.arraycopy(hist, 0, hIST_histogram, 0, numEntries);
--                
--                hIST_present = true;
--            } else if (name.equals("iCCP")) {
--                iCCP_profileName =
--                    toPrintableLatin1(getAttribute(node, "profileName"));
--                iCCP_compressionMethod =
--                    getEnumeratedAttribute(node, "compressionMethod",
--                                           iCCP_compressionMethodNames);
--                Object compressedProfile =
--                    ((IIOMetadataNode)node).getUserObject();
--                if (compressedProfile == null) {
--                    fatal(node, "No ICCP profile present in user object!");
--                }
--                if (!(compressedProfile instanceof byte[])) {
--                    fatal(node, "User object not a byte array!");
--                }
--                
--                iCCP_compressedProfile =
--                    (byte[])((byte[])compressedProfile).clone();
--                
--                iCCP_present = true;
--            } else if (name.equals("iTXt")) {
--                Node iTXt_node = node.getFirstChild();
--                while (iTXt_node != null) {
--                    if (!iTXt_node.getNodeName().equals("iTXtEntry")) {
--                        fatal(node,
--                              "Only an iTXtEntry may be a child of an iTXt!");
--                    }
--                    
--                    String keyword =
--                        toPrintableLatin1(getAttribute(iTXt_node, "keyword"));
--                    iTXt_keyword.add(keyword);
--                    
--                    boolean compressionFlag =
--                        getBooleanAttribute(iTXt_node, "compressionFlag");
--                    iTXt_compressionFlag.add(new Boolean(compressionFlag));
--                    
--                    String compressionMethod =
--                        getAttribute(iTXt_node, "compressionMethod");
--                    iTXt_compressionMethod.add(compressionMethod);
--                    
--                    String languageTag =
--                        getAttribute(iTXt_node, "languageTag");
--                    iTXt_languageTag.add(languageTag); 
--                    
--                    String translatedKeyword =
--                        getAttribute(iTXt_node, "translatedKeyword");
--                    iTXt_translatedKeyword.add(translatedKeyword);
--                    
--                    String text = getAttribute(iTXt_node, "text");
--                    iTXt_text.add(text);
--                    
--                    iTXt_node = iTXt_node.getNextSibling();
--                }
--            } else if (name.equals("pHYs")) {
--                pHYs_pixelsPerUnitXAxis =
--                    getIntAttribute(node, "pixelsPerUnitXAxis");
--                pHYs_pixelsPerUnitYAxis =
--                    getIntAttribute(node, "pixelsPerUnitYAxis");
--                pHYs_unitSpecifier =
--                    getEnumeratedAttribute(node, "unitSpecifier",
--                                           unitSpecifierNames);
--                
--                pHYs_present = true;
--            } else if (name.equals("sBIT")) {
--                sBIT_present = false; // Guard against partial overwrite
--                Node sBIT_node = node.getFirstChild();
--                if (sBIT_node == null) {
--                    fatal(node, "sBIT node has no children!");
--                }
--                String sBIT_name = sBIT_node.getNodeName();
--                if (sBIT_name.equals("sBIT_Grayscale")) {
--                    sBIT_grayBits = getIntAttribute(sBIT_node, "gray");
--                    sBIT_colorType = PNG_COLOR_GRAY;
--                } else if (sBIT_name.equals("sBIT_GrayAlpha")) {
--                    sBIT_grayBits = getIntAttribute(sBIT_node, "gray");
--                    sBIT_alphaBits = getIntAttribute(sBIT_node, "alpha");
--                    sBIT_colorType = PNG_COLOR_GRAY_ALPHA;
--                } else if (sBIT_name.equals("sBIT_RGB")) {
--                    sBIT_redBits = getIntAttribute(sBIT_node, "red");
--                    sBIT_greenBits = getIntAttribute(sBIT_node, "green");
--                    sBIT_blueBits = getIntAttribute(sBIT_node, "blue");
--                    sBIT_colorType = PNG_COLOR_RGB;
--                } else if (sBIT_name.equals("sBIT_RGBAlpha")) {
--                    sBIT_redBits = getIntAttribute(sBIT_node, "red");
--                    sBIT_greenBits = getIntAttribute(sBIT_node, "green");
--                    sBIT_blueBits = getIntAttribute(sBIT_node, "blue");
--                    sBIT_alphaBits = getIntAttribute(sBIT_node, "alpha");
--                    sBIT_colorType = PNG_COLOR_RGB_ALPHA;
--                } else if (sBIT_name.equals("sBIT_Palette")) {
--                    sBIT_redBits = getIntAttribute(sBIT_node, "red");
--                    sBIT_greenBits = getIntAttribute(sBIT_node, "green");
--                    sBIT_blueBits = getIntAttribute(sBIT_node, "blue");
--                    sBIT_colorType = PNG_COLOR_PALETTE;
--                } else {
--                    fatal(node, "Bad child of an sBIT node!");
--                }
--                if (sBIT_node.getNextSibling() != null) {
--                    fatal(node, "sBIT node has more than one child!");
--                }
--
--                sBIT_present = true;
--            } else if (name.equals("sPLT")) {
--                sPLT_paletteName =
--                    toPrintableLatin1(getAttribute(node, "name"));
--                sPLT_sampleDepth = getIntAttribute(node, "sampleDepth");
--                
--                int[] red = new int[256];
--                int[] green  = new int[256];
--                int[] blue = new int[256];
--                int[] alpha = new int[256];
--                int[] frequency = new int[256];
--                int maxindex = -1;
--                
--                Node sPLT_entry = node.getFirstChild();
--                if (sPLT_entry == null) {
--                    fatal(node, "sPLT node has no children!");
--                }
--
--                while (sPLT_entry != null) {
--                    if (!sPLT_entry.getNodeName().equals("sPLTEntry")) {
--                        fatal(node,
--                              "Only an sPLTEntry may be a child of an sPLT!");
--                    }
--                    
--                    int index = getIntAttribute(sPLT_entry, "index");
--                    if (index < 0 || index > 255) {
--                        fatal(node,
--                              "Bad value for PLTEEntry attribute index!");
--                    }
--                    if (index > maxindex) {
--                        maxindex = index;
--                    }
--                    red[index] = getIntAttribute(sPLT_entry, "red");
--                    green[index] = getIntAttribute(sPLT_entry, "green");
--                    blue[index] = getIntAttribute(sPLT_entry, "blue");
--                    alpha[index] = getIntAttribute(sPLT_entry, "alpha");
--                    frequency[index] =
--                        getIntAttribute(sPLT_entry, "frequency");
--                    
--                    sPLT_entry = sPLT_entry.getNextSibling();
--                }
--                
--                int numEntries = maxindex + 1;
--                sPLT_red = new int[numEntries];
--                sPLT_green = new int[numEntries];
--                sPLT_blue = new int[numEntries];
--                sPLT_alpha = new int[numEntries];
--                sPLT_frequency = new int[numEntries];
--                System.arraycopy(red, 0, sPLT_red, 0, numEntries);
--                System.arraycopy(green, 0, sPLT_green, 0, numEntries);
--                System.arraycopy(blue, 0, sPLT_blue, 0, numEntries);
--                System.arraycopy(alpha, 0, sPLT_alpha, 0, numEntries);
--                System.arraycopy(frequency, 0,
--                                 sPLT_frequency, 0, numEntries);
--                
--                sPLT_present = true;
--            } else if (name.equals("sRGB")) {
--                sRGB_renderingIntent =
--                    getEnumeratedAttribute(node, "renderingIntent",
--                                           renderingIntentNames);
--                
--                sRGB_present = true;
--            } else if (name.equals("tEXt")) {
--                Node tEXt_node = node.getFirstChild();
--                while (tEXt_node != null) {
--                    if (!tEXt_node.getNodeName().equals("tEXtEntry")) {
--                        fatal(node,
--                              "Only an tEXtEntry may be a child of an tEXt!");
--                    }
--                    
--                    String keyword =
--                        toPrintableLatin1(getAttribute(tEXt_node, "keyword"));
--                    tEXt_keyword.add(keyword);
--                    
--                    String text = getAttribute(tEXt_node, "value");
--                    tEXt_text.add(text);
--                    
--                    tEXt_node = tEXt_node.getNextSibling();
--                }
--            } else if (name.equals("tIME")) {
--                tIME_year = getIntAttribute(node, "year");
--                tIME_month = getIntAttribute(node, "month");
--                tIME_day = getIntAttribute(node, "day");
--                tIME_hour = getIntAttribute(node, "hour");
--                tIME_minute = getIntAttribute(node, "minute");
--                tIME_second = getIntAttribute(node, "second");
--                
--                tIME_present = true;
--            } else if (name.equals("tRNS")) {
--                tRNS_present = false; // Guard against partial overwrite
--                Node tRNS_node = node.getFirstChild();
--                if (tRNS_node == null) {
--                    fatal(node, "tRNS node has no children!");
--                }
--                String tRNS_name = tRNS_node.getNodeName();
--                if (tRNS_name.equals("tRNS_Palette")) {
--                    byte[] alpha = new byte[256];
--                    int maxindex = -1;
--                    
--                    Node tRNS_paletteEntry = tRNS_node.getFirstChild();
--                    if (tRNS_paletteEntry == null) {
--                        fatal(node, "tRNS_Palette node has no children!");
--                    }
--                    while (tRNS_paletteEntry != null) {
--                        if (!tRNS_paletteEntry.getNodeName().equals(
--                                                        "tRNS_PaletteEntry")) {
--                            fatal(node,
--                 "Only a tRNS_PaletteEntry may be a child of a tRNS_Palette!");
--                        }
--                        int index =
--                            getIntAttribute(tRNS_paletteEntry, "index");
--                        if (index < 0 || index > 255) {
--                            fatal(node,
--                           "Bad value for tRNS_PaletteEntry attribute index!");
--                        }
--                        if (index > maxindex) {
--                            maxindex = index;
--                        }
--                        alpha[index] =
--                            (byte)getIntAttribute(tRNS_paletteEntry,
--                                                  "alpha");
--                        
--                        tRNS_paletteEntry =
--                            tRNS_paletteEntry.getNextSibling();
--                    }
--                    
--                    int numEntries = maxindex + 1;
--                    tRNS_alpha = new byte[numEntries];
--                    tRNS_colorType = PNG_COLOR_PALETTE;
--                    System.arraycopy(alpha, 0, tRNS_alpha, 0, numEntries);
--                } else if (tRNS_name.equals("tRNS_Grayscale")) {
--                    tRNS_gray = getIntAttribute(tRNS_node, "gray");
--                    tRNS_colorType = PNG_COLOR_GRAY;
--                } else if (tRNS_name.equals("tRNS_RGB")) {
--                    tRNS_red = getIntAttribute(tRNS_node, "red");
--                    tRNS_green = getIntAttribute(tRNS_node, "green");
--                    tRNS_blue = getIntAttribute(tRNS_node, "blue");
--                    tRNS_colorType = PNG_COLOR_RGB;
--                } else {
--                    fatal(node, "Bad child of a tRNS node!");
--                }
--                if (tRNS_node.getNextSibling() != null) {
--                    fatal(node, "tRNS node has more than one child!");
--                }
--                
--                tRNS_present = true;
--            } else if (name.equals("zTXt")) {
--                Node zTXt_node = node.getFirstChild();
--                while (zTXt_node != null) {
--                    if (!zTXt_node.getNodeName().equals("zTXtEntry")) {
--                        fatal(node,
--                              "Only an zTXtEntry may be a child of an zTXt!");
--                    }
--                    
--                    String keyword =
--                        toPrintableLatin1(getAttribute(zTXt_node, "keyword"));
--                    zTXt_keyword.add(keyword);
--                    
--                    int compressionMethod =
--                        getEnumeratedAttribute(zTXt_node, "compressionMethod",
--                                               zTXt_compressionMethodNames);
--                    zTXt_compressionMethod.add(new Integer(compressionMethod));
--                    
--                    String text = getAttribute(zTXt_node, "text");
--                    zTXt_text.add(text);
--                    
--                    zTXt_node = zTXt_node.getNextSibling();
--                }
--            } else if (name.equals("UnknownChunks")) {
--                Node unknown_node = node.getFirstChild();
--                while (unknown_node != null) {
--                    if (!unknown_node.getNodeName().equals("UnknownChunk")) {
--                        fatal(node,
--                   "Only an UnknownChunk may be a child of an UnknownChunks!");
--                    }
--                    String chunkType = getAttribute(unknown_node, "type");
--                    Object chunkData =
--                        ((IIOMetadataNode)unknown_node).getUserObject();
--                    
--                    if (chunkType.length() != 4) {
--                        fatal(unknown_node,
--                              "Chunk type must be 4 characters!");
--                    }
--                    if (chunkData == null) {
--                        fatal(unknown_node,
--                              "No chunk data present in user object!");
--                    }
--                    if (!(chunkData instanceof byte[])) {
--                        fatal(unknown_node,
--                              "User object not a byte array!");
--                    }
--                    unknownChunkType.add(chunkType);
--                    unknownChunkData.add(((byte[])chunkData).clone());
--                    
--                    unknown_node = unknown_node.getNextSibling();
--                }
--            } else {
--                fatal(node, "Unknown child of root node!");
--            }
--            
--            node = node.getNextSibling();
--        }
--    }
--
--    private boolean isISOLatin(String s) {
--        int len = s.length();
--        for (int i = 0; i < len; i++) {
--            if (s.charAt(i) > 255) {
--                return false;
--            }
--        }
--        return true;
--    }
--
--    private void mergeStandardTree(Node root)
--        throws IIOInvalidTreeException {
--        Node node = root;
--        if (!node.getNodeName()
--            .equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
--            fatal(node, "Root must be " +
--                  IIOMetadataFormatImpl.standardMetadataFormatName);
--        }
--        
--        node = node.getFirstChild();
--        while(node != null) {
--            String name = node.getNodeName();
--
--            if (name.equals("Chroma")) {
--                Node child = node.getFirstChild();
--                while (child != null) {
--                    String childName = child.getNodeName();
--                    if (childName.equals("Gamma")) {
--                        float gamma = getFloatAttribute(child, "value");
--                        gAMA_present = true;
--                        gAMA_gamma = (int)(gamma*100000 + 0.5);
--                    } else if (childName.equals("Palette")) {
--                        byte[] red = new byte[256];
--                        byte[] green = new byte[256];
--                        byte[] blue = new byte[256];
--                        int maxindex = -1;
--                
--                        Node entry = child.getFirstChild();
--                        while (entry != null) {
--                            String entryName = entry.getNodeName();
--                            if(entryName.equals("PaletteEntry")) {
--                                int index = getIntAttribute(entry, "index");
--                                if (index >= 0 && index <= 255) {
--                                    red[index] =
--                                        (byte)getIntAttribute(entry, "red");
--                                    green[index] =
--                                        (byte)getIntAttribute(entry, "green");
--                                    blue[index] =
--                                        (byte)getIntAttribute(entry, "blue");
--                                    if (index > maxindex) {
--                                        maxindex = index;
--                                    }
--                                }
--                            }
--                            entry = entry.getNextSibling();
--                        }
--                
--                        int numEntries = maxindex + 1;
--                        PLTE_red = new byte[numEntries];
--                        PLTE_green = new byte[numEntries];
--                        PLTE_blue = new byte[numEntries];
--                        System.arraycopy(red, 0, PLTE_red, 0, numEntries);
--                        System.arraycopy(green, 0, PLTE_green, 0, numEntries);
--                        System.arraycopy(blue, 0, PLTE_blue, 0, numEntries);
--                        PLTE_present = true;
--                    } else if (childName.equals("BackgroundIndex")) {
--                        bKGD_present = true;
--                        bKGD_colorType = PNG_COLOR_PALETTE;
--                        bKGD_index = getIntAttribute(child, "value");
--                    } else if (childName.equals("BackgroundColor")) {
--                        int red = getIntAttribute(child, "red");
--                        int green = getIntAttribute(child, "green");
--                        int blue = getIntAttribute(child, "blue");
--                        if (red == green && red == blue) {
--                            bKGD_colorType = PNG_COLOR_GRAY;
--                            bKGD_gray = red;
--                        } else {
--                            bKGD_colorType = PNG_COLOR_RGB;
--                            bKGD_red = red;
--                            bKGD_green = green;
--                            bKGD_blue = blue;
--                        }
--                        bKGD_present = true;
--                    }
--                    // } else if (childName.equals("ColorSpaceType")) {
--                    // } else if (childName.equals("NumChannels")) {
--
--                    child = child.getNextSibling();
--                }
--            } else if (name.equals("Compression")) {
--                Node child = node.getFirstChild();
--                while (child != null) {
--                    String childName = child.getNodeName();
--                    if (childName.equals("NumProgressiveScans")) {
--                        // Use Adam7 if NumProgressiveScans > 1
--                        int scans = getIntAttribute(child, "value");
--                        IHDR_interlaceMethod = (scans > 1) ? 1 : 0;
--                        //                  } else if (childName.equals("CompressionTypeName")) {
--                        //                  } else if (childName.equals("Lossless")) {
--                        //                  } else if (childName.equals("BitRate")) {
--                    }
--                    child = child.getNextSibling();
--                }
--            } else if (name.equals("Data")) {
--                Node child = node.getFirstChild();
--                while (child != null) {
--                    String childName = child.getNodeName();
--                    if (childName.equals("BitsPerSample")) {
--                        String s = getAttribute(child, "value");
--                        StringTokenizer t = new StringTokenizer(s);
--                        int maxBits = -1;
--                        while (t.hasMoreTokens()) {
--                            int bits = Integer.parseInt(t.nextToken());
--                            if (bits > maxBits) {
--                                maxBits = bits;
--                            }
--                        }
--                        if (maxBits < 1) {
--                            maxBits = 1;
--                        } else if (maxBits == 3) {
--                            maxBits = 4;
--                        } else if (maxBits > 4 && maxBits < 8) {
--                            maxBits = 8;
--                        } else if (maxBits > 8) {
--                            maxBits = 16;
--                        }
--                        IHDR_bitDepth = maxBits;
--                    } else if (childName.equals("SignificantBitsPerSample")) {
--                        String s = getAttribute(child, "value");
--                        StringTokenizer t = new StringTokenizer(s);
--                        int numTokens = t.countTokens();
--                        if (numTokens == 1) {
--                            sBIT_colorType = PNG_COLOR_GRAY;
--                            sBIT_grayBits = Integer.parseInt(t.nextToken());
--                        } else if (numTokens == 2) {
--                            sBIT_colorType =
--                                PNG_COLOR_GRAY_ALPHA;
--                            sBIT_grayBits = Integer.parseInt(t.nextToken());
--                            sBIT_alphaBits = Integer.parseInt(t.nextToken());
--                        } else if (numTokens == 3) {
--                            sBIT_colorType = PNG_COLOR_RGB;
--                            sBIT_redBits = Integer.parseInt(t.nextToken());
--                            sBIT_greenBits = Integer.parseInt(t.nextToken());
--                            sBIT_blueBits = Integer.parseInt(t.nextToken());
--                        } else if (numTokens == 4) {
--                            sBIT_colorType =
--                                PNG_COLOR_RGB_ALPHA;
--                            sBIT_redBits = Integer.parseInt(t.nextToken());
--                            sBIT_greenBits = Integer.parseInt(t.nextToken());
--                            sBIT_blueBits = Integer.parseInt(t.nextToken());
--                            sBIT_alphaBits = Integer.parseInt(t.nextToken());
--                        }
--                        if (numTokens >= 1 && numTokens <= 4) {
--                            sBIT_present = true;
--                        }
--                        // } else if (childName.equals("PlanarConfiguration")) {
--                        // } else if (childName.equals("SampleFormat")) {
--                        // } else if (childName.equals("SampleMSB")) {
--                    }
--                    child = child.getNextSibling();
--                }
--            } else if (name.equals("Dimension")) {
--                boolean gotWidth = false;
--                boolean gotHeight = false;
--                boolean gotAspectRatio = false;
--
--                float width = -1.0F;
--                float height = -1.0F;
--                float aspectRatio = -1.0F;
--                
--                Node child = node.getFirstChild();
--                while (child != null) {
--                    String childName = child.getNodeName();
--                    if (childName.equals("PixelAspectRatio")) {
--                        aspectRatio = getFloatAttribute(child, "value");
--                        gotAspectRatio = true;
--                    } else if (childName.equals("HorizontalPixelSize")) {
--                        width = getFloatAttribute(child, "value");
--                        gotWidth = true;
--                    } else if (childName.equals("VerticalPixelSize")) {
--                        height = getFloatAttribute(child, "value");
--                        gotHeight = true;
--                        // } else if (childName.equals("ImageOrientation")) {
--                        // } else if
--                        //     (childName.equals("HorizontalPhysicalPixelSpacing")) {
--                        // } else if
--                        //     (childName.equals("VerticalPhysicalPixelSpacing")) {
--                        // } else if (childName.equals("HorizontalPosition")) {
--                        // } else if (childName.equals("VerticalPosition")) {
--                        // } else if (childName.equals("HorizontalPixelOffset")) {
--                        // } else if (childName.equals("VerticalPixelOffset")) {
--                    }
--                    child = child.getNextSibling();
--                }
--
--                if (gotWidth && gotHeight) {
--                    pHYs_present = true;
--                    pHYs_unitSpecifier = 1;
--                    pHYs_pixelsPerUnitXAxis = (int)(1000.0F/width + 0.5F);
--                    pHYs_pixelsPerUnitYAxis = (int)(1000.0F/height + 0.5F);
--                } else if (gotAspectRatio) {
--                    pHYs_present = true;
--                    pHYs_unitSpecifier = 0;
--
--                    // Find a reasonable rational approximation
--                    int denom = 1;
--                    for (; denom < 100; denom++) {
--                        int num = (int)(aspectRatio*denom);
--                        if (Math.abs(num/denom - aspectRatio) < 0.001) {
--                            break;
--                        }
--                    }
--                    pHYs_pixelsPerUnitXAxis = (int)(aspectRatio*denom);
--                    pHYs_pixelsPerUnitYAxis = denom;
--                }
--            } else if (name.equals("Document")) {
--                Node child = node.getFirstChild();
--                while (child != null) {
--                    String childName = child.getNodeName();
--                    if (childName.equals("ImageModificationTime")) {
--                        tIME_present = true;
--                        tIME_year = getIntAttribute(child, "year");
--                        tIME_month = getIntAttribute(child, "month");
--                        tIME_day = getIntAttribute(child, "day");
--                        tIME_hour =
--                            getIntAttribute(child, "hour", 0, false);
--                        tIME_minute =
--                            getIntAttribute(child, "minute", 0, false);
--                        tIME_second =
--                            getIntAttribute(child, "second", 0, false);
--                        // } else if (childName.equals("SubimageInterpretation")) {
--                        // } else if (childName.equals("ImageCreationTime")) {
--                    }
--                    child = child.getNextSibling();
--                }
--            } else if (name.equals("Text")) {
--                Node child = node.getFirstChild();
--                while (child != null) {
--                    String childName = child.getNodeName();
--                    if (childName.equals("TextEntry")) {
--                        String keyword = getAttribute(child, "keyword",
--                                                      "text", false);
--                        String value = getAttribute(child, "value");
--                        String encoding = getAttribute(child, "encoding",
--                                                       "unknown", false);
--                        String language = getAttribute(child, "language",
--                                                       "unknown", false);
--                        String compression =
--                            getAttribute(child, "compression",
--                                         "other", false);
--
--                        if (isISOLatin(value)) {
--                            if (compression.equals("zip")) {
--                                // Use a zTXt node
--                                zTXt_keyword.add(toPrintableLatin1(keyword));
--                                zTXt_text.add(value);
--                                zTXt_compressionMethod.add(new Integer(0));
--                            } else {
--                                // Use a tEXt node
--                                tEXt_keyword.add(toPrintableLatin1(keyword));
--                                tEXt_text.add(value);
--                            }
--                        } else {
--                            int flag = compression.equals("zip") ?
--                                1 : 0;
--
--                            // Use an iTXt node
--                            iTXt_keyword.add(toPrintableLatin1(keyword));
--                            iTXt_compressionFlag.add(new Integer(flag));
--                            iTXt_compressionMethod.add(new Integer(0));
--                            iTXt_languageTag.add(language);
--                            iTXt_translatedKeyword.add(keyword); // fake it
--                            iTXt_text.add(value);
--                        }
--                    }
--                    child = child.getNextSibling();
--                }
--                //          } else if (name.equals("Transparency")) {
--                //              Node child = node.getFirstChild();
--                //              while (child != null) {
--                //                  String childName = child.getNodeName();
--                //                  if (childName.equals("Alpha")) {
--                //                  } else if (childName.equals("TransparentIndex")) {
--                //                  } else if (childName.equals("TransparentColor")) {
--                //                  } else if (childName.equals("TileTransparencies")) {
--                //                  } else if (childName.equals("TileOpacities")) {
--                //                  }
--                //                  child = child.getNextSibling();
--                //              }
--                //          } else {
--                //              // fatal(node, "Unknown child of root node!");
--            }
--            
--            node = node.getNextSibling();
--        }
--    }
--
--    // Reset all instance variables to their initial state
--    public void reset() {
--        IHDR_present = false;
--        PLTE_present = false;
--        bKGD_present = false;
--        cHRM_present = false;
--        gAMA_present = false;
--        hIST_present = false;
--        iCCP_present = false;
--        iTXt_keyword = new ArrayList();
--        iTXt_compressionFlag = new ArrayList();
--        iTXt_compressionMethod = new ArrayList();
--        iTXt_languageTag = new ArrayList();
--        iTXt_translatedKeyword = new ArrayList();
--        iTXt_text = new ArrayList();
--        pHYs_present = false;
--        sBIT_present = false;
--        sPLT_present = false;
--        sRGB_present = false;
--        tEXt_keyword = new ArrayList();
--        tEXt_text = new ArrayList();
--        tIME_present = false;
--        tRNS_present = false;
--        zTXt_keyword = new ArrayList();
--        zTXt_compressionMethod = new ArrayList();
--        zTXt_text = new ArrayList();
--        unknownChunkType = new ArrayList();
--        unknownChunkData = new ArrayList();
--    }
--
--    // BEGIN metadata reading section.
--
--    private boolean gotHeader = false;
--    private boolean gotMetadata = false;
--
--    private Decoder decoder = null;
--    private CLibPNGImageReader reader = null;
--
--    private static int chunkType(String typeString) {
--        char c0 = typeString.charAt(0);
--        char c1 = typeString.charAt(1);
--        char c2 = typeString.charAt(2);
--        char c3 = typeString.charAt(3);
--
--        int type = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
--        return type;
--    }
--
--    private String readNullTerminatedString(ImageInputStream stream)
--        throws IOException {
--        StringBuffer b = new StringBuffer();
--        int c;
--
--        while ((c = stream.read()) != 0) {
--            b.append((char)c);
--        }
--        return b.toString();
--    }
--
--    private void readHeader() throws IIOException {
--        if (gotHeader) {
--            return;
--        }
--
--        try {
--            mediaLibImage mlibImage = decoder.getImage();
--            int width = mlibImage.getWidth();
--            int height = mlibImage.getHeight();
--            int bitDepth = decoder.getBitDepth();
--            int colorType;
--            switch(mlibImage.getChannels()) {
--            case 1:
--                colorType = decoder.getPalette() == null?
--                    PNG_COLOR_GRAY : PNG_COLOR_PALETTE;
--                break;
--            case 2:
--                colorType = PNG_COLOR_GRAY_ALPHA;
--                break;
--            case 3:
--                colorType = PNG_COLOR_RGB;
--                break;
--            case 4:
--                colorType = PNG_COLOR_RGB_ALPHA;
--                break;
--            default:
--                throw new IIOException("Unsupported image type.");
--            }
--
--            // Compression method 0 (deflate/inflate) is only supported type.
--            int compressionMethod = 0;
--
--            // Filter method 0 (adaptive filtering) is only supported type.
--            int filterMethod = 0;
--
--            int interlaceMethod = decoder.getInterlaceMethod();
--            
--            if (width == 0) {
--                throw new IIOException("Image width == 0!");
--            }
--            if (height == 0) {
--                throw new IIOException("Image height == 0!");
--            }
--            if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 &&
--                bitDepth != 8 && bitDepth != 16) {
--                throw new IIOException("Bit depth must be 1, 2, 4, 8, or 16!");
--            }
--            if (colorType != 0 && colorType != 2 && colorType != 3 &&
--                colorType != 4 && colorType != 6) {
--                throw new IIOException("Color type must be 0, 2, 3, 4, or 6!");
--            }
--            if (colorType == PNG_COLOR_PALETTE && bitDepth == 16) {
--                throw new IIOException("Bad color type/bit depth combination!");
--            }
--            if ((colorType == PNG_COLOR_RGB ||
--                 colorType == PNG_COLOR_RGB_ALPHA ||
--                 colorType == PNG_COLOR_GRAY_ALPHA) &&
--                (bitDepth != 8 && bitDepth != 16)) {
--                throw new IIOException("Bad color type/bit depth combination!");
--            }
--            if (compressionMethod != 0) {
--                throw new IIOException("Unknown compression method (not 0)!");
--            }
--            if (filterMethod != 0) {
--                throw new IIOException("Unknown filter method (not 0)!");
--            }
--            if (interlaceMethod != 0 && interlaceMethod != 1) {
--                throw new IIOException("Unknown interlace method (not 0 or 1)!");
--            }
--        
--            IHDR_present = true;
--            IHDR_width = width;
--            IHDR_height = height;
--            IHDR_bitDepth = bitDepth;
--            IHDR_colorType = colorType; 
--            IHDR_compressionMethod = compressionMethod;
--            IHDR_filterMethod = filterMethod;
--            IHDR_interlaceMethod = interlaceMethod;
--            gotHeader = true;
--        } catch (IOException e) {
--            throw new IIOException("I/O error reading PNG header!", e);
--        }
--    }
--
--    private void parse_PLTE_chunk() throws IOException {
--        if (PLTE_present) {
--            processWarningOccurred(
--"A PNG image may not contain more than one PLTE chunk.\n" +
--"The chunk will be ignored.");
--            return;
--        } else if (IHDR_colorType == PNG_COLOR_GRAY ||
--                   IHDR_colorType == PNG_COLOR_GRAY_ALPHA) {
--            processWarningOccurred(
--"A PNG gray or gray alpha image cannot have a PLTE chunk.\n" +
--"The chunk will be ignored.");
--            return;
--        }
--
--        byte[] palette = decoder.getPalette();
--
--        if(palette != null) {
--            int numEntries = palette.length/3;
--            if (IHDR_colorType == PNG_COLOR_PALETTE) {
--                int maxEntries = 1 << IHDR_bitDepth;
--                if (numEntries > maxEntries) {
--                    processWarningOccurred(
--                                           "PLTE chunk contains too many entries for bit depth, ignoring extras.");
--                    numEntries = maxEntries;
--                }
--            }
--
--            // Round array sizes up to 2^2^n
--            int paletteEntries;
--            if (numEntries > 16) {
--                paletteEntries = 256;
--            } else if (numEntries > 4) {
--                paletteEntries = 16;
--            } else if (numEntries > 2) {
--                paletteEntries = 4;
--            } else {
--                paletteEntries = 2;
--            }
--
--            PLTE_present = true;
--            PLTE_red = new byte[paletteEntries];
--            PLTE_green = new byte[paletteEntries];
--            PLTE_blue = new byte[paletteEntries];
--
--            int index = 0;
--            for (int i = 0; i < numEntries; i++) {
--                PLTE_red[i] = palette[index++];
--                PLTE_green[i] = palette[index++];
--                PLTE_blue[i] = palette[index++];
--            }
--        }
--    }
--
--    private void parse_bKGD_chunk() throws IOException {
--        int[] background = decoder.getBackground();
--        if(background != null) {
--            if (IHDR_colorType == PNG_COLOR_PALETTE) {
--                bKGD_colorType = PNG_COLOR_PALETTE;
--                bKGD_index = background[0];
--            } else if (IHDR_colorType == PNG_COLOR_GRAY ||
--                       IHDR_colorType == PNG_COLOR_GRAY_ALPHA) {
--                bKGD_colorType = PNG_COLOR_GRAY;
--                bKGD_gray = background[0];
--            } else { // RGB or RGB_ALPHA
--                bKGD_colorType = PNG_COLOR_RGB;
--                bKGD_red = background[0];
--                bKGD_green = background[1];
--                bKGD_blue = background[2];
--            }
--
--            bKGD_present = true;
--        }
--    }
--
--    private void parse_cHRM_chunk() throws IOException {
--        int[] chrm = decoder.getAllPrimaryChromaticities();
--        if(chrm != null) {
--            int i = 0;
--            cHRM_whitePointX = chrm[i++];
--            cHRM_whitePointY = chrm[i++];
--            cHRM_redX = chrm[i++];
--            cHRM_redY = chrm[i++];
--            cHRM_greenX = chrm[i++];
--            cHRM_greenY = chrm[i++];
--            cHRM_blueX = chrm[i++];
--            cHRM_blueY = chrm[i++];
--
--            cHRM_present = true;
--        }
--    }
--
--    private void parse_gAMA_chunk() throws IOException {
--        int gamma = decoder.getImageGamma();
--        if(gamma != decoder.PNG_gAMA_DEFAULT) {
--            gAMA_gamma = gamma;
--
--            gAMA_present = true;
--        }
--    }
--
--    private void parse_hIST_chunk() throws IOException, IIOException {
--        short[] histogram = decoder.getHistogram();
--        if(histogram != null) {
--            if (!PLTE_present) {
--                throw new IIOException("hIST chunk without prior PLTE chunk!");
--            }
--
--            int length = Math.min(PLTE_red.length, histogram.length);
--            hIST_histogram = new char[length];
--            for(int i = 0; i < length; i++) {
--                hIST_histogram[i] = (char)histogram[i];
--            }
--
--            hIST_present = true;
--        }
--    }
--
--    private void parse_iCCP_chunk() throws IOException {
--        String profileName = decoder.getEmbeddedICCProfileName();
--
--        if(profileName != null) {
--            iCCP_profileName = profileName;
--
--            byte[] uncompressedProfile = decoder.getEmbeddedICCProfile();
--
--            // Need to compress this profile to match metadata specification.
--            Deflater compressor = new Deflater(Deflater.BEST_COMPRESSION);
--            compressor.setInput(uncompressedProfile);
--            compressor.finish();
--
--            int off = 0;
--            int len = uncompressedProfile.length;
--            byte[] compressedProfile = new byte[uncompressedProfile.length];
--            do {
--                int count = compressor.deflate(compressedProfile, off, len);
--                off += count;
--                len -= count;
--            } while(!compressor.finished());
--
--            int compressedDataLength = off;
--
--            iCCP_compressedProfile = new byte[compressedDataLength];
--            System.arraycopy(compressedProfile, 0,
--                             iCCP_compressedProfile, 0, compressedDataLength);
--
--
--            iCCP_present = true;
--        }
--    }
--  
--    private void parse_pHYs_chunk() throws IOException {
--        int unitSpecifier =
--            decoder.getPhysicalPixelDimensions(decoder.PNG_PIXELS_UNIT_SPECIFIER);
--        if(unitSpecifier != decoder.PNG_pHYs_NOT_DEFINED) {
--            pHYs_pixelsPerUnitXAxis =
--                decoder.getPhysicalPixelDimensions(decoder.PNG_PIXELS_UNIT_X);
--            pHYs_pixelsPerUnitYAxis =
--                decoder.getPhysicalPixelDimensions(decoder.PNG_PIXELS_UNIT_Y);
--            pHYs_unitSpecifier = unitSpecifier;
--
--            pHYs_present = true;
--        }
--    }
--    
--    private void parse_sBIT_chunk() throws IOException {
--        byte[] sBits = decoder.getSignificantBits();
--        if(sBits != null) {
--            int i = 0;
--            int colorType = IHDR_colorType;
--            if (colorType == PNG_COLOR_GRAY ||
--                colorType == PNG_COLOR_GRAY_ALPHA) {
--                sBIT_grayBits = sBits[i++];
--            } else if (colorType == PNG_COLOR_RGB ||
--                       colorType == PNG_COLOR_PALETTE ||
--                       colorType == PNG_COLOR_RGB_ALPHA) {
--                sBIT_redBits = sBits[i++];
--                sBIT_greenBits = sBits[i++];
--                sBIT_blueBits = sBits[i++];
--            }
--
--            if (colorType == PNG_COLOR_GRAY_ALPHA ||
--                colorType == PNG_COLOR_RGB_ALPHA) {
--                sBIT_alphaBits = sBits[i++];
--            }
--
--            sBIT_colorType = colorType;
--            sBIT_present = true;
--        }
--    }
--
--    private void parse_sPLT_chunk()
--        throws IOException, IIOException {
--
--        PNGChunk[] sPLTChunks = decoder.getSuggestedPalette();
--
--        if(sPLTChunks != null &&
--           sPLTChunks.length > 0 && sPLTChunks[0] != null) {
--            PNGChunk sPLTChunk = sPLTChunks[0];
--            byte[] chunkData = sPLTChunk.getData();
--            int chunkLength = chunkData.length;
--
--            InputStream is = new ByteArrayInputStream(sPLTChunk.getData());
--            ImageInputStream stream = new MemoryCacheImageInputStream(is);
--
--            sPLT_paletteName = readNullTerminatedString(stream);
--            chunkLength -= sPLT_paletteName.length() + 1;
--
--            int sampleDepth = stream.readUnsignedByte();
--            sPLT_sampleDepth = sampleDepth;
--
--            int numEntries = chunkLength/(4*(sampleDepth/8) + 2);
--            sPLT_red = new int[numEntries];
--            sPLT_green = new int[numEntries];
--            sPLT_blue = new int[numEntries];
--            sPLT_alpha = new int[numEntries];
--            sPLT_frequency = new int[numEntries];
--
--            if (sampleDepth == 8) {
--                for (int i = 0; i < numEntries; i++) {
--                    sPLT_red[i] = stream.readUnsignedByte();
--                    sPLT_green[i] = stream.readUnsignedByte();
--                    sPLT_blue[i] = stream.readUnsignedByte();
--                    sPLT_alpha[i] = stream.readUnsignedByte();
--                    sPLT_frequency[i] = stream.readUnsignedShort();
--                }
--            } else if (sampleDepth == 16) {
--                for (int i = 0; i < numEntries; i++) {
--                    sPLT_red[i] = stream.readUnsignedShort();
--                    sPLT_green[i] = stream.readUnsignedShort();
--                    sPLT_blue[i] = stream.readUnsignedShort();
--                    sPLT_alpha[i] = stream.readUnsignedShort();
--                    sPLT_frequency[i] = stream.readUnsignedShort();
--                }
--            } else {
--                throw new IIOException("sPLT sample depth not 8 or 16!");
--            }
--
--            sPLT_present = true;
--        }
--    }
--
--    private void parse_sRGB_chunk() throws IOException {
--        int renderingIntent = decoder.getStandardRGB();
--        if(renderingIntent != decoder.PNG_sRGB_NOT_DEFINED) {
--            sRGB_renderingIntent = renderingIntent;
--            sRGB_present = true;
--        }
--    }
--
--    private void parse_tIME_chunk() throws IOException {
--        Calendar cal = decoder.getLastModificationTime();
--        if(cal != null) {
--            tIME_year = cal.get(Calendar.YEAR);
--            tIME_month = cal.get(Calendar.MONTH) + 1;
--            tIME_day = cal.get(Calendar.DAY_OF_MONTH);
--            tIME_hour = cal.get(Calendar.HOUR_OF_DAY);
--            tIME_minute = cal.get(Calendar.MINUTE);
--            tIME_second = cal.get(Calendar.SECOND);
--
--            tIME_present = true;
--        }
--    }
--
--    private void parse_tRNS_chunk() throws IOException {
--        int[] transparency = decoder.getTransparency();
--
--        if(transparency == null) {
--            return;
--        }
--
--        int colorType = IHDR_colorType;
--        if (colorType == PNG_COLOR_PALETTE) {
--            if (!PLTE_present) {
--                processWarningOccurred(
--"tRNS chunk without prior PLTE chunk, ignoring it.");
--                return;
--            }
--
--            // Alpha table may have fewer entries than RGB palette
--            int maxEntries = PLTE_red.length;
--            int numEntries = transparency.length;
--            if (numEntries > maxEntries) {
--                processWarningOccurred(
--"tRNS chunk has more entries than prior PLTE chunk, ignoring extras.");
--                numEntries = maxEntries;
--            }
--            tRNS_alpha = new byte[numEntries];
--            tRNS_colorType = PNG_COLOR_PALETTE;
--            for(int i = 0; i < numEntries; i++) {
--                tRNS_alpha[i] = (byte)transparency[i];
--            }
--        } else if (colorType == PNG_COLOR_GRAY) {
--            if (transparency.length != 1) {
--                processWarningOccurred(
--"tRNS chunk for gray image must have length 2, ignoring chunk.");
--                return;
--            }
--            tRNS_gray = transparency[0];
--            tRNS_colorType = PNG_COLOR_GRAY;
--        } else if (colorType == PNG_COLOR_RGB) {
--            if (transparency.length != 3) {
--                processWarningOccurred(
--"tRNS chunk for RGB image must have length 6, ignoring chunk.");
--                return;
--            }
--            tRNS_red = transparency[0];
--            tRNS_green = transparency[1];
--            tRNS_blue = transparency[2];
--            tRNS_colorType = PNG_COLOR_RGB;
--        } else {
--            processWarningOccurred(
--"Gray+Alpha and RGBA images may not have a tRNS chunk, ignoring it.");
--            return;
--        }
--
--        tRNS_present = true;
--    }
--
--    // Parse all iTXt, tEXt, and zTXt chunks.
--    private void parseTextChunk() throws IOException {
--        PNGTextualData[] textualData = decoder.getTextualData();
--
--        if(textualData != null) {
--            for(int i = 0; i < textualData.length; i++) {
--                PNGTextualData textData = textualData[i];
--                String keyword = textData.getKeyword();
--                String text = textData.getText();
--                String translatedKeyword = textData.getTranslatedKeyword();
--
--                // No way to detect a zTXt chunk to use tEXt for zTXt.
--                // Also, all text is already decompressed.
--                if(keyword.equals(translatedKeyword)) { // tEXt and zTXt
--                    tEXt_keyword.add(keyword);
--                    tEXt_text.add(text);
--                } else {                                // iTXt
--                    iTXt_keyword.add(keyword);
--                    iTXt_text.add(text);
--                    iTXt_translatedKeyword.add(translatedKeyword);
--
--                    // XXX No access to compression flag so set to 'false'
--                    // as text is decompressed by codecLib.
--                    int compressionFlag = 0;
--                    iTXt_compressionFlag.add(new Integer(compressionFlag));
--        
--                    // No access to compression method but only specified
--                    // one is '0' (deflate compression with ZLib data stream).
--                    int compressionMethod = 0;
--                    iTXt_compressionMethod.add(new Integer(compressionMethod));
--
--                    String languageTag = textData.getEncoding();
--                    iTXt_languageTag.add(languageTag);        
--                }
--            }
--        }
--    }
--
--    synchronized void readMetadata(CLibPNGImageReader reader,
--                                   Decoder decoder) throws IIOException {
--        if (gotMetadata) {
--            return;
--        }
--
--        this.reader = reader;
--        this.decoder = decoder;
--
--        readHeader();
--
--        try {
--            parse_PLTE_chunk();
--            parse_bKGD_chunk();
--            parse_cHRM_chunk();
--            parse_gAMA_chunk();
--            parse_hIST_chunk();
--            parse_iCCP_chunk();
--            parse_pHYs_chunk();
--            parse_sBIT_chunk();
--            parse_sPLT_chunk();
--            parse_sRGB_chunk();
--            parse_tIME_chunk();
--            parse_tRNS_chunk();
--
--            parseTextChunk();
--
--            PNGChunk[] userChunks = decoder.getUserData();
--            if(userChunks != null) {
--                for(int i = 0; i < userChunks.length; i++) {
--                    // Read an unknown chunk
--                    PNGChunk userChunk = userChunks[i];
--
--                    int chunkType = userChunk.getID();
--                    byte[] b = userChunk.getData();
--
--                    StringBuffer chunkName = new StringBuffer(4);
--                    chunkName.append((char)(chunkType >>> 24));
--                    chunkName.append((char)((chunkType >> 16) & 0xff));
--                    chunkName.append((char)((chunkType >> 8) & 0xff));
--                    chunkName.append((char)(chunkType & 0xff));
--
--                    int ancillaryBit = chunkType >>> 28;
--                    if (ancillaryBit == 0) {
--                        processWarningOccurred(
--                                               "Encountered unknown chunk with critical bit set!");
--                    }
--
--                    unknownChunkType.add(chunkName.toString());
--                    unknownChunkData.add(b);
--                }
--            }
--        } catch (IOException e) {
--            throw new IIOException("Error reading PNG metadata", e);
--        } finally {
--            this.reader = null;
--            this.decoder = null;
--        }
--
--        gotMetadata = true;
--    }
--
--    void processWarningOccurred(String warning) {
--        if(reader != null) {
--            reader.forwardWarningMessage(warning);
--        }
--    }
--
--    // END metadata reading methods.
--
--    // BEGIN metadata writing methods.
--
--    synchronized void writeMetadata(Encoder encoder) throws IIOException {
--        if(IHDR_present) {
--            encoder.setBitDepth(IHDR_bitDepth);
--            encoder.setInterlaceMethod(IHDR_interlaceMethod == 0 ?
--                                       Encoder.PNG_INTERLACE_METHOD_DEFAULT :
--                                       Encoder.PNG_INTERLACE_METHOD_ADAM7);
--        }
--
--        if(PLTE_present) {
--            int paletteLength = PLTE_red.length;
--            byte[] palette = new byte[3*paletteLength];
--            for(int i = 0, j= 0; i < paletteLength; i++) {
--                palette[j++] = PLTE_red[i];
--                palette[j++] = PLTE_green[i];
--                palette[j++] = PLTE_blue[i];
--            }
--            encoder.setPalette(palette);
--        }
--
--        if(bKGD_present) {
--            int[] color;
--            switch(bKGD_colorType) {
--            case PNG_COLOR_GRAY:
--                color = new int[] {bKGD_gray};
--                break;
--            case PNG_COLOR_PALETTE:
--                color = new int[] {bKGD_index};
--                break;
--            default:
--                color = new int[] {bKGD_red, bKGD_green, bKGD_blue};
--            }
--            encoder.setBackground(color);
--        }
--
--        if(cHRM_present) {
--            encoder.setPrimaryChromaticities(cHRM_whitePointX,
--                                             cHRM_whitePointY,
--                                             cHRM_redX, cHRM_redY,
--                                             cHRM_greenX, cHRM_greenY,
--                                             cHRM_blueX, cHRM_blueY);
--        }
--
--        if(gAMA_present) {
--            encoder.setImageGamma(gAMA_gamma);
--        }
--
--        if(hIST_present) {
--            int histogramLength = hIST_histogram.length;
--            short[] histogram = new short[histogramLength];
--            for(int i = 0; i < histogramLength; i++) {
--                histogram[i] = (short)hIST_histogram[i];
--            }
--            encoder.setHistogram(histogram);
--        }
--
--        if(iCCP_present) {
--            // Encoder expects an uncompressed profile so decompress.
--            Inflater decompresser = new Inflater();
--            decompresser.setInput(iCCP_compressedProfile);
--            byte[] result = new byte[2*decompresser.getRemaining()];
--
--            int off = 0;
--            try {
--                do {
--                    off +=
--                        decompresser.inflate(result, off, result.length - off);
--                    if(off == result.length && !decompresser.finished()) {
--                        byte[] tmpbuf = new byte[2*result.length];
--                        System.arraycopy(result, 0, tmpbuf, 0, result.length);
--                        result = tmpbuf;
--                    }
--                } while(!decompresser.finished());
--                decompresser.end();
--
--                byte[] uncompressedProfile;
--                if(off == result.length) {
--                    uncompressedProfile = result;
--                } else {
--                    uncompressedProfile = new byte[off];
--                    System.arraycopy(result, 0, uncompressedProfile, 0, off);
--                }
--
--                String iCCPName = toPrintableLatin1(iCCP_profileName);
--                encoder.setEmbeddedICCProfile(iCCPName, uncompressedProfile);
--            } catch(DataFormatException e) {
--                // XXX warning message?
--            }
--        }
--
--        if(iTXt_keyword.size() > 0) {
--            int numChunks = iTXt_keyword.size();
--            for(int i = 0; i < numChunks; i++) {
--                Integer compressionFlag =
--                    Integer.valueOf((String)iTXt_compressionFlag.get(i));
--                encoder.setUnicodeTextualData
--                    ((String)iTXt_keyword.get(i),
--                     (String)iTXt_translatedKeyword.get(i),
--                     (String)iTXt_languageTag.get(i),
--                     (String)iTXt_text.get(i),
--                     compressionFlag.intValue() == 1);
--            }
--        }
--
--        if(pHYs_present) {
--            encoder.setPhysicalPixelDimensions(pHYs_pixelsPerUnitXAxis,
--                                               pHYs_pixelsPerUnitYAxis,
--                                               pHYs_unitSpecifier);
--        }
--
--        if(sBIT_present) {
--            byte[] bits;
--            switch(sBIT_colorType) {
--            case PNG_COLOR_GRAY:
--                bits = new byte[] {(byte)(sBIT_grayBits&0xff)};
--                break;
--            case PNG_COLOR_GRAY_ALPHA:
--                bits = new byte[] {(byte)(sBIT_grayBits&0xff),
--                                   (byte)(sBIT_alphaBits&0xff)};
--                break;
--            case PNG_COLOR_RGB_ALPHA:
--                bits = new byte[] {(byte)(sBIT_redBits&0xff),
--                                   (byte)(sBIT_greenBits&0xff),
--                                   (byte)(sBIT_blueBits&0xff),
--                                   (byte)(sBIT_alphaBits&0xff)};
--                break;
--            default: // RGB and PALETTE
--                bits = new byte[] {(byte)(sBIT_redBits&0xff),
--                                   (byte)(sBIT_greenBits&0xff),
--                                   (byte)(sBIT_blueBits&0xff)};
--                break;
--            }
--            encoder.setSignificantBits(bits);
--        }
--
--        if(sPLT_present) {
--            if(sPLT_sampleDepth == 8) {
--                byte[] red = new byte[sPLT_red.length];
--                byte[] green = new byte[sPLT_green.length];
--                byte[] blue = new byte[sPLT_blue.length];
--                byte[] alpha = new byte[sPLT_alpha.length];
--                short[] frequency = new short[sPLT_frequency.length];
--
--                int length = red.length;
--                for(int i = 0; i < length; i++) {
--                    red[i] = (byte)(sPLT_red[i]&0xff);
--                    green[i] = (byte)(sPLT_green[i]&0xff);
--                    blue[i] = (byte)(sPLT_blue[i]&0xff);
--                    alpha[i] = (byte)(sPLT_alpha[i]&0xff);
--                    frequency[i] = (short)(sPLT_frequency[i]&0xffff);
--                }
--
--                String sPLTName = toPrintableLatin1(sPLT_paletteName);
--                encoder.setSuggestedPalette(sPLTName,
--                                            red, green, blue, alpha,
--                                            frequency);
--            } else {
--                short[] red = new short[sPLT_red.length];
--                short[] green = new short[sPLT_green.length];
--                short[] blue = new short[sPLT_blue.length];
--                short[] alpha = new short[sPLT_alpha.length];
--                short[] frequency = new short[sPLT_frequency.length];
--
--                int length = red.length;
--                for(int i = 0; i < length; i++) {
--                    red[i] = (short)(sPLT_red[i]&0xffff);
--                    green[i] = (short)(sPLT_green[i]&0xffff);
--                    blue[i] = (short)(sPLT_blue[i]&0xffff);
--                    alpha[i] = (short)(sPLT_alpha[i]&0xffff);
--                    frequency[i] = (short)(sPLT_frequency[i]&0xffff);
--                }
--
--                String sPLTName = toPrintableLatin1(sPLT_paletteName);
--                encoder.setSuggestedPalette(sPLTName,
--                                            red, green, blue, alpha,
--                                            frequency);
--            }
--        }
--
--        if(sRGB_present) {
--            encoder.setStandardRGB(sRGB_renderingIntent);
--        }
--
--        if(tEXt_keyword.size() > 0) {
--            int numChunks = tEXt_keyword.size();
--            for(int i = 0; i < numChunks; i++) {
--                encoder.setTextualData((String)tEXt_keyword.get(i),
--                                       (String)tEXt_text.get(i),
--                                       false);
--            }
--        }
--
--        if(tIME_present) {
--            encoder.setLastModificationTime
--                (new GregorianCalendar(tIME_year, tIME_month - 1, tIME_day,
--                                       tIME_hour, tIME_minute, tIME_second));
--        }
--
--        if(tRNS_present) {
--            if(tRNS_colorType == PNG_COLOR_GRAY) {
--                encoder.setTransparency(tRNS_gray, tRNS_gray, tRNS_gray);
--            } else if(tRNS_colorType == PNG_COLOR_PALETTE) {
--                int length = tRNS_alpha.length;
--                int[] color = new int[length];
--                for(int i = 0; i < length; i++) {
--                    color[i] = tRNS_alpha[i]&0xff;
--                }
--                encoder.setTransparency(color);
--            } else {
--                encoder.setTransparency(tRNS_red, tRNS_green, tRNS_blue);
--            }
--        }
--
--        if(zTXt_keyword.size() > 0) {
--            int numChunks = zTXt_keyword.size();
--            for(int i = 0; i < numChunks; i++) {
--                encoder.setTextualData((String)zTXt_keyword.get(i),
--                                       (String)zTXt_text.get(i),
--                                       true);
--            }
--        }
--
--        if(unknownChunkType.size() > 0) {
--            int numChunks = unknownChunkType.size();
--            for(int i = 0; i < numChunks; i++) {
--                encoder.setUserData((String)unknownChunkType.get(i),
--                                    (byte[])unknownChunkData.get(i),
--                                    Encoder.PNG_SAVE_BEFORE_IMAGE_DATA);
--            }
--        }
--    }
--
--    // END metadata writing methods.
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGMetadataFormat.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGMetadataFormat.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,556 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibPNGMetadataFormat.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.1 $
-- * $Date: 2005/02/11 05:01:39 $
-- * $State: Exp $
-- */
--
--package com.sun.media.imageioimpl.plugins.png;
--
--import java.util.ArrayList;
--import java.util.Arrays;
--import java.util.List;
--import java.util.ListResourceBundle;
--import javax.imageio.ImageTypeSpecifier;
--import javax.imageio.metadata.IIOMetadataFormat;
--import javax.imageio.metadata.IIOMetadataFormatImpl;
--
--public class CLibPNGMetadataFormat extends IIOMetadataFormatImpl {
--
--    private static IIOMetadataFormat instance = null;
--
--    private static String VALUE_0 = "0";
--    private static String VALUE_1 = "1";
--    private static String VALUE_12 = "12";
--    private static String VALUE_23 = "23";
--    private static String VALUE_31 = "31";
--    private static String VALUE_59 = "59";
--    private static String VALUE_60 = "60";
--    private static String VALUE_255 = "255";
--    private static String VALUE_MAX_16 = "65535"; // 2^16 - 1
--    private static String VALUE_MAX_32 = "2147483647"; // 2^32 - 1
--
--    private CLibPNGMetadataFormat() {
--        super(CLibPNGMetadata.nativeMetadataFormatName,
--              CHILD_POLICY_SOME);
--
--        // root -> IHDR
--        addElement("IHDR", CLibPNGMetadata.nativeMetadataFormatName,
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("IHDR", "width", 
--                     DATATYPE_INTEGER, true, null, 
--                     VALUE_1, VALUE_MAX_32, true, true);
--
--        addAttribute("IHDR", "height", 
--                     DATATYPE_INTEGER, true, null, 
--                     VALUE_1, VALUE_MAX_32, true, true);
--
--        addAttribute("IHDR", "bitDepth", 
--                     DATATYPE_INTEGER, true, null,
--                     Arrays.asList(CLibPNGMetadata.IHDR_bitDepths));
--
--        String[] colorTypes = {
--            "Grayscale", "RGB", "Palette", "GrayAlpha", "RGBAlpha"
--        };
--        addAttribute("IHDR", "colorType", 
--                     DATATYPE_STRING, true, null,
--                     Arrays.asList(colorTypes));
--
--        addAttribute("IHDR", "compressionMethod",
--                     DATATYPE_STRING, true, null,
--                     Arrays.asList(CLibPNGMetadata.IHDR_compressionMethodNames));
--
--        addAttribute("IHDR", "filterMethod",
--                     DATATYPE_STRING, true, null,
--                     Arrays.asList(CLibPNGMetadata.IHDR_filterMethodNames));
--
--        addAttribute("IHDR", "interlaceMethod",
--                     DATATYPE_STRING, true, null,
--                     Arrays.asList(CLibPNGMetadata.IHDR_interlaceMethodNames));
--
--        // root -> PLTE
--        addElement("PLTE", CLibPNGMetadata.nativeMetadataFormatName,
--                   1, 256);
--        
--        // root -> PLTE -> PLTEEntry
--        addElement("PLTEEntry", "PLTE",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("PLTEEntry", "index",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--        
--        addAttribute("PLTEEntry", "red",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--        
--        addAttribute("PLTEEntry", "green",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--        
--        addAttribute("PLTEEntry", "blue",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        // root -> bKGD
--        addElement("bKGD", CLibPNGMetadata.nativeMetadataFormatName,
--                   CHILD_POLICY_CHOICE);
--
--        // root -> bKGD -> bKGD_Grayscale
--        addElement("bKGD_Grayscale", "bKGD",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("bKGD_Grayscale", "gray",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        // root -> bKGD -> bKGD_RGB
--        addElement("bKGD_RGB", "bKGD",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("bKGD_RGB", "red",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("bKGD_RGB", "green",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("bKGD_RGB", "blue",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        // root -> bKGD -> bKGD_Palette
--        addElement("bKGD_Palette", "bKGD",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("bKGD_Palette", "index",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        // root -> cHRM
--        addElement("cHRM", CLibPNGMetadata.nativeMetadataFormatName,
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("cHRM", "whitePointX",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("cHRM", "whitePointY",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("cHRM", "redX",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("cHRM", "redY",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("cHRM", "greenX",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("cHRM", "greenY",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("cHRM", "blueX",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("cHRM", "blueY",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        // root -> gAMA
--        addElement("gAMA", CLibPNGMetadata.nativeMetadataFormatName,
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("gAMA", "value",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_32, true, true);
--
--        // root -> hIST
--        addElement("hIST", CLibPNGMetadata.nativeMetadataFormatName,
--                   1, 256);
--
--        // root -> hISTEntry
--        addElement("hISTEntry", "hIST",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("hISTEntry", "index",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("hISTEntry", "value",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        // root -> iCCP
--        addElement("iCCP", CLibPNGMetadata.nativeMetadataFormatName,
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("iCCP", "profileName",
--                     DATATYPE_STRING, true, null);
--
--        addAttribute("iCCP", "compressionMethod",
--                     DATATYPE_STRING, true, null,
--                     Arrays.asList(CLibPNGMetadata.iCCP_compressionMethodNames));
--
--        addObjectValue("iCCP", byte.class, 0, Integer.MAX_VALUE);
--
--        // root -> iTXt
--        addElement("iTXt", CLibPNGMetadata.nativeMetadataFormatName,
--                   1, Integer.MAX_VALUE);
--
--        // root -> iTXt -> iTXtEntry
--        addElement("iTXtEntry", "iTXt",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("iTXtEntry", "keyword",
--                     DATATYPE_STRING, true, null);
--
--        addBooleanAttribute("iTXtEntry", "compressionFlag",
--                            false, false);
--
--        addAttribute("iTXtEntry", "compressionMethod",
--                     DATATYPE_STRING, true, null);
--
--        addAttribute("iTXtEntry", "languageTag",
--                     DATATYPE_STRING, true, null);
--
--        addAttribute("iTXtEntry", "translatedKeyword",
--                     DATATYPE_STRING, true, null);
--
--        addAttribute("iTXtEntry", "text",
--                     DATATYPE_STRING, true, null);
--
--        // root -> pHYS
--        addElement("pHYS", CLibPNGMetadata.nativeMetadataFormatName,
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("pHYS", "pixelsPerUnitXAxis",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_32, true, true);
--        addAttribute("pHYS", "pixelsPerUnitYAxis",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_32, true, true);
--        addAttribute("pHYS", "unitSpecifier",
--                     DATATYPE_STRING, true, null,
--                     Arrays.asList(CLibPNGMetadata.unitSpecifierNames));
--
--        // root -> sBIT
--        addElement("sBIT", CLibPNGMetadata.nativeMetadataFormatName,
--                   CHILD_POLICY_CHOICE);
--
--        // root -> sBIT -> sBIT_Grayscale
--        addElement("sBIT_Grayscale", "sBIT",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("sBIT_Grayscale", "gray",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        // root -> sBIT -> sBIT_GrayAlpha
--        addElement("sBIT_GrayAlpha", "sBIT",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("sBIT_GrayAlpha", "gray",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sBIT_GrayAlpha", "alpha",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        // root -> sBIT -> sBIT_RGB
--        addElement("sBIT_RGB", "sBIT",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("sBIT_RGB", "red",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sBIT_RGB", "green",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sBIT_RGB", "blue",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        // root -> sBIT -> sBIT_RGBAlpha
--        addElement("sBIT_RGBAlpha", "sBIT",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("sBIT_RGBAlpha", "red",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sBIT_RGBAlpha", "green",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sBIT_RGBAlpha", "blue",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sBIT_RGBAlpha", "alpha",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        // root -> sBIT -> sBIT_Palette
--        addElement("sBIT_Palette", "sBIT",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("sBIT_Palette", "red",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sBIT_Palette", "green",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sBIT_Palette", "blue",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        // root -> sPLT
--        addElement("sPLT", CLibPNGMetadata.nativeMetadataFormatName,
--                   1, 256);
--
--        // root -> sPLT -> sPLTEntry
--        addElement("sPLTEntry", "sPLT",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("sPLTEntry", "index",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sPLTEntry", "red",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sPLTEntry", "green",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sPLTEntry", "blue",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("sPLTEntry", "alpha",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        // root -> sRGB
--        addElement("sRGB", CLibPNGMetadata.nativeMetadataFormatName,
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("sRGB", "renderingIntent",
--                     DATATYPE_STRING, true, null,
--                     Arrays.asList(CLibPNGMetadata.renderingIntentNames));
--
--        // root -> tEXt
--        addElement("tEXt", CLibPNGMetadata.nativeMetadataFormatName,
--                   1, Integer.MAX_VALUE);
--
--        // root -> tEXt -> tEXtEntry
--        addElement("tEXtEntry", "tEXt",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("tEXtEntry", "keyword",
--                     DATATYPE_STRING, true, null);
--
--        addAttribute("tEXtEntry", "value",
--                     DATATYPE_STRING, true, null);
--
--        // root -> tIME
--        addElement("tIME", CLibPNGMetadata.nativeMetadataFormatName,
--                   CHILD_POLICY_EMPTY);
--        
--        addAttribute("tIME", "year",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("tIME", "month",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_1, VALUE_12, true, true);
--
--        addAttribute("tIME", "day",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_1, VALUE_31, true, true);
--
--        addAttribute("tIME", "hour",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_23, true, true);
--
--        addAttribute("tIME", "minute",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_59, true, true);
--
--        addAttribute("tIME", "second",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_60, true, true);
--
--        // root -> tRNS
--        addElement("tRNS", CLibPNGMetadata.nativeMetadataFormatName,
--                   CHILD_POLICY_CHOICE);
--        
--        // root -> tRNS -> tRNS_Grayscale
--        addElement("tRNS_Grayscale", "tRNS",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("tRNS_Grayscale", "gray",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        // root -> tRNS -> tRNS_RGB
--        addElement("tRNS_RGB", "tRNS",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("tRNS_RGB", "red",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("tRNS_RGB", "green",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        addAttribute("tRNS_RGB", "blue",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_MAX_16, true, true);
--
--        // root -> tRNS -> tRNS_Palette
--        addElement("tRNS_Palette", "tRNS",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("tRNS_Palette", "index",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        addAttribute("tRNS_Palette", "alpha",
--                     DATATYPE_INTEGER, true, null,
--                     VALUE_0, VALUE_255, true, true);
--
--        // root -> zTXt
--        addElement("zTXt", CLibPNGMetadata.nativeMetadataFormatName,
--                   1, Integer.MAX_VALUE);
--
--        // root -> zTXt -> zTXtEntry
--        addElement("zTXtEntry", "zTXt",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("zTXtEntry", "keyword",
--                     DATATYPE_STRING, true, null);
--
--        addAttribute("zTXtEntry", "compressionMethod",
--                     DATATYPE_STRING, true, null,
--                     Arrays.asList(CLibPNGMetadata.zTXt_compressionMethodNames));
--
--        addAttribute("zTXtEntry", "text", 
--                     DATATYPE_STRING, true, null);
--
--        // root -> UnknownChunks
--        addElement("UnknownChunks", CLibPNGMetadata.nativeMetadataFormatName,
--                   1, Integer.MAX_VALUE);
--
--        // root -> UnknownChunks -> UnknownChunk
--        addElement("UnknownChunk", "UnknownChunks",
--                   CHILD_POLICY_EMPTY);
--
--        addAttribute("UnknownChunk", "type",
--                     DATATYPE_STRING, true, null);
--
--        addObjectValue("UnknownChunk", byte.class, 0, Integer.MAX_VALUE);
--    }
--
--    public boolean canNodeAppear(String elementName,
--                                 ImageTypeSpecifier imageType) {
--        return true;
--    }
--    
--    public static synchronized IIOMetadataFormat getInstance() {
--        if (instance == null) {
--            instance = new CLibPNGMetadataFormat();
--        }
--        return instance;
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGMetadataFormatResources.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/png/CLibPNGMetadataFormatResources.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,277 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: CLibPNGMetadataFormatResources.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.1 $
-- * $Date: 2005/02/11 05:01:39 $
-- * $State: Exp $
-- */
--
--package com.sun.media.imageioimpl.plugins.png;
--
--import java.util.ListResourceBundle;
--import javax.imageio.metadata.IIOMetadataFormat;
--import javax.imageio.metadata.IIOMetadataFormatImpl;
--
--public class CLibPNGMetadataFormatResources extends ListResourceBundle {
--
--    static final Object[][] contents = {
--        // Node name, followed by description
--        { "IHDR", "The IHDR chunk, containing the header" },
--        { "PLTE", "The PLTE chunk, containing the palette" },
--        { "PLTEEntry", "A palette entry" },
--        { "bKGD", "The bKGD chunk, containing the background color" },
--        { "bKGD_RGB", "An RGB background color, for RGB and RGBAlpha images" },
--        { "bKGD_Grayscale",
--          "A grayscale background color, for Gray and GrayAlpha images" },
--        { "bKGD_Palette", "A background palette index" },
--        { "cHRM", "The cHRM chunk, containing color calibration" },
--        { "gAMA", "The gAMA chunk, containing the image gamma" },
--        { "hIST", "The hIST chunk, containing histogram information " },
--        { "hISTEntry", "A histogram entry" },
--        { "iCCP", "The iCCP chunk, containing an ICC color profile" },
--        { "iTXt", "The iTXt chunk, containing internationalized text" },
--        { "iTXtEntry", "A localized text entry" },
--        { "pHYS",
--          "The pHYS chunk, containing the pixel size and aspect ratio" },
--        { "sBIT", "The sBIT chunk, containing significant bit information" },
--        { "sBIT_Grayscale", "Significant bit information for gray samples" },
--        { "sBIT_GrayAlpha",
--          "Significant bit information for gray and alpha samples" },
--        { "sBIT_RGB", "Significant bit information for RGB samples" },
--        { "sBIT_RGBAlpha", "Significant bit information for RGBA samples" },
--        { "sBIT_Palette",
--          "Significant bit information for RGB palette entries" },
--        { "sPLT", "The sPLT chunk, containing a suggested palette" },
--        { "sPLTEntry", "A suggested palette entry" },
--        { "sRGB", "The sRGB chunk, containing rendering intent information" },
--        { "tEXt", "The tEXt chunk, containing text" },
--        { "tEXtEntry", "A text entry" },
--        { "tIME", "The tIME chunk, containing the image modification time" },
--        { "tRNS", "The tRNS chunk, containing transparency information" },
--        { "tRNS_Grayscale",
--          "A grayscale value that should be considered transparent" },
--        { "tRNS_RGB",
--          "An RGB value that should be considered transparent" },
--        { "tRNS_Palette",
--          "A palette index that should be considered transparent" },
--        { "zTXt", "The zTXt chunk, containing compressed text" },
--        { "zTXtEntry", "A compressed text entry" },
--        { "UnknownChunks", "A set of unknown chunks" },
--        { "UnknownChunk", "Unknown chunk data stored as a byte array" },
--
--        // Node name + "/" + AttributeName, followed by description
--        { "IHDR/width", "The width of the image in pixels" },
--        { "IHDR/height", "The height of the image in pixels" },
--        { "IHDR/bitDepth", "The bit depth of the image samples" },
--        { "IHDR/colorType", "The color type of the image" },
--        { "IHDR/compressionMethod",
--"The compression used for image data, always \"deflate\"" },
--        { "IHDR/filterMethod",
--"The filtering method used for compression, always \"adaptive\"" },
--        { "IHDR/interlaceMethod",
--          "The interlacing method, \"none\" or \"adam7\"" },
--
--        { "PLTEEntry/index", "The index of a palette entry" },
--        { "PLTEEntry/red", "The red value of a palette entry" },
--        { "PLTEEntry/green", "The green value of a palette entry" },
--        { "PLTEEntry/blue", "The blue value of a palette entry" },
--
--        { "bKGD_Grayscale/gray", "A gray value to be used as a background" },
--        { "bKGD_RGB/red", "A red value to be used as a background" },
--        { "bKGD_RGB/green", "A green value to be used as a background" },
--        { "bKGD_RGB/blue", "A blue value to be used as a background" },
--        { "bKGD_Palette/index", "A palette index to be used as a background" },
--
--        { "cHRM/whitePointX",
--              "The CIE x coordinate of the white point, multiplied by 1e5" },
--        { "cHRM/whitePointY",
--              "The CIE y coordinate of the white point, multiplied by 1e5" },
--        { "cHRM/redX",
--              "The CIE x coordinate of the red primary, multiplied by 1e5" },
--        { "cHRM/redY",
--              "The CIE y coordinate of the red primary, multiplied by 1e5" },
--        { "cHRM/greenX",
--              "The CIE x coordinate of the green primary, multiplied by 1e5" },
--        { "cHRM/greenY",
--              "The CIE y coordinate of the green primary, multiplied by 1e5" },
--        { "cHRM/blueX",
--              "The CIE x coordinate of the blue primary, multiplied by 1e5" },
--        { "cHRM/blueY",
--              "The CIE y coordinate of the blue primary, multiplied by 1e5" },
--
--        { "gAMA/value",
--              "The image gamma, multiplied by 1e5" },
--
--        { "hISTEntry/index", "The palette index of this histogram entry" },
--        { "hISTEntry/value", "The frequency of this histogram entry" },
--
--        { "iCCP/profileName", "The name of this ICC profile" },
--        { "iCCP/compressionMethod",
--              "The compression method used to store this ICC profile" },
--
--        { "iTXtEntry/keyword", "The keyword" },
--        { "iTXtEntry/compressionMethod",
--              "The compression method used to store this iTXt entry" },
--        { "iTXtEntry/languageTag",
--              "The ISO tag describing the language of this iTXt entry" },
--        { "iTXtEntry/translatedKeyword",
--              "The translated keyword for iTXt entry" },
--        { "iTXtEntry/text",
--              "The localized text" },
--
--        { "pHYS/pixelsPerUnitXAxis",
--            "The number of horizontal pixels per unit, multiplied by 1e5" },
--        { "pHYS/pixelsPerUnitYAxis",
--            "The number of vertical pixels per unit, multiplied by 1e5" },
--        { "pHYS/unitSpecifier",
--            "The unit specifier for this chunk (i.e., meters)" },
--        
--        { "sBIT_Grayscale/gray",
--            "The number of significant bits of the gray samples" },
--        { "sBIT_GrayAlpha/gray",
--            "The number of significant bits of the gray of gray/alpha samples" },
--        { "sBIT_GrayAlpha/alpha",
--            "The number of significant bits of the alpha of gray/alpha samples" },
--        { "sBIT_RGB/red",
--            "The number of significant bits of the red of RGB samples" },
--        { "sBIT_RGB/green",
--            "The number of significant bits of the green of RGB samples" },
--        { "sBIT_RGB/blue",
--            "The number of significant bits of the blue of RGB samples" },
--        { "sBIT_RGBAlpha/red",
--            "The number of significant bits of the red of RGBA samples" },
--        { "sBIT_RGBAlpha/green",
--            "The number of significant bits of the green of RGBA samples" },
--        { "sBIT_RGBAlpha/blue",
--            "The number of significant bits of the blue of RGBA samples" },
--        { "sBIT_RGBAlpha/alpha",
--            "The number of significant bits of the alpha of RGBA samples" },
--        { "sBIT_Palette/red",
--            "The number of significant bits of the red palette entries" },
--        { "sBIT_Palette/green",
--            "The number of significant bits of the green palette entries" },
--        { "sBIT_Palette/blue",
--            "The number of significant bits of the blue palette entries" },
--
--        { "sPLTEntry/index", "The index of a suggested palette entry" },
--        { "sPLTEntry/red", "The red value of a suggested palette entry" },
--        { "sPLTEntry/green", "The green value of a suggested palette entry" },
--        { "sPLTEntry/blue", "The blue value of a suggested palette entry" },
--        { "sPLTEntry/alpha", "The blue value of a suggested palette entry" },
--
--        { "sRGB/renderingIntent", "The rendering intent" },
--
--        { "tEXtEntry/keyword", "The keyword" },
--        { "tEXtEntry/value", "The text" },
--
--        { "tIME/year", "The year when the image was last modified" },
--        { "tIME/month",
--          "The month when the image was last modified, 1 = January" },
--        { "tIME/day",
--          "The day of the month when the image was last modified" },
--        { "tIME/hour",
--          "The hour when the image was last modified" },
--        { "tIME/minute",
--          "The minute when the image was last modified" },
--        { "tIME/second",
--          "The second when the image was last modified, 60 = leap second" },
--
--        { "tRNS_Grayscale/gray",
--          "The gray value to be considered transparent" },
--        { "tRNS_RGB/red",
--          "The red value to be considered transparent" },
--        { "tRNS_RGB/green",
--          "The green value to be considered transparent" },
--        { "tRNS_RGB/blue",
--          "The blue value to be considered transparent" },
--        { "tRNS_Palette/index",
--          "A palette index to be considered transparent" },
--        { "tRNS_Palette/alpha",
--          "The transparency associated with the palette entry" },
--
--        { "zTXtEntry/keyword", "The keyword" },
--        { "zTXtEntry/compressionMethod", "The compression method" },
--        { "zTXtEntry/text", "The compressed text" },
--
--        { "UnknownChunk/type", "The 4-character type of the unknown chunk" }
--    };
--
--    public CLibPNGMetadataFormatResources() {}
--
--    public Object[][] getContents() {
--        return contents;
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibFaxDecompressor.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibFaxDecompressor.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,244 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: TIFFCodecLibFaxDecompressor.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.1 $
-- * $Date: 2005/02/11 05:01:44 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.tiff;
--
--import java.io.IOException;
--import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet;
--import com.sun.media.imageio.plugins.tiff.TIFFDecompressor;
--
--public class TIFFCodecLibFaxDecompressor extends TIFFFaxDecompressor {
--
--    private static final boolean DEBUG = false; // XXX 'false' for release!!!
--
--    /**
--     * com.sun.medialib.codec.g3fax.Decoder for T.4 or
--     * com.sun.medialib.codec.g4fax.Decoder for T.6.
--     */
--    private Object decoder = null;
--
--    /**
--     * Constructor which initializes the internal codecLib decoder.
--     *
--     * @throws RuntimeException if <code>bilevelCompression</code> is
--     * not T.4 or T.6 compression or if codecLib is not available.
--     */
--    public TIFFCodecLibFaxDecompressor(int bilevelCompression) {
--        super();
--
--        try {
--            // 'compression' is set in the superclass method.
--            if(bilevelCompression ==
--               BaselineTIFFTagSet.COMPRESSION_CCITT_T_4) {
--                com.sun.medialib.codec.g3fax.Decoder decoder =
--                    new com.sun.medialib.codec.g3fax.Decoder();
--                this.decoder = decoder;
--            } else if(bilevelCompression ==
--                      BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) {
--                com.sun.medialib.codec.g4fax.Decoder decoder =
--                    new com.sun.medialib.codec.g4fax.Decoder();
--                this.decoder = decoder;
--            } else {
--                throw new RuntimeException("Unknown compression = "+
--                                           bilevelCompression);    
--            }
--        } catch (Throwable e) {
--            throw new RuntimeException("CodecLib not available");
--        }
--}
--
--    public synchronized final void decodeRaw(byte[] b, int dstOffset,
--                                             int pixelBitStride, // always 1
--                                             int scanlineStride)
--        throws IOException {
--
--        int bytesPerRow = (srcWidth + 7)/8;
--        byte[] image = null;
--        byte[] code = new byte[byteCount];
--        stream.seek(offset);
--        stream.readFully(code, 0, byteCount);
--
--        // Flip the bytes if fill order is LSB-to-MSB.
--        if(fillOrder == 2) {
--            for(int i = 0; i < byteCount; i++) {
--                code[i] = flipTable[code[i]&0xff];
--            }
--        }
--
--        if (dstOffset == 0 && bytesPerRow == scanlineStride) {
--            image = b;
--        } else {
--            image = new byte[srcWidth*srcHeight];
--        }
--
--        if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) {
--            com.sun.medialib.codec.g4fax.Decoder decoder =
--                (com.sun.medialib.codec.g4fax.Decoder)this.decoder;
--
--            if(DEBUG) {
--                System.out.println("Using MediaLib G4 decoder");
--            }
--
--            int result = com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE;
--            try {
--                result = decoder.decode(image, code, srcWidth, srcHeight, 0);
--            } catch(Throwable t) {
--                ((TIFFImageReader)reader).forwardWarningMessage
--                    ("codecLib T.6 decompressor failed; falling back to Java.");
--                result = com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE;
--            }
--
--            if(result ==
--               com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE) {
--                // Fall back to Java decoder.
--                if(DEBUG) {
--                    System.out.println("Falling back to Java G4 decoder");
--                }
--                super.decodeRaw(b, dstOffset, pixelBitStride, scanlineStride);
--                return;
--            }
--        } else {
--             com.sun.medialib.codec.g3fax.Decoder decoder =
--                 (com.sun.medialib.codec.g3fax.Decoder)this.decoder;
--             if(DEBUG) {
--                 System.out.println("Using MediaLib G3 decoder");
--             }
--
--             int decodingFlags = 0;
--             if(oneD == 1) {
--                 decodingFlags = 
--                     decoder.G3FAX_VERTICAL_CODING |
--                     decoder.G3FAX_NORTC;
--                 if(DEBUG) {
--                     System.out.print("G3FAX_VERTICAL_CODING"+
--                                      " | G3FAX_NORTC");
--                 }
--             } else {
--                 decodingFlags = 
--                     decoder.G3FAX_HORIZONTAL_CODING |
--                     decoder.G3FAX_NORTC;
--                 if(DEBUG) {
--                     System.out.print("G3FAX_HORIZONTAL_CODING"+
--                                      " | G3FAX_NORTC");
--                 }
--             }
--
--             if(fillBits == 1) {
--                 if(DEBUG) {
--                     System.out.print(" | G3FAX_EOLPADDING_CODING");
--                 }
--                 decodingFlags |= decoder.G3FAX_EOLPADDING;
--             }
--
--             if(DEBUG) {
--                 System.out.println("");
--             }
--
--             int result = com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE;
--             try {
--                 result = decoder.decode(image, code, srcWidth, srcHeight,
--                                        decodingFlags);
--             } catch(Throwable t) {
--                 ((TIFFImageReader)reader).forwardWarningMessage
--                     ("codecLib T.4 decompressor failed; falling back to Java.");
--                 result = com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE;
--             }
--
--             if(result ==
--                com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE) {
--                 // Fall back to Java decoder.
--                 if(DEBUG) {
--                     System.out.println("Falling back to Java G3 decoder");
--                 }
--                 super.decodeRaw(b, dstOffset, pixelBitStride, scanlineStride);
--                 return;
--             }
--        }
--        
--        if (image != b) {
--            int srcOffset = 0;
--            for (int row = 0; row < srcHeight; row++) {
--                System.arraycopy(image, srcOffset, b, dstOffset, bytesPerRow);
--                srcOffset += bytesPerRow;
--                dstOffset += scanlineStride;
--            }
--        }
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibRLECompressor.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibRLECompressor.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,181 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: TIFFCodecLibRLECompressor.java,v $
-- *
-- * 
-- * Copyright (c) 2006 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.1 $
-- * $Date: 2006/04/22 00:04:23 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.tiff;
--
--import java.io.IOException;
--import javax.imageio.IIOException;
--
--public class TIFFCodecLibRLECompressor extends TIFFRLECompressor {
--
--    private static final boolean DEBUG = false; // XXX 'false' for release!!!
--
--    Object encoder;
--
--    public TIFFCodecLibRLECompressor() {
--        super();
--
--        try {
--            com.sun.medialib.codec.g3fax.Encoder encoder =
--                new com.sun.medialib.codec.g3fax.Encoder();
--            this.encoder = encoder;
--        } catch(Throwable t) {
--            throw new RuntimeException("CodecLib not available");
--        }
--    }
--    
--    public int encode(byte[] b, int off,
--                      int width, int height,
--                      int[] bitsPerSample,
--                      int scanlineStride) throws IOException {
--        if (bitsPerSample.length != 1 || bitsPerSample[0] != 1) {
--            throw new IIOException
--                ("Bits per sample must be 1 for RLE compression!"); 
--        }
--
--        // Set image to data if possible; otherwise copy.
--        int bytesPerRow = (width + 7)/8;
--        byte[] image = null;
--
--        if(off == 0 && bytesPerRow == scanlineStride) {
--            image = b;
--        } else {
--            image = new byte[bytesPerRow*height];
--            int dataOffset = off;
--            int imageOffset = 0;
--            for(int row = 0; row < height; row++) {
--                System.arraycopy(b, dataOffset, image, imageOffset,
--                                 bytesPerRow);
--                dataOffset += scanlineStride;
--                imageOffset += bytesPerRow;
--            }
--        }
--
--        // In the worst case, 2 bits of input will result in 9 bits of output,
--        // plus 2 extra bits if the row starts with black.
--        int maxBits = 9*((width + 1)/2) + 2;
--        byte[] compData = new byte[((maxBits + 7)/8)*height];
--
--        // Attempt the codecLib encoder.
--        com.sun.medialib.codec.g3fax.Encoder clibEncoder =
--            (com.sun.medialib.codec.g3fax.Encoder)encoder;
--
--        // Set RLE encoding flag.
--        int encodingFlags =
--            com.sun.medialib.codec.g3fax.Constants.G3FAX_RLE_CODING;
--        if(inverseFill) {
--            encodingFlags |=
--                com.sun.medialib.codec.g3fax.Constants.G3FAX_LSB2MSB;
--            if(DEBUG) {
--                System.out.println("Setting LSB flag");
--            }
--        }
--
--        // Set result flag.
--        int result =
--            com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE;
--        try {
--            if(DEBUG) {
--                System.out.println("Using MediaLib RLE encoder");
--            }
--            result = clibEncoder.encode(compData, image, width, height,
--                                        2, // k parameter
--                                        encodingFlags);
--            stream.write(compData, 0, result);
--        } catch(Throwable t) {
--            if(DEBUG) {
--                System.out.println("MediaLib RLE encoder failed: "+t);
--            }
--            // XXX Should write a warning to listeners here.
--            result = com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE;
--        }
--
--        // If the codecLib encoder failed, try the superclass.
--        if(result == com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE) {
--            if(DEBUG) {
--                System.out.println("Falling back to Java RLE encoder");
--            }
--            result = super.encode(b, off, width, height,
--                                  bitsPerSample, scanlineStride);
--        }
--
--        return result;
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibT4Compressor.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibT4Compressor.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,198 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: TIFFCodecLibT4Compressor.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.2 $
-- * $Date: 2006/01/30 23:22:03 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.tiff;
--
--public class TIFFCodecLibT4Compressor extends TIFFT4Compressor {
--
--    private static final boolean DEBUG = false; // XXX 'false' for release!!!
--
--    Object encoder;
--
--    public TIFFCodecLibT4Compressor() {
--        super();
--
--        try {
--            com.sun.medialib.codec.g3fax.Encoder encoder =
--                new com.sun.medialib.codec.g3fax.Encoder();
--            this.encoder = encoder;
--        } catch(Throwable t) {
--            throw new RuntimeException("CodecLib not available");
--        }
--    }
--    
--    /**
--     * Encode a buffer of data using CCITT T.4 Compression also known as
--     * Group 3 facsimile compression.
--     *
--     * @param is1DMode     Whether to perform one-dimensional encoding.
--     * @param isEOLAligned Whether EOL bit sequences should be padded.
--     * @param data         The row of data to compress.
--     * @param lineStride   Byte step between the same sample in different rows.
--     * @param colOffset    Bit offset within first <code>data[rowOffset]</code>.
--     * @param width        Number of bits in the row.
--     * @param height       Number of rows in the buffer.
--     * @param compData     The compressed data.
--     *
--     * @return The number of bytes saved in the compressed data array.
--     */
--    public final int encodeT4(boolean is1DMode,
--                              boolean isEOLAligned,
--                              byte[] data,
--                              int lineStride,
--                              int colOffset,
--                              int width,
--                              int height,
--                              byte[] compData) {
--
--        // Defer to superclass if bit offset is not byte-aligned.
--        if(colOffset % 8 != 0) {
--            return super.encodeT4(is1DMode, isEOLAligned,
--                                  data, lineStride, colOffset,
--                                  width, height, compData);
--        }
--
--        // Set image to data if possible; otherwise copy.
--        int bytesPerRow = (width + 7)/8;
--        byte[] image = null;
--
--        if(colOffset == 0 && bytesPerRow == lineStride) {
--            image = data;
--        } else {
--            image = new byte[bytesPerRow*height];
--            int dataOffset = colOffset / 8;
--            int imageOffset = 0;
--            for(int row = 0; row < height; row++) {
--                System.arraycopy(data, dataOffset, image, imageOffset,
--                                 bytesPerRow);
--                dataOffset += lineStride;
--                imageOffset += bytesPerRow;
--            }
--        }
--
--        // Attempt the codecLib encoder.
--        com.sun.medialib.codec.g3fax.Encoder clibEncoder =
--            (com.sun.medialib.codec.g3fax.Encoder)encoder;
--        //System.out.println("Using codecLib G3 encoder");
--
--        // Set encoding flags.
--        int encodingFlags =
--            is1DMode ?
--            com.sun.medialib.codec.g3fax.Constants.G3FAX_HORIZONTAL_CODING :
--            com.sun.medialib.codec.g3fax.Constants.G3FAX_VERTICAL_CODING;
--        if(isEOLAligned) {
--            encodingFlags |=
--                com.sun.medialib.codec.g3fax.Constants.G3FAX_EOLPADDING;
--        }
--        if(inverseFill) {
--            encodingFlags |=
--                com.sun.medialib.codec.g3fax.Constants.G3FAX_LSB2MSB;
--        }
--
--        int result =
--            com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE;
--        try {
--            if(DEBUG) {
--                System.out.println("Using MediaLib G3 encoder");
--            }
--            result = clibEncoder.encode(compData, image, width, height,
--                                        2, // k parameter
--                                        encodingFlags);
--        } catch(Throwable t) {
--            if(DEBUG) {
--                System.out.println("MediaLib G3 encoder failed: "+t);
--            }
--            // XXX Should write a warning to listeners here.
--            result = com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE;
--        }
--
--        // If the codecLib encoder failed, try the superclass.
--        if(result == com.sun.medialib.codec.g3fax.Constants.G3FAX_FAILURE) {
--            if(DEBUG) {
--                System.out.println("Falling back to Java G3 encoder");
--            }
--            result = super.encodeT4(is1DMode, isEOLAligned,
--                                    data, lineStride, colOffset,
--                                    width, height, compData);
--        }
--
--        return result;
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibT6Compressor.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFCodecLibT6Compressor.java	2012-08-22 20:24:05.000000000 +0000
-+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
-@@ -1,181 +0,0 @@
--/*
-- * #%L
-- * Fork of JAI Image I/O Tools.
-- * %%
-- * Copyright (C) 2008 - 2012 Open Microscopy Environment:
-- *   - Board of Regents of the University of Wisconsin-Madison
-- *   - Glencoe Software, Inc.
-- *   - University of Dundee
-- * %%
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions are met:
-- * 
-- * 1. Redistributions of source code must retain the above copyright notice,
-- *    this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright notice,
-- *    this list of conditions and the following disclaimer in the documentation
-- *    and/or other materials provided with the distribution.
-- * 
-- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
-- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGE.
-- * 
-- * The views and conclusions contained in the software and documentation are
-- * those of the authors and should not be interpreted as representing official
-- * policies, either expressed or implied, of any organization.
-- * #L%
-- */
--
--/*
-- * $RCSfile: TIFFCodecLibT6Compressor.java,v $
-- *
-- * 
-- * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
-- * 
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met: 
-- * 
-- * - Redistribution of source code must retain the above copyright 
-- *   notice, this  list of conditions and the following disclaimer.
-- * 
-- * - Redistribution in binary form must reproduce the above copyright
-- *   notice, this list of conditions and the following disclaimer in 
-- *   the documentation and/or other materials provided with the
-- *   distribution.
-- * 
-- * Neither the name of Sun Microsystems, Inc. or the names of 
-- * contributors may be used to endorse or promote products derived 
-- * from this software without specific prior written permission.
-- * 
-- * This software is provided "AS IS," without a warranty of any 
-- * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
-- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
-- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
-- * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
-- * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
-- * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
-- * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
-- * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
-- * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
-- * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
-- * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
-- * POSSIBILITY OF SUCH DAMAGES. 
-- * 
-- * You acknowledge that this software is not designed or intended for 
-- * use in the design, construction, operation or maintenance of any 
-- * nuclear facility. 
-- *
-- * $Revision: 1.2 $
-- * $Date: 2006/01/30 23:22:34 $
-- * $State: Exp $
-- */
--package com.sun.media.imageioimpl.plugins.tiff;
--
--public class TIFFCodecLibT6Compressor extends TIFFT6Compressor {
--
--    private static final boolean DEBUG = false; // XXX 'false' for release!!!
--
--    Object encoder;
--
--    public TIFFCodecLibT6Compressor() {
--        super();
--
--        try {
--            com.sun.medialib.codec.g4fax.Encoder encoder =
--                new com.sun.medialib.codec.g4fax.Encoder();
--            this.encoder = encoder;
--        } catch(Throwable t) {
--            throw new RuntimeException("CodecLib not available");
--        }
--    }
--    
--    /**
--     * Encode a buffer of data using CCITT T.6 Compression also known as
--     * Group 4 facsimile compression.
--     *
--     * @param data        The row of data to compress.
--     * @param lineStride  Byte step between the same sample in different rows.
--     * @param colOffset   Bit offset within first <code>data[rowOffset]</code>.
--     * @param width       Number of bits in the row.
--     * @param height      Number of rows in the buffer.
--     * @param compData    The compressed data.
--     *
--     * @return The number of bytes saved in the compressed data array.
--     */
--    public synchronized final int encodeT6(byte[] data,
--                                           int lineStride,
--                                           int colOffset,
--                                           int width,
--                                           int height,
--                                           byte[] compData) {
--
--        // Defer to superclass if bit offset is not byte-aligned.
--        if(colOffset % 8 != 0) {
--            return super.encodeT6(data, lineStride, colOffset,
--                                  width, height, compData);
--        }
--
--        // Set image to data if possible; otherwise copy.
--        int bytesPerRow = (width + 7)/8;
--        byte[] image = null;
--
--        if(colOffset == 0 && bytesPerRow == lineStride) {
--            image = data;
--        } else {
--            image = new byte[bytesPerRow*height];
--            int dataOffset = colOffset / 8;
--            int imageOffset = 0;
--            for(int row = 0; row < height; row++) {
--                System.arraycopy(data, dataOffset, image, imageOffset,
--                                 bytesPerRow);
--                dataOffset += lineStride;
--                imageOffset += bytesPerRow;
--            }
--        }
--
--        // Attempt the codecLib encoder.
--        com.sun.medialib.codec.g4fax.Encoder clibEncoder =
--            (com.sun.medialib.codec.g4fax.Encoder)encoder;
--        //System.out.println("Using codecLib G4 encoder");
--
--        // Set encoding flags.
--        int encodingFlags = inverseFill ?
--            com.sun.medialib.codec.g4fax.Constants.G4FAX_LSB2MSB : 0;
--
--        int result =
--            com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE;
--        try {
--            if(DEBUG) {
--                System.out.println("Using MediaLib G4 encoder");
--            }
--            result = clibEncoder.encode(compData, image, width, height,
--                                        encodingFlags);
--        } catch(Throwable t) {
--            if(DEBUG) {
--                System.out.println("MediaLib G4 encoder failed: "+t);
--            }
--            // XXX Should write a warning to listeners here.
--            result = com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE;
--        }
--
--        // If the codecLib encoder failed, try the superclass.
--        if(result == com.sun.medialib.codec.g4fax.Constants.G4FAX_FAILURE) {
--            if(DEBUG) {
--                System.out.println("Falling back to Java G4 encoder");
--            }
--            result = super.encodeT6(data, lineStride, colOffset,
--                                    width, height, compData);
--        }
--
--        return result;
--    }
--}
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFImageReader.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFImageReader.java	2012-08-22 20:24:05.000000000 +0000
-+++ bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFImageReader.java	2012-09-20 08:16:06.732187619 +0000
-@@ -1263,23 +1263,6 @@
-                 }
-             } else if (compression ==
-                        BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) {
--
--                // Try to create the codecLib decompressor.
--                if(PackageUtil.isCodecLibAvailable()) {
--                    try {
--                        this.decompressor =
--                            new TIFFCodecLibFaxDecompressor(compression);
--                        if(DEBUG) {
--                            System.out.println
--                                ("Using codecLib T.6 decompressor");
--                        }
--                    } catch (RuntimeException re) {
--                        if(DEBUG) {
--                            System.out.println(re);
--                        }
--                    }
--                }
--
-                 // Fall back to the Java decompressor.
-                 if (this.decompressor == null) {
-                     if(DEBUG) {
-@@ -1289,23 +1272,6 @@
-                 }
-             } else if (compression ==
-                        BaselineTIFFTagSet.COMPRESSION_CCITT_T_4) {
--
--                if(PackageUtil.isCodecLibAvailable()) {
--                    // Try to create the codecLib decompressor.
--                    try {
--                        this.decompressor =
--                            new TIFFCodecLibFaxDecompressor(compression);
--                        if(DEBUG) {
--                            System.out.println
--                                ("Using codecLib T.4 decompressor");
--                        }
--                    } catch (RuntimeException re) {
--                        if(DEBUG) {
--                            System.out.println(re);
--                        }
--                    }
--                }
--
-                 // Fall back to the Java decompressor.
-                 if (this.decompressor == null) {
-                     if(DEBUG) {
-Index: bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFImageWriter.java
-===================================================================
---- bio-formats-4.4.2.orig/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFImageWriter.java	2012-08-22 20:24:05.000000000 +0000
-+++ bio-formats-4.4.2/components/forks/jai/src/com/sun/media/imageioimpl/plugins/tiff/TIFFImageWriter.java	2012-09-20 08:16:06.732187619 +0000
-@@ -877,20 +877,6 @@
- 
-         if (compressor == null) {
-             if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_RLE) {
--                if(PackageUtil.isCodecLibAvailable()) {
--                    try {
--                        compressor = new TIFFCodecLibRLECompressor();
--                        if(DEBUG) {
--                            System.out.println
--                                ("Using codecLib RLE compressor");
--                        }
--                    } catch(RuntimeException e) {
--                        if(DEBUG) {
--                            System.out.println(e);
--                        }
--                    }
--                }
--
-                 if(compressor == null) {
-                     compressor = new TIFFRLECompressor();
-                     if(DEBUG) {
-@@ -904,20 +890,6 @@
-                 }
-             } else if (compression ==
-                        BaselineTIFFTagSet.COMPRESSION_CCITT_T_4) {
--                if(PackageUtil.isCodecLibAvailable()) {
--                    try {
--                        compressor = new TIFFCodecLibT4Compressor();
--                        if(DEBUG) {
--                            System.out.println
--                                ("Using codecLib T.4 compressor");
--                        }
--                    } catch(RuntimeException e) {
--                        if(DEBUG) {
--                            System.out.println(e);
--                        }
--                    }
--                }
--
-                 if(compressor == null) {
-                     compressor = new TIFFT4Compressor();
-                     if(DEBUG) {
-@@ -931,20 +903,6 @@
-                 }
-             } else if (compression ==
-                        BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) {
--                if(PackageUtil.isCodecLibAvailable()) {
--                    try {
--                        compressor = new TIFFCodecLibT6Compressor();
--                        if(DEBUG) {
--                            System.out.println
--                                ("Using codecLib T.6 compressor");
--                        }
--                    } catch(RuntimeException e) {
--                        if(DEBUG) {
--                            System.out.println(e);
--                        }
--                    }
--                }
--
-                 if(compressor == null) {
-                     compressor = new TIFFT6Compressor();
-                     if(DEBUG) {
-Index: bio-formats-4.4.2/scan-deps.pl
-===================================================================
---- bio-formats-4.4.2.orig/scan-deps.pl	2012-08-22 20:24:05.000000000 +0000
-+++ bio-formats-4.4.2/scan-deps.pl	2012-09-20 08:16:06.732187619 +0000
-@@ -379,20 +379,6 @@
-   VERSION => "1.43o"
- );
- 
--my %jiio = (
--  NAME    => "jiio",
--  TITLE   => "JAI ImageIO wrapper",
--  JAR     => "clibwrapper_jiio.jar",
--  PACKAGE => "com.sun.medialib.codec",
--  LICENSE => "BSD",
--  URL     => "https://jai-imageio.dev.java.net/",
--  NOTES   => <<ZZ,
--used by Bio-Formats via reflection for JPEG2000 support (ND2, JP2) and lossless
--JPEG decompression (DICOM)
--ZZ
--  VERSION => "1.1"
--);
--
- my %junit = (
-   NAME    => "junit",
-   TITLE   => "JUnit",
-@@ -611,7 +597,6 @@
-   \%findbugs,
-   \%forms,
-   \%ij,
--  \%jiio,
-   \%junit,
-   \%log4j,
-   \%netcdf,

Modified: trunk/packages/bio-formats/trunk/debian/patches/remove_git.patch
===================================================================
--- trunk/packages/bio-formats/trunk/debian/patches/remove_git.patch	2012-11-24 16:56:30 UTC (rev 12568)
+++ trunk/packages/bio-formats/trunk/debian/patches/remove_git.patch	2012-11-24 19:44:25 UTC (rev 12569)
@@ -1,7 +1,7 @@
-Index: bio-formats-4.4.2/ant/common.xml
+Index: bioformats-4.4.5/ant/common.xml
 ===================================================================
---- bio-formats-4.4.2.orig/ant/common.xml	2012-08-22 20:24:05.000000000 +0000
-+++ bio-formats-4.4.2/ant/common.xml	2012-09-20 08:08:20.136204462 +0000
+--- bioformats-4.4.5.orig/ant/common.xml	2012-11-19 06:33:31.000000000 +0000
++++ bioformats-4.4.5/ant/common.xml	2012-11-24 18:01:33.920515328 +0000
 @@ -34,14 +34,14 @@
      <!-- check for Git versioning information -->
      <property name="git.path" value="${root.dir}/.git"/>
@@ -27,4 +27,4 @@
 +    </if-->
  
      <!-- set release version from repository URL -->
-     <property name="release.version" value="4.4.2"/>
+     <property name="release.version" value="4.4.5"/>

Modified: trunk/packages/bio-formats/trunk/debian/patches/series
===================================================================
--- trunk/packages/bio-formats/trunk/debian/patches/series	2012-11-24 16:56:30 UTC (rev 12568)
+++ trunk/packages/bio-formats/trunk/debian/patches/series	2012-11-24 19:44:25 UTC (rev 12569)
@@ -1,4 +1,3 @@
-remove_git.patch
-bla.patch
-b.patch
-bioformats-codeclib-removal.patch
+#remove_git.patch
+#bla.patch
+#b.patch

Modified: trunk/packages/bio-formats/trunk/debian/rules
===================================================================
--- trunk/packages/bio-formats/trunk/debian/rules	2012-11-24 16:56:30 UTC (rev 12568)
+++ trunk/packages/bio-formats/trunk/debian/rules	2012-11-24 19:44:25 UTC (rev 12569)
@@ -7,9 +7,16 @@
 %:
 	dh $@ --with javahelper
 
-override_dh_auto_build:
+override_dh_auto_build-arch:
 	-mkdir jar
 	ant $(ANT_OPTS) -f build.xml jar-autogen jar-common jar-formats jar-jai jar-loci-plugins jar-lwf-stubs jar-mdbtools jar-metakit jar-ome-xml jar-poi-loci
 
+# Let's be smart with building doc
+override_dh_auto_build-indep:
+	ant $(ANT_OPTS) -f build.xml docs
+
+# No tests needed for docs
+override_dh_auto_test-indep:
+
 get-orig-source:
-	uscan --verbose --force-download
+	uscan --verbose --force-download --rename

Modified: trunk/packages/bio-formats/trunk/debian/watch
===================================================================
--- trunk/packages/bio-formats/trunk/debian/watch	2012-11-24 16:56:30 UTC (rev 12568)
+++ trunk/packages/bio-formats/trunk/debian/watch	2012-11-24 19:44:25 UTC (rev 12569)
@@ -1,3 +1,3 @@
 version=3
-https://github.com/openmicroscopy/bioformats/tags .*/tarball/v(\d.\d.\d) \
+https://github.com/openmicroscopy/bioformats/tags .*/v(\d.\d.\d)\.tar\.gz \
 debian debian/orig-tar.sh




More information about the debian-med-commit mailing list