[med-svn] r12238 - in trunk/packages/bio-formats/trunk/debian: . patches
Mathieu Malaterre
malat at alioth.debian.org
Thu Sep 20 08:15:02 UTC 2012
Author: malat
Date: 2012-09-20 08:14:59 +0000 (Thu, 20 Sep 2012)
New Revision: 12238
Added:
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/patches/remove_git.patch
trunk/packages/bio-formats/trunk/debian/patches/series
Log:
Add rleigh patch
Modified: trunk/packages/bio-formats/trunk/debian/changelog
===================================================================
--- trunk/packages/bio-formats/trunk/debian/changelog 2012-09-20 04:41:18 UTC (rev 12237)
+++ trunk/packages/bio-formats/trunk/debian/changelog 2012-09-20 08:14:59 UTC (rev 12238)
@@ -1,4 +1,4 @@
-bio-formats (4.4.1-1) UNRELEASED; urgency=low
+bio-formats (4.4.2-1) UNRELEASED; urgency=low
* Initial Debian Upload (Closes: #641448)
Added: trunk/packages/bio-formats/trunk/debian/patches/bioformats-codeclib-removal.patch
===================================================================
--- trunk/packages/bio-formats/trunk/debian/patches/bioformats-codeclib-removal.patch (rev 0)
+++ trunk/packages/bio-formats/trunk/debian/patches/bioformats-codeclib-removal.patch 2012-09-20 08:14:59 UTC (rev 12238)
@@ -0,0 +1,14826 @@
+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:12:11.100196124 +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:12:11.100196124 +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:12:11.100196124 +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:12:11.100196124 +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:12:11.104196124 +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:12:11.112196124 +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:12:11.116196124 +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:12:11.120196124 +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:12:11.124196124 +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:12:11.124196124 +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,
+Index: bio-formats-4.4.2/ant/java.xml
+===================================================================
+--- bio-formats-4.4.2.orig/ant/java.xml 2012-09-20 08:08:29.748204115 +0000
++++ bio-formats-4.4.2/ant/java.xml 2012-09-20 08:08:32.356204021 +0000
+@@ -224,7 +224,7 @@
+ <!-- Internal build targets -->
+
+ <target name="init"
+- depends="init-title, init-timestamp, init-version, init-manifest-cp"/>
++ depends="init-title, init-timestamp, init-version"/>
+
+ <target name="init-manifest-cp">
+ <!-- construct manifest classpath -->
Modified: trunk/packages/bio-formats/trunk/debian/patches/remove_git.patch
===================================================================
--- trunk/packages/bio-formats/trunk/debian/patches/remove_git.patch 2012-09-20 04:41:18 UTC (rev 12237)
+++ trunk/packages/bio-formats/trunk/debian/patches/remove_git.patch 2012-09-20 08:14:59 UTC (rev 12238)
@@ -1,7 +1,7 @@
-Index: bio-formats-4.4.1/ant/common.xml
+Index: bio-formats-4.4.2/ant/common.xml
===================================================================
---- bio-formats-4.4.1.orig/ant/common.xml 2012-07-27 14:51:05.774868720 +0000
-+++ bio-formats-4.4.1/ant/common.xml 2012-07-27 14:51:08.738868615 +0000
+--- 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
@@ -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.1"/>
+ <property name="release.version" value="4.4.2"/>
Modified: trunk/packages/bio-formats/trunk/debian/patches/series
===================================================================
--- trunk/packages/bio-formats/trunk/debian/patches/series 2012-09-20 04:41:18 UTC (rev 12237)
+++ trunk/packages/bio-formats/trunk/debian/patches/series 2012-09-20 08:14:59 UTC (rev 12238)
@@ -2,3 +2,4 @@
bla.patch
b.patch
ij.patch
+bioformats-codeclib-removal.patch
More information about the debian-med-commit
mailing list