feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.IOException;
import javax.imageio.stream.ImageOutputStream;
/*
* Came from GIFEncoder initially.
* Modified - to allow for output compressed data without the block counts
* which breakup the compressed data stream for GIF.
*/
public class BitFile {
ImageOutputStream output;
byte buffer[];
int index;
int bitsLeft; // bits left at current index that are avail.
/** note this also indicates gif format BITFile. **/
boolean blocks = false;
/*
* @param output destination for output data
* @param blocks GIF LZW requires block counts for output data
*/
public BitFile(ImageOutputStream output, boolean blocks) {
this.output = output;
this.blocks = blocks;
buffer = new byte[256];
index = 0;
bitsLeft = 8;
}
public void flush() throws IOException {
int numBytes = index + (bitsLeft == 8 ? 0 : 1);
if (numBytes > 0) {
if (blocks) {
output.write(numBytes);
}
output.write(buffer, 0, numBytes);
buffer[0] = 0;
index = 0;
bitsLeft = 8;
}
}
public void writeBits(int bits, int numbits) throws IOException {
int bitsWritten = 0;
int numBytes = 255; // gif block count
do {
// This handles the GIF block count stuff
if ((index == 254 && bitsLeft == 0) || index > 254) {
if (blocks) {
output.write(numBytes);
}
output.write(buffer, 0, numBytes);
buffer[0] = 0;
index = 0;
bitsLeft = 8;
}
if (numbits <= bitsLeft) { // bits contents fit in current index byte
if (blocks) { // GIF
buffer[index] |= (bits & ((1 << numbits) - 1)) << (8 - bitsLeft);
bitsWritten += numbits;
bitsLeft -= numbits;
numbits = 0;
} else {
buffer[index] |= (bits & ((1 << numbits) - 1)) << (bitsLeft - numbits);
bitsWritten += numbits;
bitsLeft -= numbits;
numbits = 0;
}
} else { // bits overflow from current byte to next.
if (blocks) { // GIF
// if bits > space left in current byte then the lowest order bits
// of code are taken and put in current byte and rest put in next.
buffer[index] |= (bits & ((1 << bitsLeft) - 1)) << (8 - bitsLeft);
bitsWritten += bitsLeft;
bits >>= bitsLeft;
numbits -= bitsLeft;
buffer[++index] = 0;
bitsLeft = 8;
} else {
// if bits > space left in current byte then the highest order bits
// of code are taken and put in current byte and rest put in next.
// at highest order bit location !!
int topbits = (bits >>> (numbits - bitsLeft)) & ((1 << bitsLeft) - 1);
buffer[index] |= topbits;
numbits -= bitsLeft; // ok this many bits gone off the top
bitsWritten += bitsLeft;
buffer[++index] = 0; // next index
bitsLeft = 8;
}
}
} while (numbits != 0);
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.awt.color.ColorSpace;
/**
* A dummy <code>ColorSpace</code> to enable <code>ColorModel</code>
* for image data which do not have an innate color representation.
*/
public class BogusColorSpace extends ColorSpace {
/**
* Return the type given the number of components.
*
* @param numComponents The number of components in the
* <code>ColorSpace</code>.
* @exception IllegalArgumentException if <code>numComponents</code>
* is less than 1.
*/
private static int getType(int numComponents) {
if(numComponents < 1) {
throw new IllegalArgumentException("numComponents < 1!");
}
int type;
switch(numComponents) {
case 1:
type = ColorSpace.TYPE_GRAY;
break;
default:
// Based on the constant definitions TYPE_2CLR=12 through
// TYPE_FCLR=25. This will return unknown types for
// numComponents > 15.
type = numComponents + 10;
}
return type;
}
/**
* Constructs a bogus <code>ColorSpace</code>.
*
* @param numComponents The number of components in the
* <code>ColorSpace</code>.
* @exception IllegalArgumentException if <code>numComponents</code>
* is less than 1.
*/
public BogusColorSpace(int numComponents) {
super(getType(numComponents), numComponents);
}
//
// The following methods simply copy the input array to the
// output array while otherwise attempting to adhere to the
// specified behavior of the methods vis-a-vis exceptions.
//
public float[] toRGB(float[] colorvalue) {
if(colorvalue.length < getNumComponents()) {
throw new ArrayIndexOutOfBoundsException
("colorvalue.length < getNumComponents()");
}
float[] rgbvalue = new float[3];
System.arraycopy(colorvalue, 0, rgbvalue, 0,
Math.min(3, getNumComponents()));
return colorvalue;
}
public float[] fromRGB(float[] rgbvalue) {
if(rgbvalue.length < 3) {
throw new ArrayIndexOutOfBoundsException
("rgbvalue.length < 3");
}
float[] colorvalue = new float[getNumComponents()];
System.arraycopy(rgbvalue, 0, colorvalue, 0,
Math.min(3, colorvalue.length));
return rgbvalue;
}
public float[] toCIEXYZ(float[] colorvalue) {
if(colorvalue.length < getNumComponents()) {
throw new ArrayIndexOutOfBoundsException
("colorvalue.length < getNumComponents()");
}
float[] xyzvalue = new float[3];
System.arraycopy(colorvalue, 0, xyzvalue, 0,
Math.min(3, getNumComponents()));
return colorvalue;
}
public float[] fromCIEXYZ(float[] xyzvalue) {
if(xyzvalue.length < 3) {
throw new ArrayIndexOutOfBoundsException
("xyzvalue.length < 3");
}
float[] colorvalue = new float[getNumComponents()];
System.arraycopy(xyzvalue, 0, colorvalue, 0,
Math.min(3, colorvalue.length));
return xyzvalue;
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
public final class I18N extends I18NImpl {
private final static String resource_name = "iio-plugin.properties";
public static String getString(String key) {
return getString("com.sun.imageio.plugins.common.I18N", resource_name, key);
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.InputStream;
import java.util.PropertyResourceBundle;
import java.net.URL;
/**
* Class to simplify use of internationalization message strings.
* Property files are constructed in terms of content as for JAI with
* one "key=value" pair per line. All such files however have the same
* name "properties". The resource extractor resolves the extraction of
* the file from the jar as the package name is included automatically.
*
* <p>Extenders need only provide a static method
* <code>getString(String)</code> which calls the static method in this
* class with the name of the invoking class and returns a
* <code>String</code>.
*/
public class I18NImpl {
/**
* Returns the message string with the specified key from the
* "properties" file in the package containing the class with
* the specified name.
*/
protected static final String getString(String className, String resource_name, String key) {
PropertyResourceBundle bundle = null;
try {
InputStream stream =
Class.forName(className).getResourceAsStream(resource_name);
bundle = new PropertyResourceBundle(stream);
} catch(Throwable e) {
throw new RuntimeException(e); // Chain the exception.
}
return (String)bundle.handleGetObject(key);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.stream.ImageInputStream;
public class InputStreamAdapter extends InputStream {
ImageInputStream stream;
public InputStreamAdapter(ImageInputStream stream) {
super();
this.stream = stream;
}
public int read() throws IOException {
return stream.read();
}
public int read(byte b[], int off, int len) throws IOException {
return stream.read(b, off, len);
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.IOException;
import java.io.PrintStream;
import javax.imageio.stream.ImageOutputStream;
/*
* Modified from original LZWCompressor to change interface to passing a
* buffer of data to be compressed.
*/
public class LZWCompressor {
/** base underlying code size of data being compressed 8 for TIFF, 1 to 8 for GIF **/
int codeSize;
/** reserved clear code based on code size **/
int clearCode;
/** reserved end of data code based on code size **/
int endOfInfo;
/** current number bits output for each code **/
int numBits;
/** limit at which current number of bits code size has to be increased **/
int limit;
/** the prefix code which represents the predecessor string to current input point **/
short prefix;
/** output destination for bit codes **/
BitFile bf;
/** general purpose LZW string table **/
LZWStringTable lzss;
/** modify the limits of the code values in LZW encoding due to TIFF bug / feature **/
boolean tiffFudge;
/**
* @param out destination for compressed data
* @param codeSize the initial code size for the LZW compressor
* @param TIFF flag indicating that TIFF lzw fudge needs to be applied
* @exception IOException if underlying output stream error
**/
public LZWCompressor(ImageOutputStream out, int codeSize, boolean TIFF)
throws IOException
{
bf = new BitFile(out, !TIFF); // set flag for GIF as NOT tiff
this.codeSize = codeSize;
tiffFudge = TIFF;
clearCode = 1 << codeSize;
endOfInfo = clearCode + 1;
numBits = codeSize + 1;
limit = (1 << numBits) - 1;
if (tiffFudge) {
--limit;
}
prefix = (short)0xFFFF;
lzss = new LZWStringTable();
lzss.clearTable(codeSize);
bf.writeBits(clearCode, numBits);
}
/**
* @param buf data to be compressed to output stream
* @exception IOException if underlying output stream error
**/
public void compress(byte[] buf, int offset, int length)
throws IOException
{
int idx;
byte c;
short index;
int maxOffset = offset + length;
for (idx = offset; idx < maxOffset; ++idx) {
c = buf[idx];
if ((index = lzss.findCharString(prefix, c)) != -1) {
prefix = index;
} else {
bf.writeBits(prefix, numBits);
if (lzss.addCharString(prefix, c) > limit) {
if (numBits == 12) {
bf.writeBits(clearCode, numBits);
lzss.clearTable(codeSize);
numBits = codeSize + 1;
} else {
++numBits;
}
limit = (1 << numBits) - 1;
if (tiffFudge) {
--limit;
}
}
prefix = (short)((short)c & 0xFF);
}
}
}
/*
* Indicate to compressor that no more data to go so write out
* any remaining buffered data.
*
* @exception IOException if underlying output stream error
*/
public void flush() throws IOException {
if (prefix != -1) {
bf.writeBits(prefix, numBits);
}
bf.writeBits(endOfInfo, numBits);
bf.flush();
}
public void dump(PrintStream out) {
lzss.dump(out);
}
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.PrintStream;
/**
* General purpose LZW String Table.
* Extracted from GIFEncoder by Adam Doppelt
* Comments added by Robin Luiten
* <code>expandCode</code> added by Robin Luiten
* The strLen table to give quick access to the lenght of an expanded
* code for use by the <code>expandCode</code> method added by Robin.
**/
public class LZWStringTable {
/** codesize + Reserved Codes */
private final static int RES_CODES = 2;
private final static short HASH_FREE = (short)0xFFFF;
private final static short NEXT_FIRST = (short)0xFFFF;
private final static int MAXBITS = 12;
private final static int MAXSTR = (1 << MAXBITS);
private final static short HASHSIZE = 9973;
private final static short HASHSTEP = 2039;
byte[] strChr; // after predecessor character
short[] strNxt; // predecessor string
short[] strHsh; // hash table to find predecessor + char pairs
short numStrings; // next code if adding new prestring + char
/*
* each entry corresponds to a code and contains the length of data
* that the code expands to when decoded.
*/
int[] strLen;
/*
* Constructor allocate memory for string store data
*/
public LZWStringTable() {
strChr = new byte[MAXSTR];
strNxt = new short[MAXSTR];
strLen = new int[MAXSTR];
strHsh = new short[HASHSIZE];
}
/*
* @param index value of -1 indicates no predecessor [used in initialisation]
* @param b the byte [character] to add to the string store which follows
* the predecessor string specified the index.
* @return 0xFFFF if no space in table left for addition of predecesor
* index and byte b. Else return the code allocated for combination index + b.
*/
public int addCharString(short index, byte b) {
int hshidx;
if (numStrings >= MAXSTR) { // if used up all codes
return 0xFFFF;
}
hshidx = hash(index, b);
while (strHsh[hshidx] != HASH_FREE) {
hshidx = (hshidx + HASHSTEP) % HASHSIZE;
}
strHsh[hshidx] = numStrings;
strChr[numStrings] = b;
if (index == HASH_FREE) {
strNxt[numStrings] = NEXT_FIRST;
strLen[numStrings] = 1;
} else {
strNxt[numStrings] = index;
strLen[numStrings] = strLen[index] + 1;
}
return numStrings++; // return the code and inc for next code
}
/*
* @param index index to prefix string
* @param b the character that follws the index prefix
* @return b if param index is HASH_FREE. Else return the code
* for this prefix and byte successor
*/
public short findCharString(short index, byte b) {
int hshidx, nxtidx;
if (index == HASH_FREE) {
return (short)(b & 0xFF); // Rob fixed used to sign extend
}
hshidx = hash(index, b);
while ((nxtidx = strHsh[hshidx]) != HASH_FREE) { // search
if (strNxt[nxtidx] == index && strChr[nxtidx] == b) {
return (short)nxtidx;
}
hshidx = (hshidx + HASHSTEP) % HASHSIZE;
}
return (short)0xFFFF;
}
/*
* @param codesize the size of code to be preallocated for the
* string store.
*/
public void clearTable(int codesize) {
numStrings = 0;
for (int q = 0; q < HASHSIZE; q++) {
strHsh[q] = HASH_FREE;
}
int w = (1 << codesize) + RES_CODES;
for (int q = 0; q < w; q++) {
addCharString((short)0xFFFF, (byte)q); // init with no prefix
}
}
static public int hash(short index, byte lastbyte) {
return ((int)((short)(lastbyte << 8) ^ index) & 0xFFFF) % HASHSIZE;
}
/*
* If expanded data doesn't fit into array only what will fit is written
* to buf and the return value indicates how much of the expanded code has
* been written to the buf. The next call to expandCode() should be with
* the same code and have the skip parameter set the negated value of the
* previous return. Succesive negative return values should be negated and
* added together for next skip parameter value with same code.
*
* @param buf buffer to place expanded data into
* @param offset offset to place expanded data
* @param code the code to expand to the byte array it represents.
* PRECONDITION This code must already be in the LZSS
* @param skipHead is the number of bytes at the start of the expanded code to
* be skipped before data is written to buf. It is possible that skipHead is
* equal to codeLen.
* @return the length of data expanded into buf. If the expanded code is longer
* than space left in buf then the value returned is a negative number which when
* negated is equal to the number of bytes that were used of the code being expanded.
* This negative value also indicates the buffer is full.
*/
public int expandCode(byte[] buf, int offset, short code, int skipHead) {
if (offset == -2) {
if (skipHead == 1) {
skipHead = 0;
}
}
if (code == (short)0xFFFF || // just in case
skipHead == strLen[code]) // DONE no more unpacked
{
return 0;
}
int expandLen; // how much data we are actually expanding
int codeLen = strLen[code] - skipHead; // length of expanded code left
int bufSpace = buf.length - offset; // how much space left
if (bufSpace > codeLen) {
expandLen = codeLen; // only got this many to unpack
} else {
expandLen = bufSpace;
}
int skipTail = codeLen - expandLen; // only > 0 if codeLen > bufSpace [left overs]
int idx = offset + expandLen; // initialise to exclusive end address of buffer area
// NOTE: data unpacks in reverse direction and we are placing the
// unpacked data directly into the array in the correct location.
while ((idx > offset) && (code != (short)0xFFFF)) {
if (--skipTail < 0) { // skip required of expanded data
buf[--idx] = strChr[code];
}
code = strNxt[code]; // to predecessor code
}
if (codeLen > expandLen) {
return -expandLen; // indicate what part of codeLen used
} else {
return expandLen; // indicate length of dat unpacked
}
}
public void dump(PrintStream out) {
int i;
for (i = 258; i < numStrings; ++i) {
out.println(" strNxt[" + i + "] = " + strNxt[i]
+ " strChr " + Integer.toHexString(strChr[i] & 0xFF)
+ " strLen " + Integer.toHexString(strLen[i]));
}
}
}

View File

@@ -0,0 +1,486 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.awt.Color;
import javax.imageio.ImageTypeSpecifier;
/**
* This class implements the octree quantization method
* as it is described in the "Graphics Gems"
* (ISBN 0-12-286166-3, Chapter 4, pages 297-293)
*/
public class PaletteBuilder {
/**
* maximum of tree depth
*/
protected static final int MAXLEVEL = 8;
protected RenderedImage src;
protected ColorModel srcColorModel;
protected Raster srcRaster;
protected int requiredSize;
protected ColorNode root;
protected int numNodes;
protected int maxNodes;
protected int currLevel;
protected int currSize;
protected ColorNode[] reduceList;
protected ColorNode[] palette;
protected int transparency;
protected ColorNode transColor;
/**
* Creates an image representing given image
* <code>src</code> using <code>IndexColorModel</code>.
*
* Lossless conversion is not always possible (e.g. if number
* of colors in the given image exceeds maximum palette size).
* Result image then is an approximation constructed by octree
* quantization method.
*
* @exception IllegalArgumentException if <code>src</code> is
* <code>null</code>.
*
* @exception UnsupportedOperationException if implemented method
* is unable to create approximation of <code>src</code>
* and <code>canCreatePalette</code> returns <code>false</code>.
*
* @see createIndexColorModel
*
* @see canCreatePalette
*
*/
public static RenderedImage createIndexedImage(RenderedImage src) {
PaletteBuilder pb = new PaletteBuilder(src);
pb.buildPalette();
return pb.getIndexedImage();
}
/**
* Creates an palette representing colors from given image
* <code>img</code>. If number of colors in the given image exceeds
* maximum palette size closest colors would be merged.
*
* @exception IllegalArgumentException if <code>img</code> is
* <code>null</code>.
*
* @exception UnsupportedOperationException if implemented method
* is unable to create approximation of <code>img</code>
* and <code>canCreatePalette</code> returns <code>false</code>.
*
* @see createIndexedImage
*
* @see canCreatePalette
*
*/
public static IndexColorModel createIndexColorModel(RenderedImage img) {
PaletteBuilder pb = new PaletteBuilder(img);
pb.buildPalette();
return pb.getIndexColorModel();
}
/**
* Returns <code>true</code> if PaletteBuilder is able to create
* palette for given image type.
*
* @param type an instance of <code>ImageTypeSpecifier</code> to be
* indexed.
*
* @return <code>true</code> if the <code>PaletteBuilder</code>
* is likely to be able to create palette for this image type.
*
* @exception IllegalArgumentException if <code>type</code>
* is <code>null</code>.
*/
public static boolean canCreatePalette(ImageTypeSpecifier type) {
if (type == null) {
throw new IllegalArgumentException("type == null");
}
return true;
}
/**
* Returns <code>true</code> if PaletteBuilder is able to create
* palette for given rendered image.
*
* @param image an instance of <code>RenderedImage</code> to be
* indexed.
*
* @return <code>true</code> if the <code>PaletteBuilder</code>
* is likely to be able to create palette for this image type.
*
* @exception IllegalArgumentException if <code>image</code>
* is <code>null</code>.
*/
public static boolean canCreatePalette(RenderedImage image) {
if (image == null) {
throw new IllegalArgumentException("image == null");
}
ImageTypeSpecifier type = new ImageTypeSpecifier(image);
return canCreatePalette(type);
}
protected RenderedImage getIndexedImage() {
IndexColorModel icm = getIndexColorModel();
BufferedImage dst =
new BufferedImage(src.getWidth(), src.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED, icm);
WritableRaster wr = dst.getRaster();
for (int y =0; y < dst.getHeight(); y++) {
for (int x = 0; x < dst.getWidth(); x++) {
Color aColor = getSrcColor(x,y);
wr.setSample(x, y, 0, findColorIndex(root, aColor));
}
}
return dst;
}
protected PaletteBuilder(RenderedImage src) {
this(src, 256);
}
protected PaletteBuilder(RenderedImage src, int size) {
this.src = src;
this.srcColorModel = src.getColorModel();
this.srcRaster = src.getData();
this.transparency =
srcColorModel.getTransparency();
this.requiredSize = size;
}
private Color getSrcColor(int x, int y) {
int argb = srcColorModel.getRGB(srcRaster.getDataElements(x, y, null));
return new Color(argb, transparency != Transparency.OPAQUE);
}
protected int findColorIndex(ColorNode aNode, Color aColor) {
if (transparency != Transparency.OPAQUE &&
aColor.getAlpha() != 0xff)
{
return 0; // default transparnt pixel
}
if (aNode.isLeaf) {
return aNode.paletteIndex;
} else {
int childIndex = getBranchIndex(aColor, aNode.level);
return findColorIndex(aNode.children[childIndex], aColor);
}
}
protected void buildPalette() {
reduceList = new ColorNode[MAXLEVEL + 1];
for (int i = 0; i < reduceList.length; i++) {
reduceList[i] = null;
}
numNodes = 0;
maxNodes = 0;
root = null;
currSize = 0;
currLevel = MAXLEVEL;
/*
from the book
*/
int w = src.getWidth();
int h = src.getHeight();
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
Color aColor = getSrcColor(w - x - 1, h - y - 1);
/*
* If transparency of given image is not opaque we assume all
* colors with alpha less than 1.0 as fully transparent.
*/
if (transparency != Transparency.OPAQUE &&
aColor.getAlpha() != 0xff)
{
if (transColor == null) {
this.requiredSize --; // one slot for transparent color
transColor = new ColorNode();
transColor.isLeaf = true;
}
transColor = insertNode(transColor, aColor, 0);
} else {
root = insertNode(root, aColor, 0);
}
if (currSize > requiredSize) {
reduceTree();
}
}
}
}
protected ColorNode insertNode(ColorNode aNode, Color aColor, int aLevel) {
if (aNode == null) {
aNode = new ColorNode();
numNodes++;
if (numNodes > maxNodes) {
maxNodes = numNodes;
}
aNode.level = aLevel;
aNode.isLeaf = (aLevel > MAXLEVEL);
if (aNode.isLeaf) {
currSize++;
}
}
aNode.colorCount++;
aNode.red += aColor.getRed();
aNode.green += aColor.getGreen();
aNode.blue += aColor.getBlue();
if (!aNode.isLeaf) {
int branchIndex = getBranchIndex(aColor, aLevel);
if (aNode.children[branchIndex] == null) {
aNode.childCount++;
if (aNode.childCount == 2) {
aNode.nextReducible = reduceList[aLevel];
reduceList[aLevel] = aNode;
}
}
aNode.children[branchIndex] =
insertNode(aNode.children[branchIndex], aColor, aLevel + 1);
}
return aNode;
}
protected IndexColorModel getIndexColorModel() {
int size = currSize;
if (transColor != null) {
size ++; // we need place for transparent color;
}
byte[] red = new byte[size];
byte[] green = new byte[size];
byte[] blue = new byte[size];
int index = 0;
palette = new ColorNode[size];
if (transColor != null) {
index ++;
}
if (root != null) {
findPaletteEntry(root, index, red, green, blue);
}
IndexColorModel icm = null;
if (transColor != null) {
icm = new IndexColorModel(8, size, red, green, blue, 0);
} else {
icm = new IndexColorModel(8, currSize, red, green, blue);
}
return icm;
}
protected int findPaletteEntry(ColorNode aNode, int index,
byte[] red, byte[] green, byte[] blue)
{
if (aNode.isLeaf) {
red[index] = (byte)(aNode.red/aNode.colorCount);
green[index] = (byte)(aNode.green/aNode.colorCount);
blue[index] = (byte)(aNode.blue/aNode.colorCount);
aNode.paletteIndex = index;
palette[index] = aNode;
index++;
} else {
for (int i = 0; i < 8; i++) {
if (aNode.children[i] != null) {
index = findPaletteEntry(aNode.children[i], index,
red, green, blue);
}
}
}
return index;
}
protected int getBranchIndex(Color aColor, int aLevel) {
if (aLevel > MAXLEVEL || aLevel < 0) {
throw new IllegalArgumentException("Invalid octree node depth: " +
aLevel);
}
int shift = MAXLEVEL - aLevel;
int red_index = 0x1 & ((0xff & aColor.getRed()) >> shift);
int green_index = 0x1 & ((0xff & aColor.getGreen()) >> shift);
int blue_index = 0x1 & ((0xff & aColor.getBlue()) >> shift);
int index = (red_index << 2) | (green_index << 1) | blue_index;
return index;
}
protected void reduceTree() {
int level = reduceList.length - 1;
while (reduceList[level] == null && level >= 0) {
level--;
}
ColorNode thisNode = reduceList[level];
if (thisNode == null) {
// nothing to reduce
return;
}
// look for element with lower color count
ColorNode pList = thisNode;
int minColorCount = pList.colorCount;
int cnt = 1;
while (pList.nextReducible != null) {
if (minColorCount > pList.nextReducible.colorCount) {
thisNode = pList;
minColorCount = pList.colorCount;
}
pList = pList.nextReducible;
cnt++;
}
// save pointer to first reducible node
// NB: current color count for node could be changed in future
if (thisNode == reduceList[level]) {
reduceList[level] = thisNode.nextReducible;
} else {
pList = thisNode.nextReducible; // we need to process it
thisNode.nextReducible = pList.nextReducible;
thisNode = pList;
}
if (thisNode.isLeaf) {
return;
}
// reduce node
int leafChildCount = thisNode.getLeafChildCount();
thisNode.isLeaf = true;
currSize -= (leafChildCount - 1);
int aDepth = thisNode.level;
for (int i = 0; i < 8; i++) {
thisNode.children[i] = freeTree(thisNode.children[i]);
}
thisNode.childCount = 0;
}
protected ColorNode freeTree(ColorNode aNode) {
if (aNode == null) {
return null;
}
for (int i = 0; i < 8; i++) {
aNode.children[i] = freeTree(aNode.children[i]);
}
numNodes--;
return null;
}
/**
* The node of color tree.
*/
protected class ColorNode {
public boolean isLeaf;
public int childCount;
ColorNode[] children;
public int colorCount;
public long red;
public long blue;
public long green;
public int paletteIndex;
public int level;
ColorNode nextReducible;
public ColorNode() {
isLeaf = false;
level = 0;
childCount = 0;
children = new ColorNode[8];
for (int i = 0; i < 8; i++) {
children[i] = null;
}
colorCount = 0;
red = green = blue = 0;
paletteIndex = 0;
}
public int getLeafChildCount() {
if (isLeaf) {
return 0;
}
int cnt = 0;
for (int i = 0; i < children.length; i++) {
if (children[i] != null) {
if (children[i].isLeaf) {
cnt ++;
} else {
cnt += children[i].getLeafChildCount();
}
}
}
return cnt;
}
public int getRGB() {
int r = (int)red/colorCount;
int g = (int)green/colorCount;
int b = (int)blue/colorCount;
int c = 0xff << 24 | (0xff&r) << 16 | (0xff&g) << 8 | (0xff&b);
return c;
}
}
}

View File

@@ -0,0 +1,261 @@
/*
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import javax.imageio.stream.ImageInputStream;
/**
* This class contains utility methods that may be useful to ImageReader
* plugins. Ideally these methods would be in the ImageReader base class
* so that all subclasses could benefit from them, but that would be an
* addition to the existing API, and it is not yet clear whether these methods
* are universally useful, so for now we will leave them here.
*/
public class ReaderUtil {
// Helper for computeUpdatedPixels method
private static void computeUpdatedPixels(int sourceOffset,
int sourceExtent,
int destinationOffset,
int dstMin,
int dstMax,
int sourceSubsampling,
int passStart,
int passExtent,
int passPeriod,
int[] vals,
int offset)
{
// We need to satisfy the congruences:
// dst = destinationOffset + (src - sourceOffset)/sourceSubsampling
//
// src - passStart == 0 (mod passPeriod)
// src - sourceOffset == 0 (mod sourceSubsampling)
//
// subject to the inequalities:
//
// src >= passStart
// src < passStart + passExtent
// src >= sourceOffset
// src < sourceOffset + sourceExtent
// dst >= dstMin
// dst <= dstmax
//
// where
//
// dst = destinationOffset + (src - sourceOffset)/sourceSubsampling
//
// For now we use a brute-force approach although we could
// attempt to analyze the congruences. If passPeriod and
// sourceSubsamling are relatively prime, the period will be
// their product. If they share a common factor, either the
// period will be equal to the larger value, or the sequences
// will be completely disjoint, depending on the relationship
// between passStart and sourceOffset. Since we only have to do this
// twice per image (once each for X and Y), it seems cheap enough
// to do it the straightforward way.
boolean gotPixel = false;
int firstDst = -1;
int secondDst = -1;
int lastDst = -1;
for (int i = 0; i < passExtent; i++) {
int src = passStart + i*passPeriod;
if (src < sourceOffset) {
continue;
}
if ((src - sourceOffset) % sourceSubsampling != 0) {
continue;
}
if (src >= sourceOffset + sourceExtent) {
break;
}
int dst = destinationOffset +
(src - sourceOffset)/sourceSubsampling;
if (dst < dstMin) {
continue;
}
if (dst > dstMax) {
break;
}
if (!gotPixel) {
firstDst = dst; // Record smallest valid pixel
gotPixel = true;
} else if (secondDst == -1) {
secondDst = dst; // Record second smallest valid pixel
}
lastDst = dst; // Record largest valid pixel
}
vals[offset] = firstDst;
// If we never saw a valid pixel, set width to 0
if (!gotPixel) {
vals[offset + 2] = 0;
} else {
vals[offset + 2] = lastDst - firstDst + 1;
}
// The period is given by the difference of any two adjacent pixels
vals[offset + 4] = Math.max(secondDst - firstDst, 1);
}
/**
* A utility method that computes the exact set of destination
* pixels that will be written during a particular decoding pass.
* The intent is to simplify the work done by readers in combining
* the source region, source subsampling, and destination offset
* information obtained from the <code>ImageReadParam</code> with
* the offsets and periods of a progressive or interlaced decoding
* pass.
*
* @param sourceRegion a <code>Rectangle</code> containing the
* source region being read, offset by the source subsampling
* offsets, and clipped against the source bounds, as returned by
* the <code>getSourceRegion</code> method.
* @param destinationOffset a <code>Point</code> containing the
* coordinates of the upper-left pixel to be written in the
* destination.
* @param dstMinX the smallest X coordinate (inclusive) of the
* destination <code>Raster</code>.
* @param dstMinY the smallest Y coordinate (inclusive) of the
* destination <code>Raster</code>.
* @param dstMaxX the largest X coordinate (inclusive) of the destination
* <code>Raster</code>.
* @param dstMaxY the largest Y coordinate (inclusive) of the destination
* <code>Raster</code>.
* @param sourceXSubsampling the X subsampling factor.
* @param sourceYSubsampling the Y subsampling factor.
* @param passXStart the smallest source X coordinate (inclusive)
* of the current progressive pass.
* @param passYStart the smallest source Y coordinate (inclusive)
* of the current progressive pass.
* @param passWidth the width in pixels of the current progressive
* pass.
* @param passHeight the height in pixels of the current progressive
* pass.
* @param passPeriodX the X period (horizontal spacing between
* pixels) of the current progressive pass.
* @param passPeriodY the Y period (vertical spacing between
* pixels) of the current progressive pass.
*
* @return an array of 6 <code>int</code>s containing the
* destination min X, min Y, width, height, X period and Y period
* of the region that will be updated.
*/
public static int[] computeUpdatedPixels(Rectangle sourceRegion,
Point destinationOffset,
int dstMinX,
int dstMinY,
int dstMaxX,
int dstMaxY,
int sourceXSubsampling,
int sourceYSubsampling,
int passXStart,
int passYStart,
int passWidth,
int passHeight,
int passPeriodX,
int passPeriodY)
{
int[] vals = new int[6];
computeUpdatedPixels(sourceRegion.x, sourceRegion.width,
destinationOffset.x,
dstMinX, dstMaxX, sourceXSubsampling,
passXStart, passWidth, passPeriodX,
vals, 0);
computeUpdatedPixels(sourceRegion.y, sourceRegion.height,
destinationOffset.y,
dstMinY, dstMaxY, sourceYSubsampling,
passYStart, passHeight, passPeriodY,
vals, 1);
return vals;
}
public static int readMultiByteInteger(ImageInputStream iis)
throws IOException
{
int value = iis.readByte();
int result = value & 0x7f;
while((value & 0x80) == 0x80) {
result <<= 7;
value = iis.readByte();
result |= (value & 0x7f);
}
return result;
}
/**
* An utility method to allocate and initialize a byte array
* step by step with pre-defined limit, instead of allocating
* a large array up-front based on the length derived from
* an image header.
*
* @param iis a {@code ImageInputStream} to decode data and store
* it in byte array.
* @param length the size of data to decode
*
* @return array of size length when decode succeeeds
*
* @throws IOException if decoding of stream fails
*/
public static byte[] staggeredReadByteStream(ImageInputStream iis,
int length) throws IOException {
final int UNIT_SIZE = 1024000;
byte[] decodedData;
if (length < UNIT_SIZE) {
decodedData = new byte[length];
iis.readFully(decodedData, 0, length);
} else {
int bytesToRead = length;
int bytesRead = 0;
List<byte[]> bufs = new ArrayList<>();
while (bytesToRead != 0) {
int sz = Math.min(bytesToRead, UNIT_SIZE);
byte[] unit = new byte[sz];
iis.readFully(unit, 0, sz);
bufs.add(unit);
bytesRead += sz;
bytesToRead -= sz;
}
decodedData = new byte[bytesRead];
int copiedBytes = 0;
for (byte[] ba : bufs) {
System.arraycopy(ba, 0, decodedData, copiedBytes, ba.length);
copiedBytes += ba.length;
}
}
return decodedData;
}
}

View File

@@ -0,0 +1,499 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadataFormatImpl;
public class StandardMetadataFormat extends IIOMetadataFormatImpl {
// Utility method for nodes with a single attribute named "value"
private void addSingleAttributeElement(String elementName,
String parentName,
int dataType) {
addElement(elementName, parentName, CHILD_POLICY_EMPTY);
addAttribute(elementName, "value", dataType, true, null);
}
public StandardMetadataFormat() {
super(standardMetadataFormatName, CHILD_POLICY_SOME);
List values;
// root -> Chroma
addElement("Chroma", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Chroma -> ColorSpaceType
addElement("ColorSpaceType", "Chroma",
CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("XYZ");
values.add("Lab");
values.add("Luv");
values.add("YCbCr");
values.add("Yxy");
values.add("YCCK");
values.add("PhotoYCC");
values.add("RGB");
values.add("GRAY");
values.add("HSV");
values.add("HLS");
values.add("CMYK");
values.add("CMY");
values.add("2CLR");
values.add("3CLR");
values.add("4CLR");
values.add("5CLR");
values.add("6CLR");
values.add("7CLR");
values.add("8CLR");
values.add("9CLR");
values.add("ACLR");
values.add("BCLR");
values.add("CCLR");
values.add("DCLR");
values.add("ECLR");
values.add("FCLR");
addAttribute("ColorSpaceType",
"name",
DATATYPE_STRING,
true,
null,
values);
// root -> Chroma -> NumChannels
addElement("NumChannels", "Chroma",
CHILD_POLICY_EMPTY);
addAttribute("NumChannels", "value",
DATATYPE_INTEGER,
true,
0, Integer.MAX_VALUE);
// root -> Chroma -> Gamma
addElement("Gamma", "Chroma", CHILD_POLICY_EMPTY);
addAttribute("Gamma", "value",
DATATYPE_FLOAT, true, null);
// root -> Chroma -> BlackIsZero
addElement("BlackIsZero", "Chroma", CHILD_POLICY_EMPTY);
addBooleanAttribute("BlackIsZero", "value", true, true);
// root -> Chroma -> Palette
addElement("Palette", "Chroma", 0, Integer.MAX_VALUE);
// root -> Chroma -> PaletteEntry
addElement("PaletteEntry", "Palette", CHILD_POLICY_EMPTY);
addAttribute("PaletteEntry", "index", DATATYPE_INTEGER,
true, null);
addAttribute("PaletteEntry", "red", DATATYPE_INTEGER,
true, null);
addAttribute("PaletteEntry", "green", DATATYPE_INTEGER,
true, null);
addAttribute("PaletteEntry", "blue", DATATYPE_INTEGER,
true, null);
addAttribute("PaletteEntry", "alpha", DATATYPE_INTEGER,
false, "255");
// root -> Chroma -> BackgroundIndex
addElement("BackgroundIndex", "Chroma", CHILD_POLICY_EMPTY);
addAttribute("BackgroundIndex", "value", DATATYPE_INTEGER,
true, null);
// root -> Chroma -> BackgroundColor
addElement("BackgroundColor", "Chroma", CHILD_POLICY_EMPTY);
addAttribute("BackgroundColor", "red", DATATYPE_INTEGER,
true, null);
addAttribute("BackgroundColor", "green", DATATYPE_INTEGER,
true, null);
addAttribute("BackgroundColor", "blue", DATATYPE_INTEGER,
true, null);
// root -> Compression
addElement("Compression", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Compression -> CompressionTypeName
addSingleAttributeElement("CompressionTypeName",
"Compression",
DATATYPE_STRING);
// root -> Compression -> Lossless
addElement("Lossless", "Compression", CHILD_POLICY_EMPTY);
addBooleanAttribute("Lossless", "value", true, true);
// root -> Compression -> NumProgressiveScans
addSingleAttributeElement("NumProgressiveScans",
"Compression",
DATATYPE_INTEGER);
// root -> Compression -> BitRate
addSingleAttributeElement("BitRate",
"Compression",
DATATYPE_FLOAT);
// root -> Data
addElement("Data", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Data -> PlanarConfiguration
addElement("PlanarConfiguration", "Data", CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("PixelInterleaved");
values.add("PlaneInterleaved");
values.add("LineInterleaved");
values.add("TileInterleaved");
addAttribute("PlanarConfiguration", "value",
DATATYPE_STRING,
true,
null,
values);
// root -> Data -> SampleFormat
addElement("SampleFormat", "Data", CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("SignedIntegral");
values.add("UnsignedIntegral");
values.add("Real");
values.add("Index");
addAttribute("SampleFormat", "value",
DATATYPE_STRING,
true,
null,
values);
// root -> Data -> BitsPerSample
addElement("BitsPerSample", "Data",
CHILD_POLICY_EMPTY);
addAttribute("BitsPerSample", "value",
DATATYPE_INTEGER,
true,
1, Integer.MAX_VALUE);
// root -> Data -> SignificantBitsPerSample
addElement("SignificantBitsPerSample", "Data", CHILD_POLICY_EMPTY);
addAttribute("SignificantBitsPerSample", "value",
DATATYPE_INTEGER,
true,
1, Integer.MAX_VALUE);
// root -> Data -> SampleMSB
addElement("SampleMSB", "Data",
CHILD_POLICY_EMPTY);
addAttribute("SampleMSB", "value",
DATATYPE_INTEGER,
true,
1, Integer.MAX_VALUE);
// root -> Dimension
addElement("Dimension", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Dimension -> PixelAspectRatio
addSingleAttributeElement("PixelAspectRatio",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> ImageOrientation
addElement("ImageOrientation", "Dimension",
CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("Normal");
values.add("Rotate90");
values.add("Rotate180");
values.add("Rotate270");
values.add("FlipH");
values.add("FlipV");
values.add("FlipHRotate90");
values.add("FlipVRotate90");
addAttribute("ImageOrientation", "value",
DATATYPE_STRING,
true,
null,
values);
// root -> Dimension -> HorizontalPixelSize
addSingleAttributeElement("HorizontalPixelSize",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> VerticalPixelSize
addSingleAttributeElement("VerticalPixelSize",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> HorizontalPhysicalPixelSpacing
addSingleAttributeElement("HorizontalPhysicalPixelSpacing",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> VerticalPhysicalPixelSpacing
addSingleAttributeElement("VerticalPhysicalPixelSpacing",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> HorizontalPosition
addSingleAttributeElement("HorizontalPosition",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> VerticalPosition
addSingleAttributeElement("VerticalPosition",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> HorizontalPixelOffset
addSingleAttributeElement("HorizontalPixelOffset",
"Dimension",
DATATYPE_INTEGER);
// root -> Dimension -> VerticalPixelOffset
addSingleAttributeElement("VerticalPixelOffset",
"Dimension",
DATATYPE_INTEGER);
// root -> Dimension -> HorizontalScreenSize
addSingleAttributeElement("HorizontalScreenSize",
"Dimension",
DATATYPE_INTEGER);
// root -> Dimension -> VerticalScreenSize
addSingleAttributeElement("VerticalScreenSize",
"Dimension",
DATATYPE_INTEGER);
// root -> Document
addElement("Document", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Document -> FormatVersion
addElement("FormatVersion", "Document",
CHILD_POLICY_EMPTY);
addAttribute("FormatVersion", "value",
DATATYPE_STRING,
true,
null);
// root -> Document -> SubimageInterpretation
addElement("SubimageInterpretation", "Document",
CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("Standalone");
values.add("SinglePage");
values.add("FullResolution");
values.add("ReducedResolution");
values.add("PyramidLayer");
values.add("Preview");
values.add("VolumeSlice");
values.add("ObjectView");
values.add("Panorama");
values.add("AnimationFrame");
values.add("TransparencyMask");
values.add("CompositingLayer");
values.add("SpectralSlice");
values.add("Unknown");
addAttribute("SubimageInterpretation", "value",
DATATYPE_STRING,
true,
null,
values);
// root -> Document -> ImageCreationTime
addElement("ImageCreationTime", "Document",
CHILD_POLICY_EMPTY);
addAttribute("ImageCreationTime", "year",
DATATYPE_INTEGER,
true,
null);
addAttribute("ImageCreationTime", "month",
DATATYPE_INTEGER,
true,
null,
"1", "12", true, true);
addAttribute("ImageCreationTime", "day",
DATATYPE_INTEGER,
true,
null,
"1", "31", true, true);
addAttribute("ImageCreationTime", "hour",
DATATYPE_INTEGER,
false,
"0",
"0", "23", true, true);
addAttribute("ImageCreationTime", "minute",
DATATYPE_INTEGER,
false,
"0",
"0", "59", true, true);
// second = 60 denotes leap second
addAttribute("ImageCreationTime", "second",
DATATYPE_INTEGER,
false,
"0",
"0", "60", true, true);
// root -> Document -> ImageModificationTime
addElement("ImageModificationTime", "Document",
CHILD_POLICY_EMPTY);
addAttribute("ImageModificationTime", "year",
DATATYPE_INTEGER,
true,
null);
addAttribute("ImageModificationTime", "month",
DATATYPE_INTEGER,
true,
null,
"1", "12", true, true);
addAttribute("ImageModificationTime", "day",
DATATYPE_INTEGER,
true,
null,
"1", "31", true, true);
addAttribute("ImageModificationTime", "hour",
DATATYPE_INTEGER,
false,
"0",
"0", "23", true, true);
addAttribute("ImageModificationTime", "minute",
DATATYPE_INTEGER,
false,
"0",
"0", "59", true, true);
// second = 60 denotes leap second
addAttribute("ImageModificationTime", "second",
DATATYPE_INTEGER,
false,
"0",
"0", "60", true, true);
// root -> Text
addElement("Text", standardMetadataFormatName,
0, Integer.MAX_VALUE);
// root -> Text -> TextEntry
addElement("TextEntry", "Text", CHILD_POLICY_EMPTY);
addAttribute("TextEntry", "keyword",
DATATYPE_STRING,
false,
null);
addAttribute("TextEntry", "value",
DATATYPE_STRING,
true,
null);
addAttribute("TextEntry", "language",
DATATYPE_STRING,
false,
null);
addAttribute("TextEntry", "encoding",
DATATYPE_STRING,
false,
null);
values = new ArrayList();
values.add("none");
values.add("lzw");
values.add("zip");
values.add("bzip");
values.add("other");
addAttribute("TextEntry", "compression",
DATATYPE_STRING,
false,
"none",
values);
// root -> Transparency
addElement("Transparency", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Transparency -> Alpha
addElement("Alpha", "Transparency", CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("none");
values.add("premultiplied");
values.add("nonpremultiplied");
addAttribute("Alpha", "value",
DATATYPE_STRING,
false,
"none",
values);
// root -> Transparency -> TransparentIndex
addSingleAttributeElement("TransparentIndex", "Transparency",
DATATYPE_INTEGER);
// root -> Transparency -> TransparentColor
addElement("TransparentColor", "Transparency",
CHILD_POLICY_EMPTY);
addAttribute("TransparentColor", "value",
DATATYPE_INTEGER,
true,
0, Integer.MAX_VALUE);
// root -> Transparency -> TileTransparencies
addElement("TileTransparencies", "Transparency",
0, Integer.MAX_VALUE);
// root -> Transparency -> TileTransparencies -> TransparentTile
addElement("TransparentTile", "TileTransparencies",
CHILD_POLICY_EMPTY);
addAttribute("TransparentTile", "x",
DATATYPE_INTEGER,
true,
null);
addAttribute("TransparentTile", "y",
DATATYPE_INTEGER,
true,
null);
// root -> Transparency -> TileOpacities
addElement("TileOpacities", "Transparency",
0, Integer.MAX_VALUE);
// root -> Transparency -> TileOpacities -> OpaqueTile
addElement("OpaqueTile", "TileOpacities",
CHILD_POLICY_EMPTY);
addAttribute("OpaqueTile", "x",
DATATYPE_INTEGER,
true,
null);
addAttribute("OpaqueTile", "y",
DATATYPE_INTEGER,
true,
null);
}
public boolean canNodeAppear(String elementName,
ImageTypeSpecifier imageType) {
return true;
}
}

View File

@@ -0,0 +1,210 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.util.ListResourceBundle;
public class StandardMetadataFormatResources extends ListResourceBundle {
public StandardMetadataFormatResources() {}
protected Object[][] getContents() {
return new Object[][] {
// Node name, followed by description, or
// Node name + "/" + AttributeName, followed by description
{ "Chroma", "Chroma (color) information" },
{ "ColorSpaceType", "The raw color space of the image" },
{ "NumChannels",
"The number of channels in the raw image, including alpha" },
{ "Gamma", "The image gamma" },
{ "BlackIsZero",
"True if smaller values represent darker shades"},
{ "Palette", "Palette-color information" },
{ "PaletteEntry", "A palette entry" },
{ "PaletteEntry/index", "The index of the palette entry" },
{ "PaletteEntry/red", "The red value for the palette entry" },
{ "PaletteEntry/green", "The green value for the palette entry" },
{ "PaletteEntry/blue", "The blue value for the palette entry" },
{ "PaletteEntry/alpha", "The alpha value for the palette entry" },
{ "BackgroundIndex", "A palette index to be used as a background" },
{ "BackgroundColor", "An RGB triple to be used as a background" },
{ "BackgroundColor/red", "The red background value" },
{ "BackgroundColor/green", "The green background value" },
{ "BackgroundColor/blue", "The blue background value" },
{ "Compression", "Compression information" },
{ "CompressionTypeName", "The name of the compression scheme in use" },
{ "Lossless",
"True if the compression scheme is lossless" },
{ "BitRate", "The estimated bit rate of the compression scheme" },
{ "NumProgressiveScans",
"The number of progressive scans used in the image encoding"},
{ "Data", "Information on the image layout" },
{ "PlanarConfiguration",
"The organization of image samples in the stream" },
{ "SampleFormat", "The numeric format of image samples" },
{ "BitsPerSample", "The number of bits per sample"},
{ "BitsPerSample/value",
"A list of integers, one per channel" },
{ "SignificantBitsPerSample",
"The number of significant bits per sample"},
{ "SignificantBitsPerSample/value",
"A list of integers, one per channel" },
{ "SampleMSB",
"The position of the most significant bit of each sample"},
{ "SampleMSB/value",
"A list of integers, one per channel" },
{ "Dimension", "Dimension information" },
{ "PixelAspectRatio", "The width of a pixel divided by its height" },
{ "ImageOrientation", "The desired orientation of the image in terms of flips and counter-clockwise rotations" },
{ "HorizontalPixelSize",
"The width of a pixel, in millimeters, as it should be rendered on media" },
{ "VerticalPixelSize",
"The height of a pixel, in millimeters, as it should be rendered on media" },
{ "HorizontalPhysicalPixelSpacing",
"The horizontal distance in the subject of the image, in millimeters, represented by one pixel at the center of the image" },
{ "VerticalPhysicalPixelSpacing",
"The vertical distance in the subject of the image, in millimeters, represented by one pixel at the center of the image" },
{ "HorizontalPosition",
"The horizontal position, in millimeters, where the image should be rendered on media " },
{ "VerticalPosition",
"The vertical position, in millimeters, where the image should be rendered on media " },
{ "HorizontalPixelOffset",
"The horizontal position, in pixels, where the image should be rendered onto a raster display" },
{ "VerticalPixelOffset",
"The vertical position, in pixels, where the image should be rendered onto a raster display" },
{ "HorizontalScreenSize",
"The width, in pixels, of the raster display into which the image should be rendered" },
{ "VerticalScreenSize",
"The height, in pixels, of the raster display into which the image should be rendered" },
{ "Document", "Document information" },
{ "FormatVersion",
"The version of the format used by the stream" },
{ "SubimageInterpretation",
"The interpretation of this image in relation to the other images stored in the same stream" },
{ "ImageCreationTime", "The time of image creation" },
{ "ImageCreationTime/year",
"The full year (e.g., 1967, not 67)" },
{ "ImageCreationTime/month",
"The month, with January = 1" },
{ "ImageCreationTime/day",
"The day of the month" },
{ "ImageCreationTime/hour",
"The hour from 0 to 23" },
{ "ImageCreationTime/minute",
"The minute from 0 to 59" },
{ "ImageCreationTime/second",
"The second from 0 to 60 (60 = leap second)" },
{ "ImageModificationTime", "The time of the last image modification" },
{ "ImageModificationTime/year",
"The full year (e.g., 1967, not 67)" },
{ "ImageModificationTime/month",
"The month, with January = 1" },
{ "ImageModificationTime/day",
"The day of the month" },
{ "ImageModificationTime/hour",
"The hour from 0 to 23" },
{ "ImageModificationTime/minute",
"The minute from 0 to 59" },
{ "ImageModificationTime/second",
"The second from 0 to 60 (60 = leap second)" },
{ "Text", "Text information" },
{ "TextEntry", "A text entry"},
{ "TextEntry/keyword", "A keyword associated with the text entry" },
{ "TextEntry/value", "the text entry" },
{ "TextEntry/language", "The language of the text" },
{ "TextEntry/encoding", "The encoding of the text" },
{ "TextEntry/compression", "The method used to compress the text" },
{ "Transparency", "Transparency information" },
{ "Alpha", "The type of alpha information contained in the image" },
{ "TransparentIndex", "A palette index to be treated as transparent" },
{ "TransparentColor", "An RGB color to be treated as transparent" },
{ "TransparentColor/red",
"The red channel of the transparent color" },
{ "TransparentColor/green",
"The green channel of the transparent color" },
{ "TransparentColor/blue",
"The blue channel of the transparent color" },
{ "TileTransparencies", "A list of completely transparent tiles" },
{ "TransparentTile", "The index of a completely transparent tile" },
{ "TransparentTile/x", "The tile's X index" },
{ "TransparentTile/y", "The tile's Y index" },
{ "TileOpacities", "A list of completely opaque tiles" },
{ "OpaqueTile", "The index of a completely opaque tile" },
{ "OpaqueTile/x", "The tile's X index" },
{ "OpaqueTile/y", "The tile's Y index" },
};
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.IOException;
import javax.imageio.stream.ImageInputStreamImpl;
import javax.imageio.stream.ImageInputStream;
public final class SubImageInputStream extends ImageInputStreamImpl {
ImageInputStream stream;
long startingPos;
int startingLength;
int length;
public SubImageInputStream(ImageInputStream stream, int length)
throws IOException {
this.stream = stream;
this.startingPos = stream.getStreamPosition();
this.startingLength = this.length = length;
}
public int read() throws IOException {
if (length == 0) { // Local EOF
return -1;
} else {
--length;
return stream.read();
}
}
public int read(byte[] b, int off, int len) throws IOException {
if (length == 0) { // Local EOF
return -1;
}
len = Math.min(len, length);
int bytes = stream.read(b, off, len);
length -= bytes;
return bytes;
}
public long length() {
return startingLength;
}
public void seek(long pos) throws IOException {
stream.seek(pos - startingPos);
streamPos = pos;
}
protected void finalize() throws Throwable {
// Empty finalizer (for improved performance; no need to call
// super.finalize() in this case)
}
}