/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/**
* A class that allows the format of an image (in particular, its
* <code>SampleModel</code> and <code>ColorModel</code>) to be
* specified in a convenient manner.
*
*/
public class ImageTypeSpecifier {
/**
* The <code>ColorModel</code> to be used as a prototype.
*/
/**
* A <code>SampleModel</code> to be used as a prototype.
*/
/**
* Cached specifiers for all of the standard
* <code>BufferedImage</code> types.
*/
// Initialize the standard specifiers
static {
}
/**
* A constructor to be used by inner subclasses only.
*/
private ImageTypeSpecifier() {}
/**
* Constructs an <code>ImageTypeSpecifier</code> directly
* from a <code>ColorModel</code> and a <code>SampleModel</code>.
* It is the caller's responsibility to supply compatible
* parameters.
*
* @param colorModel a <code>ColorModel</code>.
* @param sampleModel a <code>SampleModel</code>.
*
* @exception IllegalArgumentException if either parameter is
* <code>null</code>.
* @exception IllegalArgumentException if <code>sampleModel</code>
* is not compatible with <code>colorModel</code>.
*/
if (colorModel == null) {
throw new IllegalArgumentException("colorModel == null!");
}
if (sampleModel == null) {
throw new IllegalArgumentException("sampleModel == null!");
}
throw new IllegalArgumentException
("sampleModel is incompatible with colorModel!");
}
this.colorModel = colorModel;
this.sampleModel = sampleModel;
}
/**
* Constructs an <code>ImageTypeSpecifier</code> from a
* <code>RenderedImage</code>. If a <code>BufferedImage</code> is
* being used, one of the factory methods
* <code>createFromRenderedImage</code> or
* <code>createFromBufferedImageType</code> should be used instead in
* order to get a more accurate result.
*
* @param image a <code>RenderedImage</code>.
*
* @exception IllegalArgumentException if the argument is
* <code>null</code>.
*/
throw new IllegalArgumentException("image == null!");
}
}
// Packed
int redMask;
int greenMask;
int blueMask;
int alphaMask;
int transferType;
boolean isAlphaPremultiplied;
int redMask,
int greenMask,
int blueMask,
int alphaMask, // 0 if no alpha
int transferType,
boolean isAlphaPremultiplied) {
if (colorSpace == null) {
throw new IllegalArgumentException("colorSpace == null!");
}
throw new IllegalArgumentException
("colorSpace is not of type TYPE_RGB!");
}
throw new IllegalArgumentException
("Bad value for transferType!");
}
throw new IllegalArgumentException
("No mask has at least 1 bit set!");
}
this.colorSpace = colorSpace;
this.transferType = transferType;
int bits = 32;
this.colorModel =
bits,
}
}
/**
* Returns a specifier for a packed image format that will use a
* <code>DirectColorModel</code> and a packed
* <code>SampleModel</code> to store each pixel packed into in a
* single byte, short, or int.
*
* @param colorSpace the desired <code>ColorSpace</code>.
* @param redMask a contiguous mask indicated the position of the
* red channel.
* @param greenMask a contiguous mask indicated the position of the
* green channel.
* @param blueMask a contiguous mask indicated the position of the
* blue channel.
* @param alphaMask a contiguous mask indicated the position of the
* alpha channel.
* @param transferType the desired <code>SampleModel</code> transfer type.
* @param isAlphaPremultiplied <code>true</code> if the color channels
* will be premultipled by the alpha channel.
*
* @return an <code>ImageTypeSpecifier</code> with the desired
* characteristics.
*
* @exception IllegalArgumentException if <code>colorSpace</code>
* is <code>null</code>.
* @exception IllegalArgumentException if <code>colorSpace</code>
* is not of type <code>TYPE_RGB</code>.
* @exception IllegalArgumentException if no mask has at least 1
* bit set.
* @exception IllegalArgumentException if
* <code>transferType</code> if not one of
* <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_USHORT</code>, or
* <code>DataBuffer.TYPE_INT</code>.
*/
public static ImageTypeSpecifier
int redMask,
int greenMask,
int blueMask,
int alphaMask, // 0 if no alpha
int transferType,
boolean isAlphaPremultiplied) {
alphaMask, // 0 if no alpha
}
int numBands,
int dataType,
boolean hasAlpha,
boolean isAlphaPremultiplied) {
int transparency =
for (int i = 0; i < numBands; i++) {
}
return new ComponentColorModel(colorSpace,
dataType);
}
// Interleaved
int[] bandOffsets;
int dataType;
boolean hasAlpha;
boolean isAlphaPremultiplied;
int[] bandOffsets,
int dataType,
boolean hasAlpha,
boolean isAlphaPremultiplied) {
if (colorSpace == null) {
throw new IllegalArgumentException("colorSpace == null!");
}
if (bandOffsets == null) {
throw new IllegalArgumentException("bandOffsets == null!");
}
throw new IllegalArgumentException
("bandOffsets.length is wrong!");
}
throw new IllegalArgumentException
("Bad value for dataType!");
}
this.colorSpace = colorSpace;
this.colorModel =
int maxBandOffset = minBandOffset;
int offset = bandOffsets[i];
}
int w = 1;
int h = 1;
this.sampleModel =
w, h,
w*pixelStride,
}
if ((o == null) ||
!(o instanceof ImageTypeSpecifier.Interleaved)) {
return false;
}
return false;
}
return false;
}
}
return true;
}
public int hashCode() {
return (super.hashCode() +
(25 * dataType) +
}
}
/**
* Returns a specifier for an interleaved image format that will
* use a <code>ComponentColorModel</code> and a
* <code>PixelInterleavedSampleModel</code> to store each pixel
* component in a separate byte, short, or int.
*
* @param colorSpace the desired <code>ColorSpace</code>.
* @param bandOffsets an array of <code>int</code>s indicating the
* offsets for each band.
* @param dataType the desired data type, as one of the enumerations
* from the <code>DataBuffer</code> class.
* @param hasAlpha <code>true</code> if an alpha channel is desired.
* @param isAlphaPremultiplied <code>true</code> if the color channels
* will be premultipled by the alpha channel.
*
* @return an <code>ImageTypeSpecifier</code> with the desired
* characteristics.
*
* @exception IllegalArgumentException if <code>colorSpace</code>
* is <code>null</code>.
* @exception IllegalArgumentException if <code>bandOffsets</code>
* is <code>null</code>.
* @exception IllegalArgumentException if <code>dataType</code> is
* not one of the legal <code>DataBuffer.TYPE_*</code> constants.
* @exception IllegalArgumentException if
* <code>bandOffsets.length</code> does not equal the number of
* color space components, plus 1 if <code>hasAlpha</code> is
* <code>true</code>.
*/
public static ImageTypeSpecifier
int[] bandOffsets,
int dataType,
boolean hasAlpha,
boolean isAlphaPremultiplied) {
}
// Banded
int[] bankIndices;
int[] bandOffsets;
int dataType;
boolean hasAlpha;
boolean isAlphaPremultiplied;
int[] bankIndices,
int[] bandOffsets,
int dataType,
boolean hasAlpha,
boolean isAlphaPremultiplied) {
if (colorSpace == null) {
throw new IllegalArgumentException("colorSpace == null!");
}
if (bankIndices == null) {
throw new IllegalArgumentException("bankIndices == null!");
}
if (bandOffsets == null) {
throw new IllegalArgumentException("bandOffsets == null!");
}
throw new IllegalArgumentException
("bankIndices.length != bandOffsets.length!");
}
throw new IllegalArgumentException
("Bad value for dataType!");
}
throw new IllegalArgumentException
("bandOffsets.length is wrong!");
}
this.colorSpace = colorSpace;
this.colorModel =
int w = 1;
int h = 1;
w, h,
w,
}
if ((o == null) ||
!(o instanceof ImageTypeSpecifier.Banded)) {
return false;
}
return false;
}
return false;
}
}
return false;
}
}
return true;
}
public int hashCode() {
return (super.hashCode() +
(21 * dataType) +
}
}
/**
* Returns a specifier for a banded image format that will use a
* <code>ComponentColorModel</code> and a
* <code>BandedSampleModel</code> to store each channel in a
* separate array.
*
* @param colorSpace the desired <code>ColorSpace</code>.
* @param bankIndices an array of <code>int</code>s indicating the
* bank in which each band will be stored.
* @param bandOffsets an array of <code>int</code>s indicating the
* starting offset of each band within its bank.
* @param dataType the desired data type, as one of the enumerations
* from the <code>DataBuffer</code> class.
* @param hasAlpha <code>true</code> if an alpha channel is desired.
* @param isAlphaPremultiplied <code>true</code> if the color channels
* will be premultipled by the alpha channel.
*
* @return an <code>ImageTypeSpecifier</code> with the desired
* characteristics.
*
* @exception IllegalArgumentException if <code>colorSpace</code>
* is <code>null</code>.
* @exception IllegalArgumentException if <code>bankIndices</code>
* is <code>null</code>.
* @exception IllegalArgumentException if <code>bandOffsets</code>
* is <code>null</code>.
* @exception IllegalArgumentException if the lengths of
* <code>bankIndices</code> and <code>bandOffsets</code> differ.
* @exception IllegalArgumentException if
* <code>bandOffsets.length</code> does not equal the number of
* color space components, plus 1 if <code>hasAlpha</code> is
* <code>true</code>.
* @exception IllegalArgumentException if <code>dataType</code> is
* not one of the legal <code>DataBuffer.TYPE_*</code> constants.
*/
public static ImageTypeSpecifier
int[] bankIndices,
int[] bandOffsets,
int dataType,
boolean hasAlpha,
boolean isAlphaPremultiplied) {
}
// Grayscale
int bits;
int dataType;
boolean isSigned;
boolean hasAlpha;
boolean isAlphaPremultiplied;
int dataType,
boolean isSigned,
boolean hasAlpha,
boolean isAlphaPremultiplied)
{
{
throw new IllegalArgumentException("Bad value for bits!");
}
{
throw new IllegalArgumentException
("Bad value for dataType!");
}
throw new IllegalArgumentException
("Too many bits for dataType!");
}
(bits == 16 &&
// Use component color model & sample model
int transparency =
if (numBands == 2) {
}
this.colorModel =
dataType);
int[] bandOffsets = new int[numBands];
if (numBands == 2) {
}
int w = 1;
int h = 1;
this.sampleModel =
w, h,
} else {
byte[] arr = new byte[numEntries];
for (int i = 0; i < numEntries; i++) {
}
this.colorModel =
this.sampleModel =
}
}
}
/**
* Returns a specifier for a grayscale image format that will pack
* pixels of the given bit depth into array elements of
* the specified data type.
*
* @param bits the number of bits per gray value (1, 2, 4, 8, or 16).
* @param dataType the desired data type, as one of the enumerations
* from the <code>DataBuffer</code> class.
* @param isSigned <code>true</code> if negative values are to
* be represented.
*
* @return an <code>ImageTypeSpecifier</code> with the desired
* characteristics.
*
* @exception IllegalArgumentException if <code>bits</code> is
* not one of 1, 2, 4, 8, or 16.
* @exception IllegalArgumentException if <code>dataType</code> is
* not one of <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_SHORT</code>, or
* <code>DataBuffer.TYPE_USHORT</code>.
* @exception IllegalArgumentException if <code>bits</code> is
* larger than the bit size of the given <code>dataType</code>.
*/
public static ImageTypeSpecifier
int dataType,
boolean isSigned) {
false,
false);
}
/**
* Returns a specifier for a grayscale plus alpha image format
* that will pack pixels of the given bit depth into array
* elements of the specified data type.
*
* @param bits the number of bits per gray value (1, 2, 4, 8, or 16).
* @param dataType the desired data type, as one of the enumerations
* from the <code>DataBuffer</code> class.
* @param isSigned <code>true</code> if negative values are to
* be represented.
* @param isAlphaPremultiplied <code>true</code> if the luminance channel
* will be premultipled by the alpha channel.
*
* @return an <code>ImageTypeSpecifier</code> with the desired
* characteristics.
*
* @exception IllegalArgumentException if <code>bits</code> is
* not one of 1, 2, 4, 8, or 16.
* @exception IllegalArgumentException if <code>dataType</code> is
* not one of <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_SHORT</code>, or
* <code>DataBuffer.TYPE_USHORT</code>.
* @exception IllegalArgumentException if <code>bits</code> is
* larger than the bit size of the given <code>dataType</code>.
*/
public static ImageTypeSpecifier
int dataType,
boolean isSigned,
boolean isAlphaPremultiplied) {
true,
}
// Indexed
byte[] redLUT;
byte[] greenLUT;
byte[] blueLUT;
int bits;
int dataType;
byte[] greenLUT,
byte[] blueLUT,
byte[] alphaLUT,
int bits,
int dataType) {
throw new IllegalArgumentException("LUT is null!");
}
throw new IllegalArgumentException("Bad value for bits!");
}
throw new IllegalArgumentException
("Bad value for dataType!");
}
throw new IllegalArgumentException
("Too many bits for dataType!");
}
throw new IllegalArgumentException("LUT has improper length!");
}
}
blueLUT);
} else {
alphaLUT);
}
(bits == 16 &&
int[] bandOffsets = { 0 };
this.sampleModel =
1, 1, 1, 1,
} else {
this.sampleModel =
}
}
}
/**
* Returns a specifier for an indexed-color image format that will pack
* index values of the given bit depth into array elements of
* the specified data type.
*
* @param redLUT an array of <code>byte</code>s containing
* the red values for each index.
* @param greenLUT an array of <code>byte</code>s containing * the
* green values for each index.
* @param blueLUT an array of <code>byte</code>s containing the
* blue values for each index.
* @param alphaLUT an array of <code>byte</code>s containing the
* alpha values for each index, or <code>null</code> to create a
* fully opaque LUT.
* @param bits the number of bits in each index.
* @param dataType the desired output type, as one of the enumerations
* from the <code>DataBuffer</code> class.
*
* @return an <code>ImageTypeSpecifier</code> with the desired
* characteristics.
*
* @exception IllegalArgumentException if <code>redLUT</code> is
* <code>null</code>.
* @exception IllegalArgumentException if <code>greenLUT</code> is
* <code>null</code>.
* @exception IllegalArgumentException if <code>blueLUT</code> is
* <code>null</code>.
* @exception IllegalArgumentException if <code>bits</code> is
* not one of 1, 2, 4, 8, or 16.
* @exception IllegalArgumentException if the
* non-<code>null</code> LUT parameters do not have lengths of
* exactly <code>1 << bits</code>.
* @exception IllegalArgumentException if <code>dataType</code> is
* not one of <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_SHORT</code>,
* <code>DataBuffer.TYPE_USHORT</code>,
* or <code>DataBuffer.TYPE_INT</code>.
* @exception IllegalArgumentException if <code>bits</code> is
* larger than the bit size of the given <code>dataType</code>.
*/
public static ImageTypeSpecifier
byte[] greenLUT,
byte[] blueLUT,
byte[] alphaLUT,
int bits,
int dataType) {
bits,
dataType);
}
/**
* Returns an <code>ImageTypeSpecifier</code> that encodes
* one of the standard <code>BufferedImage</code> types
* (other than <code>TYPE_CUSTOM</code>).
*
* @param bufferedImageType an int representing one of the standard
* <code>BufferedImage</code> types.
*
* @return an <code>ImageTypeSpecifier</code> with the desired
* characteristics.
*
* @exception IllegalArgumentException if
* <code>bufferedImageType</code> is not one of the standard
* types, or is equal to <code>TYPE_CUSTOM</code>.
*
* @see java.awt.image.BufferedImage
* @see java.awt.image.BufferedImage#TYPE_INT_RGB
* @see java.awt.image.BufferedImage#TYPE_INT_ARGB
* @see java.awt.image.BufferedImage#TYPE_INT_ARGB_PRE
* @see java.awt.image.BufferedImage#TYPE_INT_BGR
* @see java.awt.image.BufferedImage#TYPE_3BYTE_BGR
* @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR
* @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR_PRE
* @see java.awt.image.BufferedImage#TYPE_USHORT_565_RGB
* @see java.awt.image.BufferedImage#TYPE_USHORT_555_RGB
* @see java.awt.image.BufferedImage#TYPE_BYTE_GRAY
* @see java.awt.image.BufferedImage#TYPE_USHORT_GRAY
* @see java.awt.image.BufferedImage#TYPE_BYTE_BINARY
* @see java.awt.image.BufferedImage#TYPE_BYTE_INDEXED
*/
public static
return getSpecifier(bufferedImageType);
throw new IllegalArgumentException("Cannot create from TYPE_CUSTOM!");
} else {
throw new IllegalArgumentException("Invalid BufferedImage type!");
}
}
/**
* Returns an <code>ImageTypeSpecifier</code> that encodes the
* layout of a <code>RenderedImage</code> (which may be a
* <code>BufferedImage</code>).
*
* @param image a <code>RenderedImage</code>.
*
* @return an <code>ImageTypeSpecifier</code> with the desired
* characteristics.
*
* @exception IllegalArgumentException if <code>image</code> is
* <code>null</code>.
*/
public static
throw new IllegalArgumentException("image == null!");
}
if (image instanceof BufferedImage) {
return getSpecifier(bufferedImageType);
}
}
return new ImageTypeSpecifier(image);
}
/**
* Returns an int containing one of the enumerated constant values
* describing image formats from <code>BufferedImage</code>.
*
* @return an <code>int</code> representing a
* <code>BufferedImage</code> type.
*
* @see java.awt.image.BufferedImage
* @see java.awt.image.BufferedImage#TYPE_CUSTOM
* @see java.awt.image.BufferedImage#TYPE_INT_RGB
* @see java.awt.image.BufferedImage#TYPE_INT_ARGB
* @see java.awt.image.BufferedImage#TYPE_INT_ARGB_PRE
* @see java.awt.image.BufferedImage#TYPE_INT_BGR
* @see java.awt.image.BufferedImage#TYPE_3BYTE_BGR
* @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR
* @see java.awt.image.BufferedImage#TYPE_4BYTE_ABGR_PRE
* @see java.awt.image.BufferedImage#TYPE_USHORT_565_RGB
* @see java.awt.image.BufferedImage#TYPE_USHORT_555_RGB
* @see java.awt.image.BufferedImage#TYPE_BYTE_GRAY
* @see java.awt.image.BufferedImage#TYPE_USHORT_GRAY
* @see java.awt.image.BufferedImage#TYPE_BYTE_BINARY
* @see java.awt.image.BufferedImage#TYPE_BYTE_INDEXED
*/
public int getBufferedImageType() {
}
/**
* Return the number of color components
* specified by this object. This is the same value as returned by
* <code>ColorModel.getNumComponents</code>
*
* @return the number of components in the image.
*/
public int getNumComponents() {
return colorModel.getNumComponents();
}
/**
* Return the number of bands
* specified by this object. This is the same value as returned by
* <code>SampleModel.getNumBands</code>
*
* @return the number of bands in the image.
*/
public int getNumBands() {
return sampleModel.getNumBands();
}
/**
* Return the number of bits used to represent samples of the given band.
*
* @param band the index of the band to be queried, as an
* int.
*
* @return an int specifying a number of bits.
*
* @exception IllegalArgumentException if <code>band</code> is
* negative or greater than the largest band index.
*/
throw new IllegalArgumentException("band out of range!");
}
}
/**
* Returns a <code>SampleModel</code> based on the settings
* encapsulated within this object. The width and height of the
* <code>SampleModel</code> will be set to arbitrary values.
*
* @return a <code>SampleModel</code> with arbitrary dimensions.
*/
return sampleModel;
}
/**
* Returns a <code>SampleModel</code> based on the settings
* encapsulated within this object. The width and height of the
* <code>SampleModel</code> will be set to the supplied values.
*
* @param width the desired width of the returned <code>SampleModel</code>.
* @param height the desired height of the returned
* <code>SampleModel</code>.
*
* @return a <code>SampleModel</code> with the given dimensions.
*
* @exception IllegalArgumentException if either <code>width</code> or
* <code>height</code> are negative or zero.
* @exception IllegalArgumentException if the product of
* <code>width</code> and <code>height</code> is greater than
* <code>Integer.MAX_VALUE</code>
*/
throw new IllegalArgumentException
("width*height > Integer.MAX_VALUE!");
}
}
/**
* Returns the <code>ColorModel</code> specified by this object.
*
* @return a <code>ColorModel</code>.
*/
return colorModel;
}
/**
* Creates a <code>BufferedImage</code> with a given width and
* height according to the specification embodied in this object.
*
* @param width the desired width of the returned
* <code>BufferedImage</code>.
* @param height the desired height of the returned
* <code>BufferedImage</code>.
*
* @return a new <code>BufferedImage</code>
*
* @exception IllegalArgumentException if either <code>width</code> or
* <code>height</code> are negative or zero.
* @exception IllegalArgumentException if the product of
* <code>width</code> and <code>height</code> is greater than
* <code>Integer.MAX_VALUE</code>, or if the number of array
* elements needed to store the image is greater than
* <code>Integer.MAX_VALUE</code>.
*/
try {
new Hashtable());
} catch (NegativeArraySizeException e) {
// Exception most likely thrown from a DataBuffer constructor
throw new IllegalArgumentException
("Array size > Integer.MAX_VALUE!");
}
}
/**
* Returns <code>true</code> if the given <code>Object</code> is
* an <code>ImageTypeSpecifier</code> and has a
* <code>SampleModel</code> and <code>ColorModel</code> that are
* equal to those of this object.
*
* @param o the <code>Object</code> to be compared for equality.
*
* @return <code>true</code> if the given object is an equivalent
* <code>ImageTypeSpecifier</code>.
*/
if ((o == null) || !(o instanceof ImageTypeSpecifier)) {
return false;
}
}
/**
* Returns the hash code for this ImageTypeSpecifier.
*
* @return a hash code for this ImageTypeSpecifier
*/
public int hashCode() {
}
}
return BISpecifier[type];
}
switch(type) {
case BufferedImage.TYPE_INT_RGB:
return createPacked(sRGB,
0x00ff0000,
0x0000ff00,
0x000000ff,
0x0,
false);
case BufferedImage.TYPE_INT_ARGB:
return createPacked(sRGB,
0x00ff0000,
0x0000ff00,
0x000000ff,
0xff000000,
false);
return createPacked(sRGB,
0x00ff0000,
0x0000ff00,
0x000000ff,
0xff000000,
true);
case BufferedImage.TYPE_INT_BGR:
return createPacked(sRGB,
0x000000ff,
0x0000ff00,
0x00ff0000,
0x0,
false);
case BufferedImage.TYPE_3BYTE_BGR:
return createInterleaved(sRGB,
new int[] { 2, 1, 0 },
false,
false);
case BufferedImage.TYPE_4BYTE_ABGR:
return createInterleaved(sRGB,
new int[] { 3, 2, 1, 0 },
true,
false);
return createInterleaved(sRGB,
new int[] { 3, 2, 1, 0 },
true,
true);
return createPacked(sRGB,
0xF800,
0x07E0,
0x001F,
0x0,
false);
return createPacked(sRGB,
0x7C00,
0x03E0,
0x001F,
0x0,
false);
case BufferedImage.TYPE_BYTE_GRAY:
return createGrayscale(8,
false);
return createGrayscale(16,
false);
return createGrayscale(1,
false);
{
8,
}
default:
throw new IllegalArgumentException("Invalid BufferedImage type!");
}
}
}