6662775: Move imaging and color classes from closed to open
Reviewed-by: tdv, campbell
--- a/jdk/make/common/internal/BinaryPlugs.gmk Thu Apr 10 10:32:31 2008 -0700
+++ b/jdk/make/common/internal/BinaryPlugs.gmk Thu Apr 10 16:28:45 2008 -0700
@@ -126,44 +126,10 @@
com/sun/media/sound/SimpleInputDeviceProvider\$$InputDeviceInfo.class \
com/sun/media/sound/SimpleInputDeviceProvider.class
-PLUG_AWT_CLASS_NAMES = \
-java/awt/color/CMMException.class \
-java/awt/color/ColorSpace.class \
-java/awt/color/ICC_ColorSpace.class \
-java/awt/color/ICC_Profile\$$1.class \
-java/awt/color/ICC_Profile\$$2.class \
-java/awt/color/ICC_Profile\$$3.class \
-java/awt/color/ICC_Profile.class \
-java/awt/color/ICC_ProfileGray.class \
-java/awt/color/ICC_ProfileRGB.class \
-java/awt/image/BandedSampleModel.class \
-java/awt/image/ColorConvertOp.class \
-java/awt/image/ComponentSampleModel.class \
-java/awt/image/DataBuffer\$$1.class \
-java/awt/image/DataBuffer.class \
-java/awt/image/DataBufferByte.class \
-java/awt/image/DataBufferInt.class \
-java/awt/image/DataBufferShort.class \
-java/awt/image/DataBufferUShort.class \
-java/awt/image/MultiPixelPackedSampleModel.class \
-java/awt/image/Raster.class \
-java/awt/image/RenderedImage.class \
-java/awt/image/SampleModel.class \
-java/awt/image/SinglePixelPackedSampleModel.class \
-java/awt/image/WritableRaster.class \
-java/awt/image/WritableRenderedImage.class \
-java/awt/image/renderable/ContextualRenderedImageFactory.class \
-java/awt/image/renderable/ParameterBlock.class \
-java/awt/image/renderable/RenderContext.class \
-java/awt/image/renderable/RenderableImage.class \
-java/awt/image/renderable/RenderableImageOp.class \
-java/awt/image/renderable/RenderableImageProducer.class \
-java/awt/image/renderable/RenderedImageFactory.class
-
# Class list temp files (used by both import and export of plugs)
PLUG_TEMPDIR=$(ABS_TEMPDIR)/plugs
-PLUG_CLASS_AREAS = jmf sound awt
+PLUG_CLASS_AREAS = jmf sound
PLUG_CLISTS = $(PLUG_CLASS_AREAS:%=$(PLUG_TEMPDIR)/%.clist)
# Create jargs file command
@@ -186,11 +152,6 @@
@for i in $(PLUG_SOUND_CLASS_NAMES) ; do \
$(ECHO) "$$i" >> $@ ; \
done
-$(PLUG_TEMPDIR)/awt.clist:
- @$(prep-target)
- @for i in $(PLUG_AWT_CLASS_NAMES) ; do \
- $(ECHO) "$$i" >> $@ ; \
- done
$(PLUG_TEMPDIR)/all.clist: $(PLUG_CLISTS)
@$(prep-target)
$(CAT) $(PLUG_CLISTS) > $@
@@ -198,8 +159,6 @@
$(plug-create-jargs)
$(PLUG_TEMPDIR)/sound.jargs: $(PLUG_TEMPDIR)/sound.clist
$(plug-create-jargs)
-$(PLUG_TEMPDIR)/awt.jargs: $(PLUG_TEMPDIR)/awt.clist
- $(plug-create-jargs)
$(PLUG_TEMPDIR)/all.jargs: $(PLUG_TEMPDIR)/all.clist
$(plug-create-jargs)
@@ -235,15 +194,12 @@
$(call import-binary-plug-classes,$(PLUG_TEMPDIR)/jmf.clist)
import-binary-plug-sound-classes: $(PLUG_IMPORT_JARFILE) $(PLUG_TEMPDIR)/sound.clist
$(call import-binary-plug-classes,$(PLUG_TEMPDIR)/sound.clist)
-import-binary-plug-awt-classes: $(PLUG_IMPORT_JARFILE) $(PLUG_TEMPDIR)/awt.clist
- $(call import-binary-plug-classes,$(PLUG_TEMPDIR)/awt.clist)
# Import all classes from the jar file
import-binary-plug-jar: \
import-binary-plug-jmf-classes \
- import-binary-plug-sound-classes \
- import-binary-plug-awt-classes
+ import-binary-plug-sound-classes
# Import native libraries
@@ -286,7 +242,6 @@
import-binary-plug-jar \
import-binary-plug-jmf-classes \
import-binary-plug-sound-classes \
- import-binary-plug-awt-classes \
import-binary-plug-jsound-library
else # !OPENJDK
--- a/jdk/make/java/awt/Makefile Thu Apr 10 10:32:31 2008 -0700
+++ b/jdk/make/java/awt/Makefile Thu Apr 10 16:28:45 2008 -0700
@@ -28,24 +28,12 @@
PRODUCT = sun
include $(BUILDDIR)/common/Defs.gmk
-# WARNING: Make sure the OPENJDK plugs are up-to-date, see make/common/internal/BinaryPlugs.gmk
#
# Files
#
AUTO_FILES_JAVA_DIRS = java/awt sun/awt/geom
-#
-# Specific to OPENJDK
-#
-ifdef OPENJDK
-
-build: import-binary-plug-awt-classes
-
-include $(BUILDDIR)/common/internal/BinaryPlugs.gmk
-
-endif
-
build: properties cursors
#
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/color/CMMException.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,57 @@
+/*
+ * 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ Created by gbp, October 25, 1997
+
+ *
+ */
+/**********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+
+package java.awt.color;
+
+
+/**
+ * This exception is thrown if the native CMM returns an error.
+ */
+
+public class CMMException extends java.lang.RuntimeException {
+
+ /**
+ * Constructs a CMMException with the specified detail message.
+ * @param s the specified detail message
+ */
+ public CMMException (String s) {
+ super (s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/color/ColorSpace.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,611 @@
+/*
+ * Portions Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.color;
+
+import sun.java2d.cmm.PCMM;
+import sun.java2d.cmm.CMSManager;
+
+
+/**
+ * This abstract class is used to serve as a color space tag to identify the
+ * specific color space of a Color object or, via a ColorModel object,
+ * of an Image, a BufferedImage, or a GraphicsDevice. It contains
+ * methods that transform colors in a specific color space to/from sRGB
+ * and to/from a well-defined CIEXYZ color space.
+ * <p>
+ * For purposes of the methods in this class, colors are represented as
+ * arrays of color components represented as floats in a normalized range
+ * defined by each ColorSpace. For many ColorSpaces (e.g. sRGB), this
+ * range is 0.0 to 1.0. However, some ColorSpaces have components whose
+ * values have a different range. Methods are provided to inquire per
+ * component minimum and maximum normalized values.
+ * <p>
+ * Several variables are defined for purposes of referring to color
+ * space types (e.g. TYPE_RGB, TYPE_XYZ, etc.) and to refer to specific
+ * color spaces (e.g. CS_sRGB and CS_CIEXYZ).
+ * sRGB is a proposed standard RGB color space. For more information,
+ * see <A href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
+ * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
+ * </A>.
+ * <p>
+ * The purpose of the methods to transform to/from the well-defined
+ * CIEXYZ color space is to support conversions between any two color
+ * spaces at a reasonably high degree of accuracy. It is expected that
+ * particular implementations of subclasses of ColorSpace (e.g.
+ * ICC_ColorSpace) will support high performance conversion based on
+ * underlying platform color management systems.
+ * <p>
+ * The CS_CIEXYZ space used by the toCIEXYZ/fromCIEXYZ methods can be
+ * described as follows:
+<pre>
+
+ CIEXYZ
+ viewing illuminance: 200 lux
+ viewing white point: CIE D50
+ media white point: "that of a perfectly reflecting diffuser" -- D50
+ media black point: 0 lux or 0 Reflectance
+ flare: 1 percent
+ surround: 20percent of the media white point
+ media description: reflection print (i.e., RLAB, Hunt viewing media)
+ note: For developers creating an ICC profile for this conversion
+ space, the following is applicable. Use a simple Von Kries
+ white point adaptation folded into the 3X3 matrix parameters
+ and fold the flare and surround effects into the three
+ one-dimensional lookup tables (assuming one uses the minimal
+ model for monitors).
+
+</pre>
+ *
+ * <p>
+ * @see ICC_ColorSpace
+ */
+
+
+
+public abstract class ColorSpace implements java.io.Serializable {
+
+ static final long serialVersionUID = -409452704308689724L;
+
+ private int type;
+ private int numComponents;
+ private transient String [] compName = null;
+
+ // Cache of singletons for the predefined color spaces.
+ private static ColorSpace sRGBspace;
+ private static ColorSpace XYZspace;
+ private static ColorSpace PYCCspace;
+ private static ColorSpace GRAYspace;
+ private static ColorSpace LINEAR_RGBspace;
+
+ /**
+ * Any of the family of XYZ color spaces.
+ */
+ public static final int TYPE_XYZ = 0;
+
+ /**
+ * Any of the family of Lab color spaces.
+ */
+ public static final int TYPE_Lab = 1;
+
+ /**
+ * Any of the family of Luv color spaces.
+ */
+ public static final int TYPE_Luv = 2;
+
+ /**
+ * Any of the family of YCbCr color spaces.
+ */
+ public static final int TYPE_YCbCr = 3;
+
+ /**
+ * Any of the family of Yxy color spaces.
+ */
+ public static final int TYPE_Yxy = 4;
+
+ /**
+ * Any of the family of RGB color spaces.
+ */
+ public static final int TYPE_RGB = 5;
+
+ /**
+ * Any of the family of GRAY color spaces.
+ */
+ public static final int TYPE_GRAY = 6;
+
+ /**
+ * Any of the family of HSV color spaces.
+ */
+ public static final int TYPE_HSV = 7;
+
+ /**
+ * Any of the family of HLS color spaces.
+ */
+ public static final int TYPE_HLS = 8;
+
+ /**
+ * Any of the family of CMYK color spaces.
+ */
+ public static final int TYPE_CMYK = 9;
+
+ /**
+ * Any of the family of CMY color spaces.
+ */
+ public static final int TYPE_CMY = 11;
+
+ /**
+ * Generic 2 component color spaces.
+ */
+ public static final int TYPE_2CLR = 12;
+
+ /**
+ * Generic 3 component color spaces.
+ */
+ public static final int TYPE_3CLR = 13;
+
+ /**
+ * Generic 4 component color spaces.
+ */
+ public static final int TYPE_4CLR = 14;
+
+ /**
+ * Generic 5 component color spaces.
+ */
+ public static final int TYPE_5CLR = 15;
+
+ /**
+ * Generic 6 component color spaces.
+ */
+ public static final int TYPE_6CLR = 16;
+
+ /**
+ * Generic 7 component color spaces.
+ */
+ public static final int TYPE_7CLR = 17;
+
+ /**
+ * Generic 8 component color spaces.
+ */
+ public static final int TYPE_8CLR = 18;
+
+ /**
+ * Generic 9 component color spaces.
+ */
+ public static final int TYPE_9CLR = 19;
+
+ /**
+ * Generic 10 component color spaces.
+ */
+ public static final int TYPE_ACLR = 20;
+
+ /**
+ * Generic 11 component color spaces.
+ */
+ public static final int TYPE_BCLR = 21;
+
+ /**
+ * Generic 12 component color spaces.
+ */
+ public static final int TYPE_CCLR = 22;
+
+ /**
+ * Generic 13 component color spaces.
+ */
+ public static final int TYPE_DCLR = 23;
+
+ /**
+ * Generic 14 component color spaces.
+ */
+ public static final int TYPE_ECLR = 24;
+
+ /**
+ * Generic 15 component color spaces.
+ */
+ public static final int TYPE_FCLR = 25;
+
+ /**
+ * The sRGB color space defined at
+ * <A href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
+ * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
+ * </A>.
+ */
+ public static final int CS_sRGB = 1000;
+
+ /**
+ * A built-in linear RGB color space. This space is based on the
+ * same RGB primaries as CS_sRGB, but has a linear tone reproduction curve.
+ */
+ public static final int CS_LINEAR_RGB = 1004;
+
+ /**
+ * The CIEXYZ conversion color space defined above.
+ */
+ public static final int CS_CIEXYZ = 1001;
+
+ /**
+ * The Photo YCC conversion color space.
+ */
+ public static final int CS_PYCC = 1002;
+
+ /**
+ * The built-in linear gray scale color space.
+ */
+ public static final int CS_GRAY = 1003;
+
+
+ /**
+ * Constructs a ColorSpace object given a color space type
+ * and the number of components.
+ * @param type one of the <CODE>ColorSpace</CODE> type constants
+ * @param numcomponents the number of components in the color space
+ */
+ protected ColorSpace (int type, int numcomponents) {
+ this.type = type;
+ this.numComponents = numcomponents;
+ }
+
+
+ /**
+ * Returns a ColorSpace representing one of the specific
+ * predefined color spaces.
+ * @param colorspace a specific color space identified by one of
+ * the predefined class constants (e.g. CS_sRGB, CS_LINEAR_RGB,
+ * CS_CIEXYZ, CS_GRAY, or CS_PYCC)
+ * @return the requested <CODE>ColorSpace</CODE> object
+ */
+ // NOTE: This method may be called by privileged threads.
+ // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
+ public static ColorSpace getInstance (int colorspace)
+ {
+ ColorSpace theColorSpace;
+
+ switch (colorspace) {
+ case CS_sRGB:
+ synchronized(ColorSpace.class) {
+ if (sRGBspace == null) {
+ ICC_Profile theProfile = ICC_Profile.getInstance (CS_sRGB);
+ sRGBspace = new ICC_ColorSpace (theProfile);
+ }
+
+ theColorSpace = sRGBspace;
+ }
+ break;
+
+ case CS_CIEXYZ:
+ synchronized(ColorSpace.class) {
+ if (XYZspace == null) {
+ ICC_Profile theProfile =
+ ICC_Profile.getInstance (CS_CIEXYZ);
+ XYZspace = new ICC_ColorSpace (theProfile);
+ }
+
+ theColorSpace = XYZspace;
+ }
+ break;
+
+ case CS_PYCC:
+ synchronized(ColorSpace.class) {
+ if (PYCCspace == null) {
+ ICC_Profile theProfile = ICC_Profile.getInstance (CS_PYCC);
+ PYCCspace = new ICC_ColorSpace (theProfile);
+ }
+
+ theColorSpace = PYCCspace;
+ }
+ break;
+
+
+ case CS_GRAY:
+ synchronized(ColorSpace.class) {
+ if (GRAYspace == null) {
+ ICC_Profile theProfile = ICC_Profile.getInstance (CS_GRAY);
+ GRAYspace = new ICC_ColorSpace (theProfile);
+ /* to allow access from java.awt.ColorModel */
+ CMSManager.GRAYspace = GRAYspace;
+ }
+
+ theColorSpace = GRAYspace;
+ }
+ break;
+
+
+ case CS_LINEAR_RGB:
+ synchronized(ColorSpace.class) {
+ if (LINEAR_RGBspace == null) {
+ ICC_Profile theProfile =
+ ICC_Profile.getInstance(CS_LINEAR_RGB);
+ LINEAR_RGBspace = new ICC_ColorSpace (theProfile);
+ /* to allow access from java.awt.ColorModel */
+ CMSManager.LINEAR_RGBspace = LINEAR_RGBspace;
+ }
+
+ theColorSpace = LINEAR_RGBspace;
+ }
+ break;
+
+
+ default:
+ throw new IllegalArgumentException ("Unknown color space");
+ }
+
+ return theColorSpace;
+ }
+
+
+ /**
+ * Returns true if the ColorSpace is CS_sRGB.
+ * @return <CODE>true</CODE> if this is a <CODE>CS_sRGB</CODE> color
+ * space, <code>false</code> if it is not
+ */
+ public boolean isCS_sRGB () {
+ /* REMIND - make sure we know sRGBspace exists already */
+ return (this == sRGBspace);
+ }
+
+ /**
+ * Transforms a color value assumed to be in this ColorSpace
+ * into a value in the default CS_sRGB color space.
+ * <p>
+ * This method transforms color values using algorithms designed
+ * to produce the best perceptual match between input and output
+ * colors. In order to do colorimetric conversion of color values,
+ * you should use the <code>toCIEXYZ</code>
+ * method of this color space to first convert from the input
+ * color space to the CS_CIEXYZ color space, and then use the
+ * <code>fromCIEXYZ</code> method of the CS_sRGB color space to
+ * convert from CS_CIEXYZ to the output color space.
+ * See {@link #toCIEXYZ(float[]) toCIEXYZ} and
+ * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
+ * <p>
+ * @param colorvalue a float array with length of at least the number
+ * of components in this ColorSpace
+ * @return a float array of length 3
+ * @throws ArrayIndexOutOfBoundsException if array length is not
+ * at least the number of components in this ColorSpace
+ */
+ public abstract float[] toRGB(float[] colorvalue);
+
+
+ /**
+ * Transforms a color value assumed to be in the default CS_sRGB
+ * color space into this ColorSpace.
+ * <p>
+ * This method transforms color values using algorithms designed
+ * to produce the best perceptual match between input and output
+ * colors. In order to do colorimetric conversion of color values,
+ * you should use the <code>toCIEXYZ</code>
+ * method of the CS_sRGB color space to first convert from the input
+ * color space to the CS_CIEXYZ color space, and then use the
+ * <code>fromCIEXYZ</code> method of this color space to
+ * convert from CS_CIEXYZ to the output color space.
+ * See {@link #toCIEXYZ(float[]) toCIEXYZ} and
+ * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
+ * <p>
+ * @param rgbvalue a float array with length of at least 3
+ * @return a float array with length equal to the number of
+ * components in this ColorSpace
+ * @throws ArrayIndexOutOfBoundsException if array length is not
+ * at least 3
+ */
+ public abstract float[] fromRGB(float[] rgbvalue);
+
+
+ /**
+ * Transforms a color value assumed to be in this ColorSpace
+ * into the CS_CIEXYZ conversion color space.
+ * <p>
+ * This method transforms color values using relative colorimetry,
+ * as defined by the International Color Consortium standard. This
+ * means that the XYZ values returned by this method are represented
+ * relative to the D50 white point of the CS_CIEXYZ color space.
+ * This representation is useful in a two-step color conversion
+ * process in which colors are transformed from an input color
+ * space to CS_CIEXYZ and then to an output color space. This
+ * representation is not the same as the XYZ values that would
+ * be measured from the given color value by a colorimeter.
+ * A further transformation is necessary to compute the XYZ values
+ * that would be measured using current CIE recommended practices.
+ * See the {@link ICC_ColorSpace#toCIEXYZ(float[]) toCIEXYZ} method of
+ * <code>ICC_ColorSpace</code> for further information.
+ * <p>
+ * @param colorvalue a float array with length of at least the number
+ * of components in this ColorSpace
+ * @return a float array of length 3
+ * @throws ArrayIndexOutOfBoundsException if array length is not
+ * at least the number of components in this ColorSpace.
+ */
+ public abstract float[] toCIEXYZ(float[] colorvalue);
+
+
+ /**
+ * Transforms a color value assumed to be in the CS_CIEXYZ conversion
+ * color space into this ColorSpace.
+ * <p>
+ * This method transforms color values using relative colorimetry,
+ * as defined by the International Color Consortium standard. This
+ * means that the XYZ argument values taken by this method are represented
+ * relative to the D50 white point of the CS_CIEXYZ color space.
+ * This representation is useful in a two-step color conversion
+ * process in which colors are transformed from an input color
+ * space to CS_CIEXYZ and then to an output color space. The color
+ * values returned by this method are not those that would produce
+ * the XYZ value passed to the method when measured by a colorimeter.
+ * If you have XYZ values corresponding to measurements made using
+ * current CIE recommended practices, they must be converted to D50
+ * relative values before being passed to this method.
+ * See the {@link ICC_ColorSpace#fromCIEXYZ(float[]) fromCIEXYZ} method of
+ * <code>ICC_ColorSpace</code> for further information.
+ * <p>
+ * @param colorvalue a float array with length of at least 3
+ * @return a float array with length equal to the number of
+ * components in this ColorSpace
+ * @throws ArrayIndexOutOfBoundsException if array length is not
+ * at least 3
+ */
+ public abstract float[] fromCIEXYZ(float[] colorvalue);
+
+ /**
+ * Returns the color space type of this ColorSpace (for example
+ * TYPE_RGB, TYPE_XYZ, ...). The type defines the
+ * number of components of the color space and the interpretation,
+ * e.g. TYPE_RGB identifies a color space with three components - red,
+ * green, and blue. It does not define the particular color
+ * characteristics of the space, e.g. the chromaticities of the
+ * primaries.
+ *
+ * @return the type constant that represents the type of this
+ * <CODE>ColorSpace</CODE>
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Returns the number of components of this ColorSpace.
+ * @return The number of components in this <CODE>ColorSpace</CODE>.
+ */
+ public int getNumComponents() {
+ return numComponents;
+ }
+
+ /**
+ * Returns the name of the component given the component index.
+ *
+ * @param idx the component index
+ * @return the name of the component at the specified index
+ * @throws IllegalArgumentException if <code>idx</code> is
+ * less than 0 or greater than numComponents - 1
+ */
+ public String getName (int idx) {
+ /* REMIND - handle common cases here */
+ if ((idx < 0) || (idx > numComponents - 1)) {
+ throw new IllegalArgumentException(
+ "Component index out of range: " + idx);
+ }
+
+ if (compName == null) {
+ switch (type) {
+ case ColorSpace.TYPE_XYZ:
+ compName = new String[] {"X", "Y", "Z"};
+ break;
+ case ColorSpace.TYPE_Lab:
+ compName = new String[] {"L", "a", "b"};
+ break;
+ case ColorSpace.TYPE_Luv:
+ compName = new String[] {"L", "u", "v"};
+ break;
+ case ColorSpace.TYPE_YCbCr:
+ compName = new String[] {"Y", "Cb", "Cr"};
+ break;
+ case ColorSpace.TYPE_Yxy:
+ compName = new String[] {"Y", "x", "y"};
+ break;
+ case ColorSpace.TYPE_RGB:
+ compName = new String[] {"Red", "Green", "Blue"};
+ break;
+ case ColorSpace.TYPE_GRAY:
+ compName = new String[] {"Gray"};
+ break;
+ case ColorSpace.TYPE_HSV:
+ compName = new String[] {"Hue", "Saturation", "Value"};
+ break;
+ case ColorSpace.TYPE_HLS:
+ compName = new String[] {"Hue", "Lightness",
+ "Saturation"};
+ break;
+ case ColorSpace.TYPE_CMYK:
+ compName = new String[] {"Cyan", "Magenta", "Yellow",
+ "Black"};
+ break;
+ case ColorSpace.TYPE_CMY:
+ compName = new String[] {"Cyan", "Magenta", "Yellow"};
+ break;
+ default:
+ String [] tmp = new String[numComponents];
+ for (int i = 0; i < tmp.length; i++) {
+ tmp[i] = "Unnamed color component(" + i + ")";
+ }
+ compName = tmp;
+ }
+ }
+ return compName[idx];
+ }
+
+ /**
+ * Returns the minimum normalized color component value for the
+ * specified component. The default implementation in this abstract
+ * class returns 0.0 for all components. Subclasses should override
+ * this method if necessary.
+ *
+ * @param component the component index
+ * @return the minimum normalized component value
+ * @throws IllegalArgumentException if component is less than 0 or
+ * greater than numComponents - 1
+ * @since 1.4
+ */
+ public float getMinValue(int component) {
+ if ((component < 0) || (component > numComponents - 1)) {
+ throw new IllegalArgumentException(
+ "Component index out of range: " + component);
+ }
+ return 0.0f;
+ }
+
+ /**
+ * Returns the maximum normalized color component value for the
+ * specified component. The default implementation in this abstract
+ * class returns 1.0 for all components. Subclasses should override
+ * this method if necessary.
+ *
+ * @param component the component index
+ * @return the maximum normalized component value
+ * @throws IllegalArgumentException if component is less than 0 or
+ * greater than numComponents - 1
+ * @since 1.4
+ */
+ public float getMaxValue(int component) {
+ if ((component < 0) || (component > numComponents - 1)) {
+ throw new IllegalArgumentException(
+ "Component index out of range: " + component);
+ }
+ return 1.0f;
+ }
+
+ /* Returns true if cspace is the XYZspace.
+ */
+ static boolean isCS_CIEXYZ(ColorSpace cspace) {
+ return (cspace == XYZspace);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/color/ICC_ColorSpace.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,616 @@
+/*
+ * Portions Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.color;
+
+import sun.java2d.cmm.ColorTransform;
+import sun.java2d.cmm.CMSManager;
+import sun.java2d.cmm.PCMM;
+
+
+/**
+ *
+ * The ICC_ColorSpace class is an implementation of the abstract
+ * ColorSpace class. This representation of
+ * device independent and device dependent color spaces is based on the
+ * International Color Consortium Specification ICC.1:2001-12, File Format for
+ * Color Profiles (see <A href="http://www.color.org">http://www.color.org</A>).
+ * <p>
+ * Typically, a Color or ColorModel would be associated with an ICC
+ * Profile which is either an input, display, or output profile (see
+ * the ICC specification). There are other types of ICC Profiles, e.g.
+ * abstract profiles, device link profiles, and named color profiles,
+ * which do not contain information appropriate for representing the color
+ * space of a color, image, or device (see ICC_Profile).
+ * Attempting to create an ICC_ColorSpace object from an inappropriate ICC
+ * Profile is an error.
+ * <p>
+ * ICC Profiles represent transformations from the color space of
+ * the profile (e.g. a monitor) to a Profile Connection Space (PCS).
+ * Profiles of interest for tagging images or colors have a
+ * PCS which is one of the device independent
+ * spaces (one CIEXYZ space and two CIELab spaces) defined in the
+ * ICC Profile Format Specification. Most profiles of interest
+ * either have invertible transformations or explicitly specify
+ * transformations going both directions. Should an ICC_ColorSpace
+ * object be used in a way requiring a conversion from PCS to
+ * the profile's native space and there is inadequate data to
+ * correctly perform the conversion, the ICC_ColorSpace object will
+ * produce output in the specified type of color space (e.g. TYPE_RGB,
+ * TYPE_CMYK, etc.), but the specific color values of the output data
+ * will be undefined.
+ * <p>
+ * The details of this class are not important for simple applets,
+ * which draw in a default color space or manipulate and display
+ * imported images with a known color space. At most, such applets
+ * would need to get one of the default color spaces via
+ * ColorSpace.getInstance().
+ * <p>
+ * @see ColorSpace
+ * @see ICC_Profile
+ */
+
+
+
+public class ICC_ColorSpace extends ColorSpace {
+
+ static final long serialVersionUID = 3455889114070431483L;
+
+ private ICC_Profile thisProfile;
+ private float[] minVal;
+ private float[] maxVal;
+ private float[] diffMinMax;
+ private float[] invDiffMinMax;
+ private boolean needScaleInit = true;
+
+ // {to,from}{RGB,CIEXYZ} methods create and cache these when needed
+ private transient ColorTransform this2srgb;
+ private transient ColorTransform srgb2this;
+ private transient ColorTransform this2xyz;
+ private transient ColorTransform xyz2this;
+
+
+ /**
+ * Constructs a new ICC_ColorSpace from an ICC_Profile object.
+ * @param profile the specified ICC_Profile object
+ * @exception IllegalArgumentException if profile is inappropriate for
+ * representing a ColorSpace.
+ */
+ public ICC_ColorSpace (ICC_Profile profile) {
+ super (profile.getColorSpaceType(), profile.getNumComponents());
+
+ int profileClass = profile.getProfileClass();
+
+ /* REMIND - is NAMEDCOLOR OK? */
+ if ((profileClass != ICC_Profile.CLASS_INPUT) &&
+ (profileClass != ICC_Profile.CLASS_DISPLAY) &&
+ (profileClass != ICC_Profile.CLASS_OUTPUT) &&
+ (profileClass != ICC_Profile.CLASS_COLORSPACECONVERSION) &&
+ (profileClass != ICC_Profile.CLASS_NAMEDCOLOR) &&
+ (profileClass != ICC_Profile.CLASS_ABSTRACT)) {
+ throw new IllegalArgumentException("Invalid profile type");
+ }
+
+ thisProfile = profile;
+ setMinMax();
+ }
+
+ /**
+ * Returns the ICC_Profile for this ICC_ColorSpace.
+ * @return the ICC_Profile for this ICC_ColorSpace.
+ */
+ public ICC_Profile getProfile() {
+ return thisProfile;
+ }
+
+ /**
+ * Transforms a color value assumed to be in this ColorSpace
+ * into a value in the default CS_sRGB color space.
+ * <p>
+ * This method transforms color values using algorithms designed
+ * to produce the best perceptual match between input and output
+ * colors. In order to do colorimetric conversion of color values,
+ * you should use the <code>toCIEXYZ</code>
+ * method of this color space to first convert from the input
+ * color space to the CS_CIEXYZ color space, and then use the
+ * <code>fromCIEXYZ</code> method of the CS_sRGB color space to
+ * convert from CS_CIEXYZ to the output color space.
+ * See {@link #toCIEXYZ(float[]) toCIEXYZ} and
+ * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
+ * <p>
+ * @param colorvalue a float array with length of at least the number
+ * of components in this ColorSpace.
+ * @return a float array of length 3.
+ * @throws ArrayIndexOutOfBoundsException if array length is not
+ * at least the number of components in this ColorSpace.
+ */
+ public float[] toRGB (float[] colorvalue) {
+
+ if (this2srgb == null) {
+ ColorTransform[] transformList = new ColorTransform [2];
+ ICC_ColorSpace srgbCS =
+ (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB);
+ PCMM mdl = CMSManager.getModule();
+ transformList[0] = mdl.createTransform(
+ thisProfile, ColorTransform.Any, ColorTransform.In);
+ transformList[1] = mdl.createTransform(
+ srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
+ this2srgb = mdl.createTransform(transformList);
+ if (needScaleInit) {
+ setComponentScaling();
+ }
+ }
+
+ int nc = this.getNumComponents();
+ short tmp[] = new short[nc];
+ for (int i = 0; i < nc; i++) {
+ tmp[i] = (short)
+ ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f);
+ }
+ tmp = this2srgb.colorConvert(tmp, null);
+ float[] result = new float [3];
+ for (int i = 0; i < 3; i++) {
+ result[i] = ((float) (tmp[i] & 0xffff)) / 65535.0f;
+ }
+ return result;
+ }
+
+ /**
+ * Transforms a color value assumed to be in the default CS_sRGB
+ * color space into this ColorSpace.
+ * <p>
+ * This method transforms color values using algorithms designed
+ * to produce the best perceptual match between input and output
+ * colors. In order to do colorimetric conversion of color values,
+ * you should use the <code>toCIEXYZ</code>
+ * method of the CS_sRGB color space to first convert from the input
+ * color space to the CS_CIEXYZ color space, and then use the
+ * <code>fromCIEXYZ</code> method of this color space to
+ * convert from CS_CIEXYZ to the output color space.
+ * See {@link #toCIEXYZ(float[]) toCIEXYZ} and
+ * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
+ * <p>
+ * @param rgbvalue a float array with length of at least 3.
+ * @return a float array with length equal to the number of
+ * components in this ColorSpace.
+ * @throws ArrayIndexOutOfBoundsException if array length is not
+ * at least 3.
+ */
+ public float[] fromRGB(float[] rgbvalue) {
+
+ if (srgb2this == null) {
+ ColorTransform[] transformList = new ColorTransform [2];
+ ICC_ColorSpace srgbCS =
+ (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB);
+ PCMM mdl = CMSManager.getModule();
+ transformList[0] = mdl.createTransform(
+ srgbCS.getProfile(), ColorTransform.Any, ColorTransform.In);
+ transformList[1] = mdl.createTransform(
+ thisProfile, ColorTransform.Any, ColorTransform.Out);
+ srgb2this = mdl.createTransform(transformList);
+ if (needScaleInit) {
+ setComponentScaling();
+ }
+ }
+
+ short tmp[] = new short[3];
+ for (int i = 0; i < 3; i++) {
+ tmp[i] = (short) ((rgbvalue[i] * 65535.0f) + 0.5f);
+ }
+ tmp = srgb2this.colorConvert(tmp, null);
+ int nc = this.getNumComponents();
+ float[] result = new float [nc];
+ for (int i = 0; i < nc; i++) {
+ result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) *
+ diffMinMax[i] + minVal[i];
+ }
+ return result;
+ }
+
+
+ /**
+ * Transforms a color value assumed to be in this ColorSpace
+ * into the CS_CIEXYZ conversion color space.
+ * <p>
+ * This method transforms color values using relative colorimetry,
+ * as defined by the ICC Specification. This
+ * means that the XYZ values returned by this method are represented
+ * relative to the D50 white point of the CS_CIEXYZ color space.
+ * This representation is useful in a two-step color conversion
+ * process in which colors are transformed from an input color
+ * space to CS_CIEXYZ and then to an output color space. This
+ * representation is not the same as the XYZ values that would
+ * be measured from the given color value by a colorimeter.
+ * A further transformation is necessary to compute the XYZ values
+ * that would be measured using current CIE recommended practices.
+ * The paragraphs below explain this in more detail.
+ * <p>
+ * The ICC standard uses a device independent color space (DICS) as the
+ * mechanism for converting color from one device to another device. In
+ * this architecture, colors are converted from the source device's color
+ * space to the ICC DICS and then from the ICC DICS to the destination
+ * device's color space. The ICC standard defines device profiles which
+ * contain transforms which will convert between a device's color space
+ * and the ICC DICS. The overall conversion of colors from a source
+ * device to colors of a destination device is done by connecting the
+ * device-to-DICS transform of the profile for the source device to the
+ * DICS-to-device transform of the profile for the destination device.
+ * For this reason, the ICC DICS is commonly referred to as the profile
+ * connection space (PCS). The color space used in the methods
+ * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC
+ * Specification. This is also the color space represented by
+ * ColorSpace.CS_CIEXYZ.
+ * <p>
+ * The XYZ values of a color are often represented as relative to some
+ * white point, so the actual meaning of the XYZ values cannot be known
+ * without knowing the white point of those values. This is known as
+ * relative colorimetry. The PCS uses a white point of D50, so the XYZ
+ * values of the PCS are relative to D50. For example, white in the PCS
+ * will have the XYZ values of D50, which is defined to be X=.9642,
+ * Y=1.000, and Z=0.8249. This white point is commonly used for graphic
+ * arts applications, but others are often used in other applications.
+ * <p>
+ * To quantify the color characteristics of a device such as a printer
+ * or monitor, measurements of XYZ values for particular device colors
+ * are typically made. For purposes of this discussion, the term
+ * device XYZ values is used to mean the XYZ values that would be
+ * measured from device colors using current CIE recommended practices.
+ * <p>
+ * Converting between device XYZ values and the PCS XYZ values returned
+ * by this method corresponds to converting between the device's color
+ * space, as represented by CIE colorimetric values, and the PCS. There
+ * are many factors involved in this process, some of which are quite
+ * subtle. The most important, however, is the adjustment made to account
+ * for differences between the device's white point and the white point of
+ * the PCS. There are many techniques for doing this and it is the
+ * subject of much current research and controversy. Some commonly used
+ * methods are XYZ scaling, the von Kries transform, and the Bradford
+ * transform. The proper method to use depends upon each particular
+ * application.
+ * <p>
+ * The simplest method is XYZ scaling. In this method each device XYZ
+ * value is converted to a PCS XYZ value by multiplying it by the ratio
+ * of the PCS white point (D50) to the device white point.
+ * <pre>
+ *
+ * Xd, Yd, Zd are the device XYZ values
+ * Xdw, Ydw, Zdw are the device XYZ white point values
+ * Xp, Yp, Zp are the PCS XYZ values
+ * Xd50, Yd50, Zd50 are the PCS XYZ white point values
+ *
+ * Xp = Xd * (Xd50 / Xdw)
+ * Yp = Yd * (Yd50 / Ydw)
+ * Zp = Zd * (Zd50 / Zdw)
+ *
+ * </pre>
+ * <p>
+ * Conversion from the PCS to the device would be done by inverting these
+ * equations:
+ * <pre>
+ *
+ * Xd = Xp * (Xdw / Xd50)
+ * Yd = Yp * (Ydw / Yd50)
+ * Zd = Zp * (Zdw / Zd50)
+ *
+ * </pre>
+ * <p>
+ * Note that the media white point tag in an ICC profile is not the same
+ * as the device white point. The media white point tag is expressed in
+ * PCS values and is used to represent the difference between the XYZ of
+ * device illuminant and the XYZ of the device media when measured under
+ * that illuminant. The device white point is expressed as the device
+ * XYZ values corresponding to white displayed on the device. For
+ * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device
+ * will result in a measured device XYZ value of D65. This will not
+ * be the same as the media white point tag XYZ value in the ICC
+ * profile for an sRGB device.
+ * <p>
+ * @param colorvalue a float array with length of at least the number
+ * of components in this ColorSpace.
+ * @return a float array of length 3.
+ * @throws ArrayIndexOutOfBoundsException if array length is not
+ * at least the number of components in this ColorSpace.
+ */
+ public float[] toCIEXYZ(float[] colorvalue) {
+
+ if (this2xyz == null) {
+ ColorTransform[] transformList = new ColorTransform [2];
+ ICC_ColorSpace xyzCS =
+ (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ);
+ PCMM mdl = CMSManager.getModule();
+ try {
+ transformList[0] = mdl.createTransform(
+ thisProfile, ICC_Profile.icRelativeColorimetric,
+ ColorTransform.In);
+ } catch (CMMException e) {
+ transformList[0] = mdl.createTransform(
+ thisProfile, ColorTransform.Any, ColorTransform.In);
+ }
+ transformList[1] = mdl.createTransform(
+ xyzCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
+ this2xyz = mdl.createTransform (transformList);
+ if (needScaleInit) {
+ setComponentScaling();
+ }
+ }
+
+ int nc = this.getNumComponents();
+ short tmp[] = new short[nc];
+ for (int i = 0; i < nc; i++) {
+ tmp[i] = (short)
+ ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f);
+ }
+ tmp = this2xyz.colorConvert(tmp, null);
+ float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f);
+ // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components
+ float[] result = new float [3];
+ for (int i = 0; i < 3; i++) {
+ result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * ALMOST_TWO;
+ }
+ return result;
+ }
+
+
+ /**
+ * Transforms a color value assumed to be in the CS_CIEXYZ conversion
+ * color space into this ColorSpace.
+ * <p>
+ * This method transforms color values using relative colorimetry,
+ * as defined by the ICC Specification. This
+ * means that the XYZ argument values taken by this method are represented
+ * relative to the D50 white point of the CS_CIEXYZ color space.
+ * This representation is useful in a two-step color conversion
+ * process in which colors are transformed from an input color
+ * space to CS_CIEXYZ and then to an output color space. The color
+ * values returned by this method are not those that would produce
+ * the XYZ value passed to the method when measured by a colorimeter.
+ * If you have XYZ values corresponding to measurements made using
+ * current CIE recommended practices, they must be converted to D50
+ * relative values before being passed to this method.
+ * The paragraphs below explain this in more detail.
+ * <p>
+ * The ICC standard uses a device independent color space (DICS) as the
+ * mechanism for converting color from one device to another device. In
+ * this architecture, colors are converted from the source device's color
+ * space to the ICC DICS and then from the ICC DICS to the destination
+ * device's color space. The ICC standard defines device profiles which
+ * contain transforms which will convert between a device's color space
+ * and the ICC DICS. The overall conversion of colors from a source
+ * device to colors of a destination device is done by connecting the
+ * device-to-DICS transform of the profile for the source device to the
+ * DICS-to-device transform of the profile for the destination device.
+ * For this reason, the ICC DICS is commonly referred to as the profile
+ * connection space (PCS). The color space used in the methods
+ * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC
+ * Specification. This is also the color space represented by
+ * ColorSpace.CS_CIEXYZ.
+ * <p>
+ * The XYZ values of a color are often represented as relative to some
+ * white point, so the actual meaning of the XYZ values cannot be known
+ * without knowing the white point of those values. This is known as
+ * relative colorimetry. The PCS uses a white point of D50, so the XYZ
+ * values of the PCS are relative to D50. For example, white in the PCS
+ * will have the XYZ values of D50, which is defined to be X=.9642,
+ * Y=1.000, and Z=0.8249. This white point is commonly used for graphic
+ * arts applications, but others are often used in other applications.
+ * <p>
+ * To quantify the color characteristics of a device such as a printer
+ * or monitor, measurements of XYZ values for particular device colors
+ * are typically made. For purposes of this discussion, the term
+ * device XYZ values is used to mean the XYZ values that would be
+ * measured from device colors using current CIE recommended practices.
+ * <p>
+ * Converting between device XYZ values and the PCS XYZ values taken as
+ * arguments by this method corresponds to converting between the device's
+ * color space, as represented by CIE colorimetric values, and the PCS.
+ * There are many factors involved in this process, some of which are quite
+ * subtle. The most important, however, is the adjustment made to account
+ * for differences between the device's white point and the white point of
+ * the PCS. There are many techniques for doing this and it is the
+ * subject of much current research and controversy. Some commonly used
+ * methods are XYZ scaling, the von Kries transform, and the Bradford
+ * transform. The proper method to use depends upon each particular
+ * application.
+ * <p>
+ * The simplest method is XYZ scaling. In this method each device XYZ
+ * value is converted to a PCS XYZ value by multiplying it by the ratio
+ * of the PCS white point (D50) to the device white point.
+ * <pre>
+ *
+ * Xd, Yd, Zd are the device XYZ values
+ * Xdw, Ydw, Zdw are the device XYZ white point values
+ * Xp, Yp, Zp are the PCS XYZ values
+ * Xd50, Yd50, Zd50 are the PCS XYZ white point values
+ *
+ * Xp = Xd * (Xd50 / Xdw)
+ * Yp = Yd * (Yd50 / Ydw)
+ * Zp = Zd * (Zd50 / Zdw)
+ *
+ * </pre>
+ * <p>
+ * Conversion from the PCS to the device would be done by inverting these
+ * equations:
+ * <pre>
+ *
+ * Xd = Xp * (Xdw / Xd50)
+ * Yd = Yp * (Ydw / Yd50)
+ * Zd = Zp * (Zdw / Zd50)
+ *
+ * </pre>
+ * <p>
+ * Note that the media white point tag in an ICC profile is not the same
+ * as the device white point. The media white point tag is expressed in
+ * PCS values and is used to represent the difference between the XYZ of
+ * device illuminant and the XYZ of the device media when measured under
+ * that illuminant. The device white point is expressed as the device
+ * XYZ values corresponding to white displayed on the device. For
+ * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device
+ * will result in a measured device XYZ value of D65. This will not
+ * be the same as the media white point tag XYZ value in the ICC
+ * profile for an sRGB device.
+ * <p>
+ * <p>
+ * @param colorvalue a float array with length of at least 3.
+ * @return a float array with length equal to the number of
+ * components in this ColorSpace.
+ * @throws ArrayIndexOutOfBoundsException if array length is not
+ * at least 3.
+ */
+ public float[] fromCIEXYZ(float[] colorvalue) {
+
+ if (xyz2this == null) {
+ ColorTransform[] transformList = new ColorTransform [2];
+ ICC_ColorSpace xyzCS =
+ (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ);
+ PCMM mdl = CMSManager.getModule();
+ transformList[0] = mdl.createTransform (
+ xyzCS.getProfile(), ColorTransform.Any, ColorTransform.In);
+ try {
+ transformList[1] = mdl.createTransform(
+ thisProfile, ICC_Profile.icRelativeColorimetric,
+ ColorTransform.Out);
+ } catch (CMMException e) {
+ transformList[1] = CMSManager.getModule().createTransform(
+ thisProfile, ColorTransform.Any, ColorTransform.Out);
+ }
+ xyz2this = mdl.createTransform(transformList);
+ if (needScaleInit) {
+ setComponentScaling();
+ }
+ }
+
+ short tmp[] = new short[3];
+ float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f);
+ float factor = 65535.0f / ALMOST_TWO;
+ // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components
+ for (int i = 0; i < 3; i++) {
+ tmp[i] = (short) ((colorvalue[i] * factor) + 0.5f);
+ }
+ tmp = xyz2this.colorConvert(tmp, null);
+ int nc = this.getNumComponents();
+ float[] result = new float [nc];
+ for (int i = 0; i < nc; i++) {
+ result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) *
+ diffMinMax[i] + minVal[i];
+ }
+ return result;
+ }
+
+ /**
+ * Returns the minimum normalized color component value for the
+ * specified component. For TYPE_XYZ spaces, this method returns
+ * minimum values of 0.0 for all components. For TYPE_Lab spaces,
+ * this method returns 0.0 for L and -128.0 for a and b components.
+ * This is consistent with the encoding of the XYZ and Lab Profile
+ * Connection Spaces in the ICC specification. For all other types, this
+ * method returns 0.0 for all components. When using an ICC_ColorSpace
+ * with a profile that requires different minimum component values,
+ * it is necessary to subclass this class and override this method.
+ * @param component The component index.
+ * @return The minimum normalized component value.
+ * @throws IllegalArgumentException if component is less than 0 or
+ * greater than numComponents - 1.
+ * @since 1.4
+ */
+ public float getMinValue(int component) {
+ if ((component < 0) || (component > this.getNumComponents() - 1)) {
+ throw new IllegalArgumentException(
+ "Component index out of range: + component");
+ }
+ return minVal[component];
+ }
+
+ /**
+ * Returns the maximum normalized color component value for the
+ * specified component. For TYPE_XYZ spaces, this method returns
+ * maximum values of 1.0 + (32767.0 / 32768.0) for all components.
+ * For TYPE_Lab spaces,
+ * this method returns 100.0 for L and 127.0 for a and b components.
+ * This is consistent with the encoding of the XYZ and Lab Profile
+ * Connection Spaces in the ICC specification. For all other types, this
+ * method returns 1.0 for all components. When using an ICC_ColorSpace
+ * with a profile that requires different maximum component values,
+ * it is necessary to subclass this class and override this method.
+ * @param component The component index.
+ * @return The maximum normalized component value.
+ * @throws IllegalArgumentException if component is less than 0 or
+ * greater than numComponents - 1.
+ * @since 1.4
+ */
+ public float getMaxValue(int component) {
+ if ((component < 0) || (component > this.getNumComponents() - 1)) {
+ throw new IllegalArgumentException(
+ "Component index out of range: + component");
+ }
+ return maxVal[component];
+ }
+
+ private void setMinMax() {
+ int nc = this.getNumComponents();
+ int type = this.getType();
+ minVal = new float[nc];
+ maxVal = new float[nc];
+ if (type == ColorSpace.TYPE_Lab) {
+ minVal[0] = 0.0f; // L
+ maxVal[0] = 100.0f;
+ minVal[1] = -128.0f; // a
+ maxVal[1] = 127.0f;
+ minVal[2] = -128.0f; // b
+ maxVal[2] = 127.0f;
+ } else if (type == ColorSpace.TYPE_XYZ) {
+ minVal[0] = minVal[1] = minVal[2] = 0.0f; // X, Y, Z
+ maxVal[0] = maxVal[1] = maxVal[2] = 1.0f + (32767.0f/ 32768.0f);
+ } else {
+ for (int i = 0; i < nc; i++) {
+ minVal[i] = 0.0f;
+ maxVal[i] = 1.0f;
+ }
+ }
+ }
+
+ private void setComponentScaling() {
+ int nc = this.getNumComponents();
+ diffMinMax = new float[nc];
+ invDiffMinMax = new float[nc];
+ for (int i = 0; i < nc; i++) {
+ minVal[i] = this.getMinValue(i); // in case getMinVal is overridden
+ maxVal[i] = this.getMaxValue(i); // in case getMaxVal is overridden
+ diffMinMax[i] = maxVal[i] - minVal[i];
+ invDiffMinMax[i] = 65535.0f / diffMinMax[i];
+ }
+ needScaleInit = false;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/color/ICC_Profile.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,2003 @@
+/*
+ * Portions Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.color;
+
+import sun.java2d.cmm.PCMM;
+import sun.java2d.cmm.CMSManager;
+import sun.java2d.cmm.ProfileDeferralMgr;
+import sun.java2d.cmm.ProfileDeferralInfo;
+import sun.java2d.cmm.ProfileActivator;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamException;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+import java.util.StringTokenizer;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * A representation of color profile data for device independent and
+ * device dependent color spaces based on the International Color
+ * Consortium Specification ICC.1:2001-12, File Format for Color Profiles,
+ * (see <A href="http://www.color.org"> http://www.color.org</A>).
+ * <p>
+ * An ICC_ColorSpace object can be constructed from an appropriate
+ * ICC_Profile.
+ * Typically, an ICC_ColorSpace would be associated with an ICC
+ * Profile which is either an input, display, or output profile (see
+ * the ICC specification). There are also device link, abstract,
+ * color space conversion, and named color profiles. These are less
+ * useful for tagging a color or image, but are useful for other
+ * purposes (in particular device link profiles can provide improved
+ * performance for converting from one device's color space to
+ * another's).
+ * <p>
+ * ICC Profiles represent transformations from the color space of
+ * the profile (e.g. a monitor) to a Profile Connection Space (PCS).
+ * Profiles of interest for tagging images or colors have a PCS
+ * which is one of the two specific device independent
+ * spaces (one CIEXYZ space and one CIELab space) defined in the
+ * ICC Profile Format Specification. Most profiles of interest
+ * either have invertible transformations or explicitly specify
+ * transformations going both directions.
+ * <p>
+ * @see ICC_ColorSpace
+ */
+
+
+public class ICC_Profile implements Serializable {
+
+ private static final long serialVersionUID = -3938515861990936766L;
+
+ transient long ID;
+
+ private transient ProfileDeferralInfo deferralInfo;
+ private transient ProfileActivator profileActivator;
+
+ // Registry of singleton profile objects for specific color spaces
+ // defined in the ColorSpace class (e.g. CS_sRGB), see
+ // getInstance(int cspace) factory method.
+ private static ICC_Profile sRGBprofile;
+ private static ICC_Profile XYZprofile;
+ private static ICC_Profile PYCCprofile;
+ private static ICC_Profile GRAYprofile;
+ private static ICC_Profile LINEAR_RGBprofile;
+
+
+ /**
+ * Profile class is input.
+ */
+ public static final int CLASS_INPUT = 0;
+
+ /**
+ * Profile class is display.
+ */
+ public static final int CLASS_DISPLAY = 1;
+
+ /**
+ * Profile class is output.
+ */
+ public static final int CLASS_OUTPUT = 2;
+
+ /**
+ * Profile class is device link.
+ */
+ public static final int CLASS_DEVICELINK = 3;
+
+ /**
+ * Profile class is color space conversion.
+ */
+ public static final int CLASS_COLORSPACECONVERSION = 4;
+
+ /**
+ * Profile class is abstract.
+ */
+ public static final int CLASS_ABSTRACT = 5;
+
+ /**
+ * Profile class is named color.
+ */
+ public static final int CLASS_NAMEDCOLOR = 6;
+
+
+ /**
+ * ICC Profile Color Space Type Signature: 'XYZ '.
+ */
+ public static final int icSigXYZData = 0x58595A20; /* 'XYZ ' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'Lab '.
+ */
+ public static final int icSigLabData = 0x4C616220; /* 'Lab ' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'Luv '.
+ */
+ public static final int icSigLuvData = 0x4C757620; /* 'Luv ' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'YCbr'.
+ */
+ public static final int icSigYCbCrData = 0x59436272; /* 'YCbr' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'Yxy '.
+ */
+ public static final int icSigYxyData = 0x59787920; /* 'Yxy ' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'RGB '.
+ */
+ public static final int icSigRgbData = 0x52474220; /* 'RGB ' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'GRAY'.
+ */
+ public static final int icSigGrayData = 0x47524159; /* 'GRAY' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'HSV'.
+ */
+ public static final int icSigHsvData = 0x48535620; /* 'HSV ' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'HLS'.
+ */
+ public static final int icSigHlsData = 0x484C5320; /* 'HLS ' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'CMYK'.
+ */
+ public static final int icSigCmykData = 0x434D594B; /* 'CMYK' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'CMY '.
+ */
+ public static final int icSigCmyData = 0x434D5920; /* 'CMY ' */
+
+ /**
+ * ICC Profile Color Space Type Signature: '2CLR'.
+ */
+ public static final int icSigSpace2CLR = 0x32434C52; /* '2CLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: '3CLR'.
+ */
+ public static final int icSigSpace3CLR = 0x33434C52; /* '3CLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: '4CLR'.
+ */
+ public static final int icSigSpace4CLR = 0x34434C52; /* '4CLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: '5CLR'.
+ */
+ public static final int icSigSpace5CLR = 0x35434C52; /* '5CLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: '6CLR'.
+ */
+ public static final int icSigSpace6CLR = 0x36434C52; /* '6CLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: '7CLR'.
+ */
+ public static final int icSigSpace7CLR = 0x37434C52; /* '7CLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: '8CLR'.
+ */
+ public static final int icSigSpace8CLR = 0x38434C52; /* '8CLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: '9CLR'.
+ */
+ public static final int icSigSpace9CLR = 0x39434C52; /* '9CLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'ACLR'.
+ */
+ public static final int icSigSpaceACLR = 0x41434C52; /* 'ACLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'BCLR'.
+ */
+ public static final int icSigSpaceBCLR = 0x42434C52; /* 'BCLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'CCLR'.
+ */
+ public static final int icSigSpaceCCLR = 0x43434C52; /* 'CCLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'DCLR'.
+ */
+ public static final int icSigSpaceDCLR = 0x44434C52; /* 'DCLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'ECLR'.
+ */
+ public static final int icSigSpaceECLR = 0x45434C52; /* 'ECLR' */
+
+ /**
+ * ICC Profile Color Space Type Signature: 'FCLR'.
+ */
+ public static final int icSigSpaceFCLR = 0x46434C52; /* 'FCLR' */
+
+
+ /**
+ * ICC Profile Class Signature: 'scnr'.
+ */
+ public static final int icSigInputClass = 0x73636E72; /* 'scnr' */
+
+ /**
+ * ICC Profile Class Signature: 'mntr'.
+ */
+ public static final int icSigDisplayClass = 0x6D6E7472; /* 'mntr' */
+
+ /**
+ * ICC Profile Class Signature: 'prtr'.
+ */
+ public static final int icSigOutputClass = 0x70727472; /* 'prtr' */
+
+ /**
+ * ICC Profile Class Signature: 'link'.
+ */
+ public static final int icSigLinkClass = 0x6C696E6B; /* 'link' */
+
+ /**
+ * ICC Profile Class Signature: 'abst'.
+ */
+ public static final int icSigAbstractClass = 0x61627374; /* 'abst' */
+
+ /**
+ * ICC Profile Class Signature: 'spac'.
+ */
+ public static final int icSigColorSpaceClass = 0x73706163; /* 'spac' */
+
+ /**
+ * ICC Profile Class Signature: 'nmcl'.
+ */
+ public static final int icSigNamedColorClass = 0x6e6d636c; /* 'nmcl' */
+
+
+ /**
+ * ICC Profile Rendering Intent: Perceptual.
+ */
+ public static final int icPerceptual = 0;
+
+ /**
+ * ICC Profile Rendering Intent: RelativeColorimetric.
+ */
+ public static final int icRelativeColorimetric = 1;
+
+ /**
+ * ICC Profile Rendering Intent: Media-RelativeColorimetric.
+ * @since 1.5
+ */
+ public static final int icMediaRelativeColorimetric = 1;
+
+ /**
+ * ICC Profile Rendering Intent: Saturation.
+ */
+ public static final int icSaturation = 2;
+
+ /**
+ * ICC Profile Rendering Intent: AbsoluteColorimetric.
+ */
+ public static final int icAbsoluteColorimetric = 3;
+
+ /**
+ * ICC Profile Rendering Intent: ICC-AbsoluteColorimetric.
+ * @since 1.5
+ */
+ public static final int icICCAbsoluteColorimetric = 3;
+
+
+ /**
+ * ICC Profile Tag Signature: 'head' - special.
+ */
+ public static final int icSigHead = 0x68656164; /* 'head' - special */
+
+ /**
+ * ICC Profile Tag Signature: 'A2B0'.
+ */
+ public static final int icSigAToB0Tag = 0x41324230; /* 'A2B0' */
+
+ /**
+ * ICC Profile Tag Signature: 'A2B1'.
+ */
+ public static final int icSigAToB1Tag = 0x41324231; /* 'A2B1' */
+
+ /**
+ * ICC Profile Tag Signature: 'A2B2'.
+ */
+ public static final int icSigAToB2Tag = 0x41324232; /* 'A2B2' */
+
+ /**
+ * ICC Profile Tag Signature: 'bXYZ'.
+ */
+ public static final int icSigBlueColorantTag = 0x6258595A; /* 'bXYZ' */
+
+ /**
+ * ICC Profile Tag Signature: 'bXYZ'.
+ * @since 1.5
+ */
+ public static final int icSigBlueMatrixColumnTag = 0x6258595A; /* 'bXYZ' */
+
+ /**
+ * ICC Profile Tag Signature: 'bTRC'.
+ */
+ public static final int icSigBlueTRCTag = 0x62545243; /* 'bTRC' */
+
+ /**
+ * ICC Profile Tag Signature: 'B2A0'.
+ */
+ public static final int icSigBToA0Tag = 0x42324130; /* 'B2A0' */
+
+ /**
+ * ICC Profile Tag Signature: 'B2A1'.
+ */
+ public static final int icSigBToA1Tag = 0x42324131; /* 'B2A1' */
+
+ /**
+ * ICC Profile Tag Signature: 'B2A2'.
+ */
+ public static final int icSigBToA2Tag = 0x42324132; /* 'B2A2' */
+
+ /**
+ * ICC Profile Tag Signature: 'calt'.
+ */
+ public static final int icSigCalibrationDateTimeTag = 0x63616C74;
+ /* 'calt' */
+
+ /**
+ * ICC Profile Tag Signature: 'targ'.
+ */
+ public static final int icSigCharTargetTag = 0x74617267; /* 'targ' */
+
+ /**
+ * ICC Profile Tag Signature: 'cprt'.
+ */
+ public static final int icSigCopyrightTag = 0x63707274; /* 'cprt' */
+
+ /**
+ * ICC Profile Tag Signature: 'crdi'.
+ */
+ public static final int icSigCrdInfoTag = 0x63726469; /* 'crdi' */
+
+ /**
+ * ICC Profile Tag Signature: 'dmnd'.
+ */
+ public static final int icSigDeviceMfgDescTag = 0x646D6E64; /* 'dmnd' */
+
+ /**
+ * ICC Profile Tag Signature: 'dmdd'.
+ */
+ public static final int icSigDeviceModelDescTag = 0x646D6464; /* 'dmdd' */
+
+ /**
+ * ICC Profile Tag Signature: 'devs'.
+ */
+ public static final int icSigDeviceSettingsTag = 0x64657673; /* 'devs' */
+
+ /**
+ * ICC Profile Tag Signature: 'gamt'.
+ */
+ public static final int icSigGamutTag = 0x67616D74; /* 'gamt' */
+
+ /**
+ * ICC Profile Tag Signature: 'kTRC'.
+ */
+ public static final int icSigGrayTRCTag = 0x6b545243; /* 'kTRC' */
+
+ /**
+ * ICC Profile Tag Signature: 'gXYZ'.
+ */
+ public static final int icSigGreenColorantTag = 0x6758595A; /* 'gXYZ' */
+
+ /**
+ * ICC Profile Tag Signature: 'gXYZ'.
+ * @since 1.5
+ */
+ public static final int icSigGreenMatrixColumnTag = 0x6758595A;/* 'gXYZ' */
+
+ /**
+ * ICC Profile Tag Signature: 'gTRC'.
+ */
+ public static final int icSigGreenTRCTag = 0x67545243; /* 'gTRC' */
+
+ /**
+ * ICC Profile Tag Signature: 'lumi'.
+ */
+ public static final int icSigLuminanceTag = 0x6C756d69; /* 'lumi' */
+
+ /**
+ * ICC Profile Tag Signature: 'meas'.
+ */
+ public static final int icSigMeasurementTag = 0x6D656173; /* 'meas' */
+
+ /**
+ * ICC Profile Tag Signature: 'bkpt'.
+ */
+ public static final int icSigMediaBlackPointTag = 0x626B7074; /* 'bkpt' */
+
+ /**
+ * ICC Profile Tag Signature: 'wtpt'.
+ */
+ public static final int icSigMediaWhitePointTag = 0x77747074; /* 'wtpt' */
+
+ /**
+ * ICC Profile Tag Signature: 'ncl2'.
+ */
+ public static final int icSigNamedColor2Tag = 0x6E636C32; /* 'ncl2' */
+
+ /**
+ * ICC Profile Tag Signature: 'resp'.
+ */
+ public static final int icSigOutputResponseTag = 0x72657370; /* 'resp' */
+
+ /**
+ * ICC Profile Tag Signature: 'pre0'.
+ */
+ public static final int icSigPreview0Tag = 0x70726530; /* 'pre0' */
+
+ /**
+ * ICC Profile Tag Signature: 'pre1'.
+ */
+ public static final int icSigPreview1Tag = 0x70726531; /* 'pre1' */
+
+ /**
+ * ICC Profile Tag Signature: 'pre2'.
+ */
+ public static final int icSigPreview2Tag = 0x70726532; /* 'pre2' */
+
+ /**
+ * ICC Profile Tag Signature: 'desc'.
+ */
+ public static final int icSigProfileDescriptionTag = 0x64657363;
+ /* 'desc' */
+
+ /**
+ * ICC Profile Tag Signature: 'pseq'.
+ */
+ public static final int icSigProfileSequenceDescTag = 0x70736571;
+ /* 'pseq' */
+
+ /**
+ * ICC Profile Tag Signature: 'psd0'.
+ */
+ public static final int icSigPs2CRD0Tag = 0x70736430; /* 'psd0' */
+
+ /**
+ * ICC Profile Tag Signature: 'psd1'.
+ */
+ public static final int icSigPs2CRD1Tag = 0x70736431; /* 'psd1' */
+
+ /**
+ * ICC Profile Tag Signature: 'psd2'.
+ */
+ public static final int icSigPs2CRD2Tag = 0x70736432; /* 'psd2' */
+
+ /**
+ * ICC Profile Tag Signature: 'psd3'.
+ */
+ public static final int icSigPs2CRD3Tag = 0x70736433; /* 'psd3' */
+
+ /**
+ * ICC Profile Tag Signature: 'ps2s'.
+ */
+ public static final int icSigPs2CSATag = 0x70733273; /* 'ps2s' */
+
+ /**
+ * ICC Profile Tag Signature: 'ps2i'.
+ */
+ public static final int icSigPs2RenderingIntentTag = 0x70733269;
+ /* 'ps2i' */
+
+ /**
+ * ICC Profile Tag Signature: 'rXYZ'.
+ */
+ public static final int icSigRedColorantTag = 0x7258595A; /* 'rXYZ' */
+
+ /**
+ * ICC Profile Tag Signature: 'rXYZ'.
+ * @since 1.5
+ */
+ public static final int icSigRedMatrixColumnTag = 0x7258595A; /* 'rXYZ' */
+
+ /**
+ * ICC Profile Tag Signature: 'rTRC'.
+ */
+ public static final int icSigRedTRCTag = 0x72545243; /* 'rTRC' */
+
+ /**
+ * ICC Profile Tag Signature: 'scrd'.
+ */
+ public static final int icSigScreeningDescTag = 0x73637264; /* 'scrd' */
+
+ /**
+ * ICC Profile Tag Signature: 'scrn'.
+ */
+ public static final int icSigScreeningTag = 0x7363726E; /* 'scrn' */
+
+ /**
+ * ICC Profile Tag Signature: 'tech'.
+ */
+ public static final int icSigTechnologyTag = 0x74656368; /* 'tech' */
+
+ /**
+ * ICC Profile Tag Signature: 'bfd '.
+ */
+ public static final int icSigUcrBgTag = 0x62666420; /* 'bfd ' */
+
+ /**
+ * ICC Profile Tag Signature: 'vued'.
+ */
+ public static final int icSigViewingCondDescTag = 0x76756564; /* 'vued' */
+
+ /**
+ * ICC Profile Tag Signature: 'view'.
+ */
+ public static final int icSigViewingConditionsTag = 0x76696577;/* 'view' */
+
+ /**
+ * ICC Profile Tag Signature: 'chrm'.
+ */
+ public static final int icSigChromaticityTag = 0x6368726d; /* 'chrm' */
+
+ /**
+ * ICC Profile Tag Signature: 'chad'.
+ * @since 1.5
+ */
+ public static final int icSigChromaticAdaptationTag = 0x63686164;/* 'chad' */
+
+ /**
+ * ICC Profile Tag Signature: 'clro'.
+ * @since 1.5
+ */
+ public static final int icSigColorantOrderTag = 0x636C726F; /* 'clro' */
+
+ /**
+ * ICC Profile Tag Signature: 'clrt'.
+ * @since 1.5
+ */
+ public static final int icSigColorantTableTag = 0x636C7274; /* 'clrt' */
+
+
+ /**
+ * ICC Profile Header Location: profile size in bytes.
+ */
+ public static final int icHdrSize = 0; /* Profile size in bytes */
+
+ /**
+ * ICC Profile Header Location: CMM for this profile.
+ */
+ public static final int icHdrCmmId = 4; /* CMM for this profile */
+
+ /**
+ * ICC Profile Header Location: format version number.
+ */
+ public static final int icHdrVersion = 8; /* Format version number */
+
+ /**
+ * ICC Profile Header Location: type of profile.
+ */
+ public static final int icHdrDeviceClass = 12; /* Type of profile */
+
+ /**
+ * ICC Profile Header Location: color space of data.
+ */
+ public static final int icHdrColorSpace = 16; /* Color space of data */
+
+ /**
+ * ICC Profile Header Location: PCS - XYZ or Lab only.
+ */
+ public static final int icHdrPcs = 20; /* PCS - XYZ or Lab only */
+
+ /**
+ * ICC Profile Header Location: date profile was created.
+ */
+ public static final int icHdrDate = 24; /* Date profile was created */
+
+ /**
+ * ICC Profile Header Location: icMagicNumber.
+ */
+ public static final int icHdrMagic = 36; /* icMagicNumber */
+
+ /**
+ * ICC Profile Header Location: primary platform.
+ */
+ public static final int icHdrPlatform = 40; /* Primary Platform */
+
+ /**
+ * ICC Profile Header Location: various bit settings.
+ */
+ public static final int icHdrFlags = 44; /* Various bit settings */
+
+ /**
+ * ICC Profile Header Location: device manufacturer.
+ */
+ public static final int icHdrManufacturer = 48; /* Device manufacturer */
+
+ /**
+ * ICC Profile Header Location: device model number.
+ */
+ public static final int icHdrModel = 52; /* Device model number */
+
+ /**
+ * ICC Profile Header Location: device attributes.
+ */
+ public static final int icHdrAttributes = 56; /* Device attributes */
+
+ /**
+ * ICC Profile Header Location: rendering intent.
+ */
+ public static final int icHdrRenderingIntent = 64; /* Rendering intent */
+
+ /**
+ * ICC Profile Header Location: profile illuminant.
+ */
+ public static final int icHdrIlluminant = 68; /* Profile illuminant */
+
+ /**
+ * ICC Profile Header Location: profile creator.
+ */
+ public static final int icHdrCreator = 80; /* Profile creator */
+
+ /**
+ * ICC Profile Header Location: profile's ID.
+ * @since 1.5
+ */
+ public static final int icHdrProfileID = 84; /* Profile's ID */
+
+
+ /**
+ * ICC Profile Constant: tag type signaturE.
+ */
+ public static final int icTagType = 0; /* tag type signature */
+
+ /**
+ * ICC Profile Constant: reserved.
+ */
+ public static final int icTagReserved = 4; /* reserved */
+
+ /**
+ * ICC Profile Constant: curveType count.
+ */
+ public static final int icCurveCount = 8; /* curveType count */
+
+ /**
+ * ICC Profile Constant: curveType data.
+ */
+ public static final int icCurveData = 12; /* curveType data */
+
+ /**
+ * ICC Profile Constant: XYZNumber X.
+ */
+ public static final int icXYZNumberX = 8; /* XYZNumber X */
+
+
+ /**
+ * Constructs an ICC_Profile object with a given ID.
+ */
+ ICC_Profile(long ID) {
+ this.ID = ID;
+ }
+
+
+ /**
+ * Constructs an ICC_Profile object whose loading will be deferred.
+ * The ID will be 0 until the profile is loaded.
+ */
+ ICC_Profile(ProfileDeferralInfo pdi) {
+ this.deferralInfo = pdi;
+ this.profileActivator = new ProfileActivator() {
+ public void activate() {
+ activateDeferredProfile();
+ }
+ };
+ ProfileDeferralMgr.registerDeferral(this.profileActivator);
+ }
+
+
+ /**
+ * Frees the resources associated with an ICC_Profile object.
+ */
+ protected void finalize () {
+ if (ID != 0) {
+ CMSManager.getModule().freeProfile(ID);
+ } else if (profileActivator != null) {
+ ProfileDeferralMgr.unregisterDeferral(profileActivator);
+ }
+ }
+
+
+ /**
+ * Constructs an ICC_Profile object corresponding to the data in
+ * a byte array. Throws an IllegalArgumentException if the data
+ * does not correspond to a valid ICC Profile.
+ * @param data the specified ICC Profile data
+ * @return an <code>ICC_Profile</code> object corresponding to
+ * the data in the specified <code>data</code> array.
+ */
+ public static ICC_Profile getInstance(byte[] data) {
+ ICC_Profile thisProfile;
+
+ long theID;
+
+ if (ProfileDeferralMgr.deferring) {
+ ProfileDeferralMgr.activateProfiles();
+ }
+
+ try {
+ theID = CMSManager.getModule().loadProfile(data);
+ } catch (CMMException c) {
+ throw new IllegalArgumentException("Invalid ICC Profile Data");
+ }
+
+ try {
+ if ((getColorSpaceType (theID) == ColorSpace.TYPE_GRAY) &&
+ (getData (theID, icSigMediaWhitePointTag) != null) &&
+ (getData (theID, icSigGrayTRCTag) != null)) {
+ thisProfile = new ICC_ProfileGray (theID);
+ }
+ else if ((getColorSpaceType (theID) == ColorSpace.TYPE_RGB) &&
+ (getData (theID, icSigMediaWhitePointTag) != null) &&
+ (getData (theID, icSigRedColorantTag) != null) &&
+ (getData (theID, icSigGreenColorantTag) != null) &&
+ (getData (theID, icSigBlueColorantTag) != null) &&
+ (getData (theID, icSigRedTRCTag) != null) &&
+ (getData (theID, icSigGreenTRCTag) != null) &&
+ (getData (theID, icSigBlueTRCTag) != null)) {
+ thisProfile = new ICC_ProfileRGB (theID);
+ }
+ else {
+ thisProfile = new ICC_Profile (theID);
+ }
+ } catch (CMMException c) {
+ thisProfile = new ICC_Profile (theID);
+ }
+ return thisProfile;
+ }
+
+
+
+ /**
+ * Constructs an ICC_Profile corresponding to one of the specific color
+ * spaces defined by the ColorSpace class (for example CS_sRGB).
+ * Throws an IllegalArgumentException if cspace is not one of the
+ * defined color spaces.
+ *
+ * @param cspace the type of color space to create a profile for.
+ * The specified type is one of the color
+ * space constants defined in the <CODE>ColorSpace</CODE> class.
+ *
+ * @return an <code>ICC_Profile</code> object corresponding to
+ * the specified <code>ColorSpace</code> type.
+ * @exception IllegalArgumentException If <CODE>cspace</CODE> is not
+ * one of the predefined color space types.
+ */
+ public static ICC_Profile getInstance (int cspace) {
+ ICC_Profile thisProfile = null;
+ String fileName;
+
+ switch (cspace) {
+ case ColorSpace.CS_sRGB:
+ synchronized(ICC_Profile.class) {
+ if (sRGBprofile == null) {
+ try {
+ /*
+ * Deferral is only used for standard profiles.
+ * Enabling the appropriate access privileges is handled
+ * at a lower level.
+ */
+ sRGBprofile = getDeferredInstance(
+ new ProfileDeferralInfo("sRGB.pf",
+ ColorSpace.TYPE_RGB,
+ 3, CLASS_DISPLAY));
+ } catch (IOException e) {
+ throw new IllegalArgumentException(
+ "Can't load standard profile: sRGB.pf");
+ }
+ }
+ thisProfile = sRGBprofile;
+ }
+
+ break;
+
+ case ColorSpace.CS_CIEXYZ:
+ synchronized(ICC_Profile.class) {
+ if (XYZprofile == null) {
+ XYZprofile = getStandardProfile("CIEXYZ.pf");
+ }
+ thisProfile = XYZprofile;
+ }
+
+ break;
+
+ case ColorSpace.CS_PYCC:
+ synchronized(ICC_Profile.class) {
+ if (PYCCprofile == null) {
+ PYCCprofile = getStandardProfile("PYCC.pf");
+ }
+ thisProfile = PYCCprofile;
+ }
+
+ break;
+
+ case ColorSpace.CS_GRAY:
+ synchronized(ICC_Profile.class) {
+ if (GRAYprofile == null) {
+ GRAYprofile = getStandardProfile("GRAY.pf");
+ }
+ thisProfile = GRAYprofile;
+ }
+
+ break;
+
+ case ColorSpace.CS_LINEAR_RGB:
+ synchronized(ICC_Profile.class) {
+ if (LINEAR_RGBprofile == null) {
+ LINEAR_RGBprofile = getStandardProfile("LINEAR_RGB.pf");
+ }
+ thisProfile = LINEAR_RGBprofile;
+ }
+
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown color space");
+ }
+
+ return thisProfile;
+ }
+
+ /* This asserts system privileges, so is used only for the
+ * standard profiles.
+ */
+ private static ICC_Profile getStandardProfile(final String name) {
+
+ return (ICC_Profile) AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Object run() {
+ ICC_Profile p = null;
+ try {
+ p = getInstance (name);
+ } catch (IOException ex) {
+ throw new IllegalArgumentException(
+ "Can't load standard profile: " + name);
+ }
+ return p;
+ }
+ });
+ }
+
+ /**
+ * Constructs an ICC_Profile corresponding to the data in a file.
+ * fileName may be an absolute or a relative file specification.
+ * Relative file names are looked for in several places: first, relative
+ * to any directories specified by the java.iccprofile.path property;
+ * second, relative to any directories specified by the java.class.path
+ * property; finally, in a directory used to store profiles always
+ * available, such as the profile for sRGB. Built-in profiles use .pf as
+ * the file name extension for profiles, e.g. sRGB.pf.
+ * This method throws an IOException if the specified file cannot be
+ * opened or if an I/O error occurs while reading the file. It throws
+ * an IllegalArgumentException if the file does not contain valid ICC
+ * Profile data.
+ * @param fileName The file that contains the data for the profile.
+ *
+ * @return an <code>ICC_Profile</code> object corresponding to
+ * the data in the specified file.
+ * @exception IOException If the specified file cannot be opened or
+ * an I/O error occurs while reading the file.
+ *
+ * @exception IllegalArgumentException If the file does not
+ * contain valid ICC Profile data.
+ *
+ * @exception SecurityException If a security manager is installed
+ * and it does not permit read access to the given file.
+ */
+ public static ICC_Profile getInstance(String fileName) throws IOException {
+ ICC_Profile thisProfile;
+ FileInputStream fis;
+
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkRead(fileName);
+ }
+
+ if ((fis = openProfile(fileName)) == null) {
+ throw new IOException("Cannot open file " + fileName);
+ }
+
+ thisProfile = getInstance(fis);
+
+ fis.close(); /* close the file */
+
+ return thisProfile;
+ }
+
+
+ /**
+ * Constructs an ICC_Profile corresponding to the data in an InputStream.
+ * This method throws an IllegalArgumentException if the stream does not
+ * contain valid ICC Profile data. It throws an IOException if an I/O
+ * error occurs while reading the stream.
+ * @param s The input stream from which to read the profile data.
+ *
+ * @return an <CODE>ICC_Profile</CODE> object corresponding to the
+ * data in the specified <code>InputStream</code>.
+ *
+ * @exception IOException If an I/O error occurs while reading the stream.
+ *
+ * @exception IllegalArgumentException If the stream does not
+ * contain valid ICC Profile data.
+ */
+ public static ICC_Profile getInstance(InputStream s) throws IOException {
+ byte profileData[];
+
+ if (s instanceof ProfileDeferralInfo) {
+ /* hack to detect profiles whose loading can be deferred */
+ return getDeferredInstance((ProfileDeferralInfo) s);
+ }
+
+ if ((profileData = getProfileDataFromStream(s)) == null) {
+ throw new IllegalArgumentException("Invalid ICC Profile Data");
+ }
+
+ return getInstance(profileData);
+ }
+
+
+ static byte[] getProfileDataFromStream(InputStream s) throws IOException {
+ byte profileData[];
+ int profileSize;
+
+ byte header[] = new byte[128];
+ int bytestoread = 128;
+ int bytesread = 0;
+ int n;
+
+ while (bytestoread != 0) {
+ if ((n = s.read(header, bytesread, bytestoread)) < 0) {
+ return null;
+ }
+ bytesread += n;
+ bytestoread -= n;
+ }
+ if (header[36] != 0x61 || header[37] != 0x63 ||
+ header[38] != 0x73 || header[39] != 0x70) {
+ return null; /* not a valid profile */
+ }
+ profileSize = ((header[0] & 0xff) << 24) |
+ ((header[1] & 0xff) << 16) |
+ ((header[2] & 0xff) << 8) |
+ (header[3] & 0xff);
+ profileData = new byte[profileSize];
+ System.arraycopy(header, 0, profileData, 0, 128);
+ bytestoread = profileSize - 128;
+ bytesread = 128;
+ while (bytestoread != 0) {
+ if ((n = s.read(profileData, bytesread, bytestoread)) < 0) {
+ return null;
+ }
+ bytesread += n;
+ bytestoread -= n;
+ }
+
+ return profileData;
+ }
+
+
+ /**
+ * Constructs an ICC_Profile for which the actual loading of the
+ * profile data from a file and the initialization of the CMM should
+ * be deferred as long as possible.
+ * Deferral is only used for standard profiles.
+ * If deferring is disabled, then getStandardProfile() ensures
+ * that all of the appropriate access privileges are granted
+ * when loading this profile.
+ * If deferring is enabled, then the deferred activation
+ * code will take care of access privileges.
+ * @see activateDeferredProfile()
+ */
+ static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi)
+ throws IOException {
+
+ if (!ProfileDeferralMgr.deferring) {
+ return getStandardProfile(pdi.filename);
+ }
+ if (pdi.colorSpaceType == ColorSpace.TYPE_RGB) {
+ return new ICC_ProfileRGB(pdi);
+ } else if (pdi.colorSpaceType == ColorSpace.TYPE_GRAY) {
+ return new ICC_ProfileGray(pdi);
+ } else {
+ return new ICC_Profile(pdi);
+ }
+ }
+
+
+ void activateDeferredProfile() {
+ byte profileData[];
+ FileInputStream fis;
+ String fileName = deferralInfo.filename;
+
+ profileActivator = null;
+ deferralInfo = null;
+ if ((fis = openProfile(fileName)) == null) {
+ throw new IllegalArgumentException("Cannot open file " + fileName);
+ }
+ try {
+ profileData = getProfileDataFromStream(fis);
+ fis.close(); /* close the file */
+ }
+ catch (IOException e) {
+ throw new IllegalArgumentException("Invalid ICC Profile Data" +
+ fileName);
+ }
+ if (profileData == null) {
+ throw new IllegalArgumentException("Invalid ICC Profile Data" +
+ fileName);
+ }
+ try {
+ ID = CMSManager.getModule().loadProfile(profileData);
+ } catch (CMMException c) {
+ throw new IllegalArgumentException("Invalid ICC Profile Data" +
+ fileName);
+ }
+ }
+
+
+ /**
+ * Returns profile major version.
+ * @return The major version of the profile.
+ */
+ public int getMajorVersion() {
+ byte[] theHeader;
+
+ theHeader = getData(icSigHead); /* getData will activate deferred
+ profiles if necessary */
+
+ return (int) theHeader[8];
+ }
+
+ /**
+ * Returns profile minor version.
+ * @return The minor version of the profile.
+ */
+ public int getMinorVersion() {
+ byte[] theHeader;
+
+ theHeader = getData(icSigHead); /* getData will activate deferred
+ profiles if necessary */
+
+ return (int) theHeader[9];
+ }
+
+ /**
+ * Returns the profile class.
+ * @return One of the predefined profile class constants.
+ */
+ public int getProfileClass() {
+ byte[] theHeader;
+ int theClassSig, theClass;
+
+ if (deferralInfo != null) {
+ return deferralInfo.profileClass; /* Need to have this info for
+ ICC_ColorSpace without
+ causing a deferred profile
+ to be loaded */
+ }
+
+ theHeader = getData(icSigHead);
+
+ theClassSig = intFromBigEndian (theHeader, icHdrDeviceClass);
+
+ switch (theClassSig) {
+ case icSigInputClass:
+ theClass = CLASS_INPUT;
+ break;
+
+ case icSigDisplayClass:
+ theClass = CLASS_DISPLAY;
+ break;
+
+ case icSigOutputClass:
+ theClass = CLASS_OUTPUT;
+ break;
+
+ case icSigLinkClass:
+ theClass = CLASS_DEVICELINK;
+ break;
+
+ case icSigColorSpaceClass:
+ theClass = CLASS_COLORSPACECONVERSION;
+ break;
+
+ case icSigAbstractClass:
+ theClass = CLASS_ABSTRACT;
+ break;
+
+ case icSigNamedColorClass:
+ theClass = CLASS_NAMEDCOLOR;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown profile class");
+ }
+
+ return theClass;
+ }
+
+ /**
+ * Returns the color space type. Returns one of the color space type
+ * constants defined by the ColorSpace class. This is the
+ * "input" color space of the profile. The type defines the
+ * number of components of the color space and the interpretation,
+ * e.g. TYPE_RGB identifies a color space with three components - red,
+ * green, and blue. It does not define the particular color
+ * characteristics of the space, e.g. the chromaticities of the
+ * primaries.
+ * @return One of the color space type constants defined in the
+ * <CODE>ColorSpace</CODE> class.
+ */
+ public int getColorSpaceType() {
+ if (deferralInfo != null) {
+ return deferralInfo.colorSpaceType; /* Need to have this info for
+ ICC_ColorSpace without
+ causing a deferred profile
+ to be loaded */
+ }
+ return getColorSpaceType(ID);
+ }
+
+ static int getColorSpaceType(long profileID) {
+ byte[] theHeader;
+ int theColorSpaceSig, theColorSpace;
+
+ theHeader = getData(profileID, icSigHead);
+ theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace);
+ theColorSpace = iccCStoJCS (theColorSpaceSig);
+ return theColorSpace;
+ }
+
+ /**
+ * Returns the color space type of the Profile Connection Space (PCS).
+ * Returns one of the color space type constants defined by the
+ * ColorSpace class. This is the "output" color space of the
+ * profile. For an input, display, or output profile useful
+ * for tagging colors or images, this will be either TYPE_XYZ or
+ * TYPE_Lab and should be interpreted as the corresponding specific
+ * color space defined in the ICC specification. For a device
+ * link profile, this could be any of the color space type constants.
+ * @return One of the color space type constants defined in the
+ * <CODE>ColorSpace</CODE> class.
+ */
+ public int getPCSType() {
+ if (ProfileDeferralMgr.deferring) {
+ ProfileDeferralMgr.activateProfiles();
+ }
+ return getPCSType(ID);
+ }
+
+
+ static int getPCSType(long profileID) {
+ byte[] theHeader;
+ int thePCSSig, thePCS;
+
+ theHeader = getData(profileID, icSigHead);
+ thePCSSig = intFromBigEndian(theHeader, icHdrPcs);
+ thePCS = iccCStoJCS(thePCSSig);
+ return thePCS;
+ }
+
+
+ /**
+ * Write this ICC_Profile to a file.
+ *
+ * @param fileName The file to write the profile data to.
+ *
+ * @exception IOException If the file cannot be opened for writing
+ * or an I/O error occurs while writing to the file.
+ */
+ public void write(String fileName) throws IOException {
+ FileOutputStream outputFile;
+ byte profileData[];
+
+ profileData = getData(); /* this will activate deferred
+ profiles if necessary */
+ outputFile = new FileOutputStream(fileName);
+ outputFile.write(profileData);
+ outputFile.close ();
+ }
+
+
+ /**
+ * Write this ICC_Profile to an OutputStream.
+ *
+ * @param s The stream to write the profile data to.
+ *
+ * @exception IOException If an I/O error occurs while writing to the
+ * stream.
+ */
+ public void write(OutputStream s) throws IOException {
+ byte profileData[];
+
+ profileData = getData(); /* this will activate deferred
+ profiles if necessary */
+ s.write(profileData);
+ }
+
+
+ /**
+ * Returns a byte array corresponding to the data of this ICC_Profile.
+ * @return A byte array that contains the profile data.
+ * @see #setData(int, byte[])
+ */
+ public byte[] getData() {
+ int profileSize;
+ byte[] profileData;
+
+ if (ProfileDeferralMgr.deferring) {
+ ProfileDeferralMgr.activateProfiles();
+ }
+
+ PCMM mdl = CMSManager.getModule();
+
+ /* get the number of bytes needed for this profile */
+ profileSize = mdl.getProfileSize(ID);
+
+ profileData = new byte [profileSize];
+
+ /* get the data for the profile */
+ mdl.getProfileData(ID, profileData);
+
+ return profileData;
+ }
+
+
+ /**
+ * Returns a particular tagged data element from the profile as
+ * a byte array. Elements are identified by signatures
+ * as defined in the ICC specification. The signature
+ * icSigHead can be used to get the header. This method is useful
+ * for advanced applets or applications which need to access
+ * profile data directly.
+ *
+ * @param tagSignature The ICC tag signature for the data element you
+ * want to get.
+ *
+ * @return A byte array that contains the tagged data element. Returns
+ * <code>null</code> if the specified tag doesn't exist.
+ * @see #setData(int, byte[])
+ */
+ public byte[] getData(int tagSignature) {
+
+ if (ProfileDeferralMgr.deferring) {
+ ProfileDeferralMgr.activateProfiles();
+ }
+
+ return getData(ID, tagSignature);
+ }
+
+
+ static byte[] getData(long profileID, int tagSignature) {
+ int tagSize;
+ byte[] tagData;
+
+ try {
+ PCMM mdl = CMSManager.getModule();
+
+ /* get the number of bytes needed for this tag */
+ tagSize = mdl.getTagSize(profileID, tagSignature);
+
+ tagData = new byte[tagSize]; /* get an array for the tag */
+
+ /* get the tag's data */
+ mdl.getTagData(profileID, tagSignature, tagData);
+ } catch(CMMException c) {
+ tagData = null;
+ }
+
+ return tagData;
+ }
+
+ /**
+ * Sets a particular tagged data element in the profile from
+ * a byte array. This method is useful
+ * for advanced applets or applications which need to access
+ * profile data directly.
+ *
+ * @param tagSignature The ICC tag signature for the data element
+ * you want to set.
+ * @param tagData the data to set for the specified tag signature
+ * @see #getData
+ */
+ public void setData(int tagSignature, byte[] tagData) {
+
+ if (ProfileDeferralMgr.deferring) {
+ ProfileDeferralMgr.activateProfiles();
+ }
+
+ CMSManager.getModule().setTagData(ID, tagSignature, tagData);
+ }
+
+ /**
+ * Sets the rendering intent of the profile.
+ * This is used to select the proper transform from a profile that
+ * has multiple transforms.
+ */
+ void setRenderingIntent(int renderingIntent) {
+ byte[] theHeader = getData(icSigHead);/* getData will activate deferred
+ profiles if necessary */
+ intToBigEndian (renderingIntent, theHeader, icHdrRenderingIntent);
+ /* set the rendering intent */
+ setData (icSigHead, theHeader);
+ }
+
+
+ /**
+ * Returns the rendering intent of the profile.
+ * This is used to select the proper transform from a profile that
+ * has multiple transforms. It is typically set in a source profile
+ * to select a transform from an output profile.
+ */
+ int getRenderingIntent() {
+ byte[] theHeader = getData(icSigHead);/* getData will activate deferred
+ profiles if necessary */
+
+ int renderingIntent = intFromBigEndian(theHeader, icHdrRenderingIntent);
+ /* set the rendering intent */
+ return renderingIntent;
+ }
+
+
+ /**
+ * Returns the number of color components in the "input" color
+ * space of this profile. For example if the color space type
+ * of this profile is TYPE_RGB, then this method will return 3.
+ *
+ * @return The number of color components in the profile's input
+ * color space.
+ *
+ * @throws ProfileDataException if color space is in the profile
+ * is invalid
+ */
+ public int getNumComponents() {
+ byte[] theHeader;
+ int theColorSpaceSig, theNumComponents;
+
+ if (deferralInfo != null) {
+ return deferralInfo.numComponents; /* Need to have this info for
+ ICC_ColorSpace without
+ causing a deferred profile
+ to be loaded */
+ }
+ theHeader = getData(icSigHead);
+
+ theColorSpaceSig = intFromBigEndian (theHeader, icHdrColorSpace);
+
+ switch (theColorSpaceSig) {
+ case icSigGrayData:
+ theNumComponents = 1;
+ break;
+
+ case icSigSpace2CLR:
+ theNumComponents = 2;
+ break;
+
+ case icSigXYZData:
+ case icSigLabData:
+ case icSigLuvData:
+ case icSigYCbCrData:
+ case icSigYxyData:
+ case icSigRgbData:
+ case icSigHsvData:
+ case icSigHlsData:
+ case icSigCmyData:
+ case icSigSpace3CLR:
+ theNumComponents = 3;
+ break;
+
+ case icSigCmykData:
+ case icSigSpace4CLR:
+ theNumComponents = 4;
+ break;
+
+ case icSigSpace5CLR:
+ theNumComponents = 5;
+ break;
+
+ case icSigSpace6CLR:
+ theNumComponents = 6;
+ break;
+
+ case icSigSpace7CLR:
+ theNumComponents = 7;
+ break;
+
+ case icSigSpace8CLR:
+ theNumComponents = 8;
+ break;
+
+ case icSigSpace9CLR:
+ theNumComponents = 9;
+ break;
+
+ case icSigSpaceACLR:
+ theNumComponents = 10;
+ break;
+
+ case icSigSpaceBCLR:
+ theNumComponents = 11;
+ break;
+
+ case icSigSpaceCCLR:
+ theNumComponents = 12;
+ break;
+
+ case icSigSpaceDCLR:
+ theNumComponents = 13;
+ break;
+
+ case icSigSpaceECLR:
+ theNumComponents = 14;
+ break;
+
+ case icSigSpaceFCLR:
+ theNumComponents = 15;
+ break;
+
+ default:
+ throw new ProfileDataException ("invalid ICC color space");
+ }
+
+ return theNumComponents;
+ }
+
+
+ /**
+ * Returns a float array of length 3 containing the X, Y, and Z
+ * components of the mediaWhitePointTag in the ICC profile.
+ */
+ float[] getMediaWhitePoint() {
+ return getXYZTag(icSigMediaWhitePointTag);
+ /* get the media white point tag */
+ }
+
+
+ /**
+ * Returns a float array of length 3 containing the X, Y, and Z
+ * components encoded in an XYZType tag.
+ */
+ float[] getXYZTag(int theTagSignature) {
+ byte[] theData;
+ float[] theXYZNumber;
+ int i1, i2, theS15Fixed16;
+
+ theData = getData(theTagSignature); /* get the tag data */
+ /* getData will activate deferred
+ profiles if necessary */
+
+ theXYZNumber = new float [3]; /* array to return */
+
+ /* convert s15Fixed16Number to float */
+ for (i1 = 0, i2 = icXYZNumberX; i1 < 3; i1++, i2 += 4) {
+ theS15Fixed16 = intFromBigEndian(theData, i2);
+ theXYZNumber [i1] = ((float) theS15Fixed16) / 65536.0f;
+ }
+ return theXYZNumber;
+ }
+
+
+ /**
+ * Returns a gamma value representing a tone reproduction
+ * curve (TRC). If the profile represents the TRC as a table rather
+ * than a single gamma value, then an exception is thrown. In this
+ * case the actual table can be obtained via getTRC().
+ * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag,
+ * icSigGreenTRCTag, or icSigBlueTRCTag.
+ * @return the gamma value as a float.
+ * @exception ProfileDataException if the profile does not specify
+ * the TRC as a single gamma value.
+ */
+ float getGamma(int theTagSignature) {
+ byte[] theTRCData;
+ float theGamma;
+ int theU8Fixed8;
+
+ theTRCData = getData(theTagSignature); /* get the TRC */
+ /* getData will activate deferred
+ profiles if necessary */
+
+ if (intFromBigEndian (theTRCData, icCurveCount) != 1) {
+ throw new ProfileDataException ("TRC is not a gamma");
+ }
+
+ /* convert u8Fixed8 to float */
+ theU8Fixed8 = (shortFromBigEndian(theTRCData, icCurveData)) & 0xffff;
+
+ theGamma = ((float) theU8Fixed8) / 256.0f;
+
+ return theGamma;
+ }
+
+
+ /**
+ * Returns the TRC as an array of shorts. If the profile has
+ * specified the TRC as linear (gamma = 1.0) or as a simple gamma
+ * value, this method throws an exception, and the getGamma() method
+ * should be used to get the gamma value. Otherwise the short array
+ * returned here represents a lookup table where the input Gray value
+ * is conceptually in the range [0.0, 1.0]. Value 0.0 maps
+ * to array index 0 and value 1.0 maps to array index length-1.
+ * Interpolation may be used to generate output values for
+ * input values which do not map exactly to an index in the
+ * array. Output values also map linearly to the range [0.0, 1.0].
+ * Value 0.0 is represented by an array value of 0x0000 and
+ * value 1.0 by 0xFFFF, i.e. the values are really unsigned
+ * short values, although they are returned in a short array.
+ * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag,
+ * icSigGreenTRCTag, or icSigBlueTRCTag.
+ * @return a short array representing the TRC.
+ * @exception ProfileDataException if the profile does not specify
+ * the TRC as a table.
+ */
+ short[] getTRC(int theTagSignature) {
+ byte[] theTRCData;
+ short[] theTRC;
+ int i1, i2, nElements, theU8Fixed8;
+
+ theTRCData = getData(theTagSignature); /* get the TRC */
+ /* getData will activate deferred
+ profiles if necessary */
+
+ nElements = intFromBigEndian(theTRCData, icCurveCount);
+
+ if (nElements == 1) {
+ throw new ProfileDataException("TRC is not a table");
+ }
+
+ /* make the short array */
+ theTRC = new short [nElements];
+
+ for (i1 = 0, i2 = icCurveData; i1 < nElements; i1++, i2 += 2) {
+ theTRC[i1] = shortFromBigEndian(theTRCData, i2);
+ }
+
+ return theTRC;
+ }
+
+
+ /* convert an ICC color space signature into a Java color space type */
+ static int iccCStoJCS(int theColorSpaceSig) {
+ int theColorSpace;
+
+ switch (theColorSpaceSig) {
+ case icSigXYZData:
+ theColorSpace = ColorSpace.TYPE_XYZ;
+ break;
+
+ case icSigLabData:
+ theColorSpace = ColorSpace.TYPE_Lab;
+ break;
+
+ case icSigLuvData:
+ theColorSpace = ColorSpace.TYPE_Luv;
+ break;
+
+ case icSigYCbCrData:
+ theColorSpace = ColorSpace.TYPE_YCbCr;
+ break;
+
+ case icSigYxyData:
+ theColorSpace = ColorSpace.TYPE_Yxy;
+ break;
+
+ case icSigRgbData:
+ theColorSpace = ColorSpace.TYPE_RGB;
+ break;
+
+ case icSigGrayData:
+ theColorSpace = ColorSpace.TYPE_GRAY;
+ break;
+
+ case icSigHsvData:
+ theColorSpace = ColorSpace.TYPE_HSV;
+ break;
+
+ case icSigHlsData:
+ theColorSpace = ColorSpace.TYPE_HLS;
+ break;
+
+ case icSigCmykData:
+ theColorSpace = ColorSpace.TYPE_CMYK;
+ break;
+
+ case icSigCmyData:
+ theColorSpace = ColorSpace.TYPE_CMY;
+ break;
+
+ case icSigSpace2CLR:
+ theColorSpace = ColorSpace.TYPE_2CLR;
+ break;
+
+ case icSigSpace3CLR:
+ theColorSpace = ColorSpace.TYPE_3CLR;
+ break;
+
+ case icSigSpace4CLR:
+ theColorSpace = ColorSpace.TYPE_4CLR;
+ break;
+
+ case icSigSpace5CLR:
+ theColorSpace = ColorSpace.TYPE_5CLR;
+ break;
+
+ case icSigSpace6CLR:
+ theColorSpace = ColorSpace.TYPE_6CLR;
+ break;
+
+ case icSigSpace7CLR:
+ theColorSpace = ColorSpace.TYPE_7CLR;
+ break;
+
+ case icSigSpace8CLR:
+ theColorSpace = ColorSpace.TYPE_8CLR;
+ break;
+
+ case icSigSpace9CLR:
+ theColorSpace = ColorSpace.TYPE_9CLR;
+ break;
+
+ case icSigSpaceACLR:
+ theColorSpace = ColorSpace.TYPE_ACLR;
+ break;
+
+ case icSigSpaceBCLR:
+ theColorSpace = ColorSpace.TYPE_BCLR;
+ break;
+
+ case icSigSpaceCCLR:
+ theColorSpace = ColorSpace.TYPE_CCLR;
+ break;
+
+ case icSigSpaceDCLR:
+ theColorSpace = ColorSpace.TYPE_DCLR;
+ break;
+
+ case icSigSpaceECLR:
+ theColorSpace = ColorSpace.TYPE_ECLR;
+ break;
+
+ case icSigSpaceFCLR:
+ theColorSpace = ColorSpace.TYPE_FCLR;
+ break;
+
+ default:
+ throw new IllegalArgumentException ("Unknown color space");
+ }
+
+ return theColorSpace;
+ }
+
+
+ static int intFromBigEndian(byte[] array, int index) {
+ return (((array[index] & 0xff) << 24) |
+ ((array[index+1] & 0xff) << 16) |
+ ((array[index+2] & 0xff) << 8) |
+ (array[index+3] & 0xff));
+ }
+
+
+ static void intToBigEndian(int value, byte[] array, int index) {
+ array[index] = (byte) (value >> 24);
+ array[index+1] = (byte) (value >> 16);
+ array[index+2] = (byte) (value >> 8);
+ array[index+3] = (byte) (value);
+ }
+
+
+ static short shortFromBigEndian(byte[] array, int index) {
+ return (short) (((array[index] & 0xff) << 8) |
+ (array[index+1] & 0xff));
+ }
+
+
+ static void shortToBigEndian(short value, byte[] array, int index) {
+ array[index] = (byte) (value >> 8);
+ array[index+1] = (byte) (value);
+ }
+
+
+ /*
+ * fileName may be an absolute or a relative file specification.
+ * Relative file names are looked for in several places: first, relative
+ * to any directories specified by the java.iccprofile.path property;
+ * second, relative to any directories specified by the java.class.path
+ * property; finally, in a directory used to store profiles always
+ * available, such as a profile for sRGB. Built-in profiles use .pf as
+ * the file name extension for profiles, e.g. sRGB.pf.
+ */
+ private static FileInputStream openProfile(final String fileName) {
+ return (FileInputStream)java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Object run() {
+ return privilegedOpenProfile(fileName);
+ }
+ });
+ }
+
+ /*
+ * this version is called from doPrivileged in privilegedOpenProfile.
+ * the whole method is privileged!
+ */
+ private static FileInputStream privilegedOpenProfile(String fileName) {
+ FileInputStream fis = null;
+ String path, dir, fullPath;
+
+ File f = new File(fileName); /* try absolute file name */
+
+ if ((!f.isFile()) &&
+ ((path = System.getProperty("java.iccprofile.path")) != null)){
+ /* try relative to java.iccprofile.path */
+ StringTokenizer st =
+ new StringTokenizer(path, File.pathSeparator);
+ while (st.hasMoreTokens() && (!f.isFile())) {
+ dir = st.nextToken();
+ fullPath = dir + File.separatorChar + fileName;
+ f = new File(fullPath);
+ }
+ }
+
+ if ((!f.isFile()) &&
+ ((path = System.getProperty("java.class.path")) != null)) {
+ /* try relative to java.class.path */
+ StringTokenizer st =
+ new StringTokenizer(path, File.pathSeparator);
+ while (st.hasMoreTokens() && (!f.isFile())) {
+ dir = st.nextToken();
+ fullPath = dir + File.separatorChar + fileName;
+ f = new File(fullPath);
+ }
+ }
+
+ if (!f.isFile()) { /* try the directory of built-in profiles */
+ dir = System.getProperty("java.home") +
+ File.separatorChar + "lib" + File.separatorChar + "cmm";
+ fullPath = dir + File.separatorChar + fileName;
+ f = new File(fullPath);
+ }
+
+ if (f.isFile()) {
+ try {
+ fis = new FileInputStream(f);
+ } catch (FileNotFoundException e) {
+ }
+ }
+ return fis;
+ }
+
+
+ /*
+ * Serialization support.
+ *
+ * Directly deserialized profiles are useless since they are not
+ * registered with CMM. We don't allow constructor to be called
+ * directly and instead have clients to call one of getInstance
+ * factory methods that will register the profile with CMM. For
+ * deserialization we implement readResolve method that will
+ * resolve the bogus deserialized profile object with one obtained
+ * with getInstance as well.
+ *
+ * There're two primary factory methods for construction of ICC
+ * profiles: getInstance(int cspace) and getInstance(byte[] data).
+ * This implementation of ICC_Profile uses the former to return a
+ * cached singleton profile object, other implementations will
+ * likely use this technique too. To preserve the singleton
+ * pattern across serialization we serialize cached singleton
+ * profiles in such a way that deserializing VM could call
+ * getInstance(int cspace) method that will resolve deserialized
+ * object into the corresponding singleton as well.
+ *
+ * Since the singletons are private to ICC_Profile the readResolve
+ * method have to be `protected' instead of `private' so that
+ * singletons that are instances of subclasses of ICC_Profile
+ * could be correctly deserialized.
+ */
+
+
+ /**
+ * Version of the format of additional serialized data in the
+ * stream. Version <code>1</code> corresponds to Java 2
+ * Platform, v1.3.
+ * @since 1.3
+ * @serial
+ */
+ private int iccProfileSerializedDataVersion = 1;
+
+
+ /**
+ * Writes default serializable fields to the stream. Writes a
+ * string and an array of bytes to the stream as additional data.
+ *
+ * @param s stream used for serialization.
+ * @throws IOException
+ * thrown by <code>ObjectInputStream</code>.
+ * @serialData
+ * The <code>String</code> is the name of one of
+ * <code>CS_<var>*</var></code> constants defined in the
+ * {@link ColorSpace} class if the profile object is a profile
+ * for a predefined color space (for example
+ * <code>"CS_sRGB"</code>). The string is <code>null</code>
+ * otherwise.
+ * <p>
+ * The <code>byte[]</code> array is the profile data for the
+ * profile. For predefined color spaces <code>null</code> is
+ * written instead of the profile data. If in the future
+ * versions of Java API new predefined color spaces will be
+ * added, future versions of this class may choose to write
+ * for new predefined color spaces not only the color space
+ * name, but the profile data as well so that older versions
+ * could still deserialize the object.
+ */
+ private void writeObject(ObjectOutputStream s)
+ throws IOException
+ {
+ s.defaultWriteObject();
+
+ String csName = null;
+ if (this == sRGBprofile) {
+ csName = "CS_sRGB";
+ } else if (this == XYZprofile) {
+ csName = "CS_CIEXYZ";
+ } else if (this == PYCCprofile) {
+ csName = "CS_PYCC";
+ } else if (this == GRAYprofile) {
+ csName = "CS_GRAY";
+ } else if (this == LINEAR_RGBprofile) {
+ csName = "CS_LINEAR_RGB";
+ }
+
+ // Future versions may choose to write profile data for new
+ // predefined color spaces as well, if any will be introduced,
+ // so that old versions that don't recognize the new CS name
+ // may fall back to constructing profile from the data.
+ byte[] data = null;
+ if (csName == null) {
+ // getData will activate deferred profile if necessary
+ data = getData();
+ }
+
+ s.writeObject(csName);
+ s.writeObject(data);
+ }
+
+ // Temporary storage used by readObject to store resolved profile
+ // (obtained with getInstance) for readResolve to return.
+ private transient ICC_Profile resolvedDeserializedProfile;
+
+ /**
+ * Reads default serializable fields from the stream. Reads from
+ * the stream a string and an array of bytes as additional data.
+ *
+ * @param s stream used for deserialization.
+ * @throws IOException
+ * thrown by <code>ObjectInputStream</code>.
+ * @throws ClassNotFoundException
+ * thrown by <code>ObjectInputStream</code>.
+ * @serialData
+ * The <code>String</code> is the name of one of
+ * <code>CS_<var>*</var></code> constants defined in the
+ * {@link ColorSpace} class if the profile object is a profile
+ * for a predefined color space (for example
+ * <code>"CS_sRGB"</code>). The string is <code>null</code>
+ * otherwise.
+ * <p>
+ * The <code>byte[]</code> array is the profile data for the
+ * profile. It will usually be <code>null</code> for the
+ * predefined profiles.
+ * <p>
+ * If the string is recognized as a constant name for
+ * predefined color space the object will be resolved into
+ * profile obtained with
+ * <code>getInstance(int cspace)</code> and the profile
+ * data are ignored. Otherwise the object will be resolved
+ * into profile obtained with
+ * <code>getInstance(byte[] data)</code>.
+ * @see #readResolve()
+ * @see #getInstance(int)
+ * @see #getInstance(byte[])
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+
+ String csName = (String)s.readObject();
+ byte[] data = (byte[])s.readObject();
+
+ int cspace = 0; // ColorSpace.CS_* constant if known
+ boolean isKnownPredefinedCS = false;
+ if (csName != null) {
+ isKnownPredefinedCS = true;
+ if (csName.equals("CS_sRGB")) {
+ cspace = ColorSpace.CS_sRGB;
+ } else if (csName.equals("CS_CIEXYZ")) {
+ cspace = ColorSpace.CS_CIEXYZ;
+ } else if (csName.equals("CS_PYCC")) {
+ cspace = ColorSpace.CS_PYCC;
+ } else if (csName.equals("CS_GRAY")) {
+ cspace = ColorSpace.CS_GRAY;
+ } else if (csName.equals("CS_LINEAR_RGB")) {
+ cspace = ColorSpace.CS_LINEAR_RGB;
+ } else {
+ isKnownPredefinedCS = false;
+ }
+ }
+
+ if (isKnownPredefinedCS) {
+ resolvedDeserializedProfile = getInstance(cspace);
+ } else {
+ resolvedDeserializedProfile = getInstance(data);
+ }
+ }
+
+ /**
+ * Resolves instances being deserialized into instances registered
+ * with CMM.
+ * @return ICC_Profile object for profile registered with CMM.
+ * @throws ObjectStreamException
+ * never thrown, but mandated by the serialization spec.
+ * @since 1.3
+ */
+ protected Object readResolve() throws ObjectStreamException {
+ return resolvedDeserializedProfile;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/color/ICC_ProfileGray.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,150 @@
+/*
+ * Portions Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.color;
+
+import java.awt.image.LookupTable;
+import sun.java2d.cmm.ProfileDeferralInfo;
+
+/**
+ *
+ * A subclass of the ICC_Profile class which represents profiles
+ * which meet the following criteria: the color space type of the
+ * profile is TYPE_GRAY and the profile includes the grayTRCTag and
+ * mediaWhitePointTag tags. Examples of this kind of profile are
+ * monochrome input profiles, monochrome display profiles, and
+ * monochrome output profiles. The getInstance methods in the
+ * ICC_Profile class will
+ * return an ICC_ProfileGray object when the above conditions are
+ * met. The advantage of this class is that it provides a lookup
+ * table that Java or native methods may be able to use directly to
+ * optimize color conversion in some cases.
+ * <p>
+ * To transform from a GRAY device profile color space to the CIEXYZ Profile
+ * Connection Space, the device gray component is transformed by
+ * a lookup through the tone reproduction curve (TRC). The result is
+ * treated as the achromatic component of the PCS.
+<pre>
+
+ PCSY = grayTRC[deviceGray]
+
+</pre>
+ * The inverse transform is done by converting the PCS Y components to
+ * device Gray via the inverse of the grayTRC.
+ * <p>
+ */
+
+
+
+public class ICC_ProfileGray
+extends ICC_Profile {
+
+ static final long serialVersionUID = -1124721290732002649L;
+
+ /**
+ * Constructs a new ICC_ProfileGray from a CMM ID.
+ */
+ ICC_ProfileGray(long ID) {
+ super(ID);
+ }
+
+ /**
+ * Constructs a new ICC_ProfileGray from a ProfileDeferralInfo object.
+ */
+ ICC_ProfileGray(ProfileDeferralInfo pdi) {
+ super(pdi);
+ }
+
+
+ /**
+ * Returns a float array of length 3 containing the X, Y, and Z
+ * components of the mediaWhitePointTag in the ICC profile.
+ * @return an array containing the components of the
+ * mediaWhitePointTag in the ICC profile.
+ */
+ public float[] getMediaWhitePoint() {
+ return super.getMediaWhitePoint();
+ }
+
+
+ /**
+ * Returns a gamma value representing the tone reproduction
+ * curve (TRC). If the profile represents the TRC as a table rather
+ * than a single gamma value, then an exception is thrown. In this
+ * case the actual table can be obtained via getTRC(). When
+ * using a gamma value, the PCS Y component is computed as follows:
+<pre>
+
+ gamma
+ PCSY = deviceGray
+
+</pre>
+ * @return the gamma value as a float.
+ * @exception ProfileDataException if the profile does not specify
+ * the TRC as a single gamma value.
+ */
+ public float getGamma() {
+ float theGamma;
+
+ theGamma = super.getGamma(ICC_Profile.icSigGrayTRCTag);
+ return theGamma;
+ }
+
+ /**
+ * Returns the TRC as an array of shorts. If the profile has
+ * specified the TRC as linear (gamma = 1.0) or as a simple gamma
+ * value, this method throws an exception, and the getGamma() method
+ * should be used to get the gamma value. Otherwise the short array
+ * returned here represents a lookup table where the input Gray value
+ * is conceptually in the range [0.0, 1.0]. Value 0.0 maps
+ * to array index 0 and value 1.0 maps to array index length-1.
+ * Interpolation may be used to generate output values for
+ * input values which do not map exactly to an index in the
+ * array. Output values also map linearly to the range [0.0, 1.0].
+ * Value 0.0 is represented by an array value of 0x0000 and
+ * value 1.0 by 0xFFFF, i.e. the values are really unsigned
+ * short values, although they are returned in a short array.
+ * @return a short array representing the TRC.
+ * @exception ProfileDataException if the profile does not specify
+ * the TRC as a table.
+ */
+ public short[] getTRC() {
+ short[] theTRC;
+
+ theTRC = super.getTRC(ICC_Profile.icSigGrayTRCTag);
+ return theTRC;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/color/ICC_ProfileRGB.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,282 @@
+/*
+ * Portions Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.color;
+
+import java.awt.image.LookupTable;
+import sun.java2d.cmm.ProfileDeferralInfo;
+
+/**
+ *
+ * The ICC_ProfileRGB class is a subclass of the ICC_Profile class
+ * that represents profiles which meet the following criteria:
+ * <ul>
+ * <li>The profile's color space type is RGB.</li>
+ * <li>The profile includes the <code>redColorantTag</code>,
+ * <code>greenColorantTag</code>, <code>blueColorantTag</code>,
+ * <code>redTRCTag</code>, <code>greenTRCTag</code>,
+ * <code>blueTRCTag</code>, and <code>mediaWhitePointTag</code> tags.</li>
+ * </ul>
+ * The <code>ICC_Profile</code> <code>getInstance</code> method will
+ * return an <code>ICC_ProfileRGB</code> object when these conditions are met.
+ * Three-component, matrix-based input profiles and RGB display profiles are
+ * examples of this type of profile.
+ * <p>
+ * This profile class provides color transform matrices and lookup tables
+ * that Java or native methods can use directly to
+ * optimize color conversion in some cases.
+ * <p>
+ * To transform from a device profile color space to the CIEXYZ Profile
+ * Connection Space, each device color component is first linearized by
+ * a lookup through the corresponding tone reproduction curve (TRC).
+ * The resulting linear RGB components are converted to the CIEXYZ PCS
+ * using a a 3x3 matrix constructed from the RGB colorants.
+ * <pre>
+ *
+ * linearR = redTRC[deviceR]
+ *
+ * linearG = greenTRC[deviceG]
+ *
+ * linearB = blueTRC[deviceB]
+ *
+ * _ _ _ _ _ _
+ * [ PCSX ] [ redColorantX greenColorantX blueColorantX ] [ linearR ]
+ * [ ] [ ] [ ]
+ * [ PCSY ] = [ redColorantY greenColorantY blueColorantY ] [ linearG ]
+ * [ ] [ ] [ ]
+ * [_ PCSZ _] [_ redColorantZ greenColorantZ blueColorantZ _] [_ linearB _]
+ *
+ * </pre>
+ * The inverse transform is performed by converting PCS XYZ components to linear
+ * RGB components through the inverse of the above 3x3 matrix, and then converting
+ * linear RGB to device RGB through inverses of the TRCs.
+ * <p>
+ */
+
+
+
+public class ICC_ProfileRGB
+extends ICC_Profile {
+
+ static final long serialVersionUID = 8505067385152579334L;
+
+ /**
+ * Used to get a gamma value or TRC for the red component.
+ */
+ public static final int REDCOMPONENT = 0;
+
+ /**
+ * Used to get a gamma value or TRC for the green component.
+ */
+ public static final int GREENCOMPONENT = 1;
+
+ /**
+ * Used to get a gamma value or TRC for the blue component.
+ */
+ public static final int BLUECOMPONENT = 2;
+
+
+ /**
+ * Constructs an new <code>ICC_ProfileRGB</code> from a CMM ID.
+ *
+ * @param ID The CMM ID for the profile.
+ *
+ */
+ ICC_ProfileRGB(long ID) {
+ super(ID);
+ }
+
+ /**
+ * Constructs a new <code>ICC_ProfileRGB</code> from a
+ * ProfileDeferralInfo object.
+ *
+ * @param pdi
+ */
+ ICC_ProfileRGB(ProfileDeferralInfo pdi) {
+ super(pdi);
+ }
+
+
+ /**
+ * Returns an array that contains the components of the profile's
+ * <CODE>mediaWhitePointTag</CODE>.
+ *
+ * @return A 3-element <CODE>float</CODE> array containing the x, y,
+ * and z components of the profile's <CODE>mediaWhitePointTag</CODE>.
+ */
+ public float[] getMediaWhitePoint() {
+ return super.getMediaWhitePoint();
+ }
+
+
+ /**
+ * Returns a 3x3 <CODE>float</CODE> matrix constructed from the
+ * X, Y, and Z components of the profile's <CODE>redColorantTag</CODE>,
+ * <CODE>greenColorantTag</CODE>, and <CODE>blueColorantTag</CODE>.
+ * <p>
+ * This matrix can be used for color transforms in the forward
+ * direction of the profile--from the profile color space
+ * to the CIEXYZ PCS.
+ *
+ * @return A 3x3 <CODE>float</CODE> array that contains the x, y, and z
+ * components of the profile's <CODE>redColorantTag</CODE>,
+ * <CODE>greenColorantTag</CODE>, and <CODE>blueColorantTag</CODE>.
+ */
+ public float[][] getMatrix() {
+ float[][] theMatrix = new float[3][3];
+ float[] tmpMatrix;
+
+ tmpMatrix = getXYZTag(ICC_Profile.icSigRedColorantTag);
+ theMatrix[0][0] = tmpMatrix[0];
+ theMatrix[1][0] = tmpMatrix[1];
+ theMatrix[2][0] = tmpMatrix[2];
+ tmpMatrix = getXYZTag(ICC_Profile.icSigGreenColorantTag);
+ theMatrix[0][1] = tmpMatrix[0];
+ theMatrix[1][1] = tmpMatrix[1];
+ theMatrix[2][1] = tmpMatrix[2];
+ tmpMatrix = getXYZTag(ICC_Profile.icSigBlueColorantTag);
+ theMatrix[0][2] = tmpMatrix[0];
+ theMatrix[1][2] = tmpMatrix[1];
+ theMatrix[2][2] = tmpMatrix[2];
+ return theMatrix;
+ }
+
+ /**
+ * Returns a gamma value representing the tone reproduction curve
+ * (TRC) for a particular component. The component parameter
+ * must be one of REDCOMPONENT, GREENCOMPONENT, or BLUECOMPONENT.
+ * <p>
+ * If the profile
+ * represents the TRC for the corresponding component
+ * as a table rather than a single gamma value, an
+ * exception is thrown. In this case the actual table
+ * can be obtained through the {@link #getTRC(int)} method.
+ * When using a gamma value,
+ * the linear component (R, G, or B) is computed as follows:
+ * <pre>
+ *
+ * gamma
+ * linearComponent = deviceComponent
+ *
+ *</pre>
+ * @param component The <CODE>ICC_ProfileRGB</CODE> constant that
+ * represents the component whose TRC you want to retrieve
+ * @return the gamma value as a float.
+ * @exception ProfileDataException if the profile does not specify
+ * the corresponding TRC as a single gamma value.
+ */
+ public float getGamma(int component) {
+ float theGamma;
+ int theSignature;
+
+ switch (component) {
+ case REDCOMPONENT:
+ theSignature = ICC_Profile.icSigRedTRCTag;
+ break;
+
+ case GREENCOMPONENT:
+ theSignature = ICC_Profile.icSigGreenTRCTag;
+ break;
+
+ case BLUECOMPONENT:
+ theSignature = ICC_Profile.icSigBlueTRCTag;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Must be Red, Green, or Blue");
+ }
+
+ theGamma = super.getGamma(theSignature);
+
+ return theGamma;
+ }
+
+ /**
+ * Returns the TRC for a particular component as an array.
+ * Component must be <code>REDCOMPONENT</code>,
+ * <code>GREENCOMPONENT</code>, or <code>BLUECOMPONENT</code>.
+ * Otherwise the returned array
+ * represents a lookup table where the input component value
+ * is conceptually in the range [0.0, 1.0]. Value 0.0 maps
+ * to array index 0 and value 1.0 maps to array index length-1.
+ * Interpolation might be used to generate output values for
+ * input values that do not map exactly to an index in the
+ * array. Output values also map linearly to the range [0.0, 1.0].
+ * Value 0.0 is represented by an array value of 0x0000 and
+ * value 1.0 by 0xFFFF. In other words, the values are really unsigned
+ * <code>short</code> values even though they are returned in a
+ * <code>short</code> array.
+ *
+ * If the profile has specified the corresponding TRC
+ * as linear (gamma = 1.0) or as a simple gamma value, this method
+ * throws an exception. In this case, the {@link #getGamma(int)}
+ * method should be used to get the gamma value.
+ *
+ * @param component The <CODE>ICC_ProfileRGB</CODE> constant that
+ * represents the component whose TRC you want to retrieve:
+ * <CODE>REDCOMPONENT</CODE>, <CODE>GREENCOMPONENT</CODE>, or
+ * <CODE>BLUECOMPONENT</CODE>.
+ *
+ * @return a short array representing the TRC.
+ * @exception ProfileDataException if the profile does not specify
+ * the corresponding TRC as a table.
+ */
+ public short[] getTRC(int component) {
+ short[] theTRC;
+ int theSignature;
+
+ switch (component) {
+ case REDCOMPONENT:
+ theSignature = ICC_Profile.icSigRedTRCTag;
+ break;
+
+ case GREENCOMPONENT:
+ theSignature = ICC_Profile.icSigGreenTRCTag;
+ break;
+
+ case BLUECOMPONENT:
+ theSignature = ICC_Profile.icSigBlueTRCTag;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Must be Red, Green, or Blue");
+ }
+
+ theTRC = super.getTRC(theSignature);
+
+ return theTRC;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/BandedSampleModel.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,839 @@
+/*
+ * Portions Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+
+/**
+ * This class represents image data which is stored in a band interleaved
+ * fashion and for
+ * which each sample of a pixel occupies one data element of the DataBuffer.
+ * It subclasses ComponentSampleModel but provides a more efficent
+ * implementation for accessing band interleaved image data than is provided
+ * by ComponentSampleModel. This class should typically be used when working
+ * with images which store sample data for each band in a different bank of the
+ * DataBuffer. Accessor methods are provided so that image data can be
+ * manipulated directly. Pixel stride is the number of
+ * data array elements between two samples for the same band on the same
+ * scanline. The pixel stride for a BandedSampleModel is one.
+ * Scanline stride is the number of data array elements between
+ * a given sample and the corresponding sample in the same column of the next
+ * scanline. Band offsets denote the number
+ * of data array elements from the first data array element of the bank
+ * of the DataBuffer holding each band to the first sample of the band.
+ * The bands are numbered from 0 to N-1.
+ * Bank indices denote the correspondence between a bank of the data buffer
+ * and a band of image data. This class supports
+ * {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
+ * {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
+ * {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
+ * {@link DataBuffer#TYPE_INT TYPE_INT},
+ * {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT}, and
+ * {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE} datatypes
+ */
+
+
+public final class BandedSampleModel extends ComponentSampleModel
+{
+
+ /**
+ * Constructs a BandedSampleModel with the specified parameters.
+ * The pixel stride will be one data element. The scanline stride
+ * will be the same as the width. Each band will be stored in
+ * a separate bank and all band offsets will be zero.
+ * @param dataType The data type for storing samples.
+ * @param w The width (in pixels) of the region of
+ * image data described.
+ * @param h The height (in pixels) of the region of image
+ * data described.
+ * @param numBands The number of bands for the image data.
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types
+ */
+ public BandedSampleModel(int dataType, int w, int h, int numBands) {
+ super(dataType, w, h, 1, w,
+ BandedSampleModel.createIndicesArray(numBands),
+ BandedSampleModel.createOffsetArray(numBands));
+ }
+
+ /**
+ * Constructs a BandedSampleModel with the specified parameters.
+ * The number of bands will be inferred from the lengths of the
+ * bandOffsets bankIndices arrays, which must be equal. The pixel
+ * stride will be one data element.
+ * @param dataType The data type for storing samples.
+ * @param w The width (in pixels) of the region of
+ * image data described.
+ * @param h The height (in pixels) of the region of
+ * image data described.
+ * @param scanlineStride The line stride of the of the image data.
+ * @param bankIndices The bank index for each band.
+ * @param bandOffsets The band offset for each band.
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types
+ */
+ public BandedSampleModel(int dataType,
+ int w, int h,
+ int scanlineStride,
+ int bankIndices[],
+ int bandOffsets[]) {
+
+ super(dataType, w, h, 1,scanlineStride, bankIndices, bandOffsets);
+ }
+
+ /**
+ * Creates a new BandedSampleModel with the specified
+ * width and height. The new BandedSampleModel will have the same
+ * number of bands, storage data type, and bank indices
+ * as this BandedSampleModel. The band offsets will be compressed
+ * such that the offset between bands will be w*pixelStride and
+ * the minimum of all of the band offsets is zero.
+ * @param w the width of the resulting <code>BandedSampleModel</code>
+ * @param h the height of the resulting <code>BandedSampleModel</code>
+ * @return a new <code>BandedSampleModel</code> with the specified
+ * width and height.
+ * @throws IllegalArgumentException if <code>w</code> or
+ * <code>h</code> equals either
+ * <code>Integer.MAX_VALUE</code> or
+ * <code>Integer.MIN_VALUE</code>
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ int[] bandOffs;
+
+ if (numBanks == 1) {
+ bandOffs = orderBands(bandOffsets, w*h);
+ }
+ else {
+ bandOffs = new int[bandOffsets.length];
+ }
+
+ SampleModel sampleModel =
+ new BandedSampleModel(dataType, w, h, w, bankIndices, bandOffs);
+ return sampleModel;
+ }
+
+ /**
+ * Creates a new BandedSampleModel with a subset of the bands of this
+ * BandedSampleModel. The new BandedSampleModel can be
+ * used with any DataBuffer that the existing BandedSampleModel
+ * can be used with. The new BandedSampleModel/DataBuffer
+ * combination will represent an image with a subset of the bands
+ * of the original BandedSampleModel/DataBuffer combination.
+ * @throws RasterFormatException if the number of bands is greater than
+ * the number of banks in this sample model.
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types
+ */
+ public SampleModel createSubsetSampleModel(int bands[]) {
+ if (bands.length > bankIndices.length)
+ throw new RasterFormatException("There are only " +
+ bankIndices.length +
+ " bands");
+ int newBankIndices[] = new int[bands.length];
+ int newBandOffsets[] = new int[bands.length];
+
+ for (int i=0; i<bands.length; i++) {
+ newBankIndices[i] = bankIndices[bands[i]];
+ newBandOffsets[i] = bandOffsets[bands[i]];
+ }
+
+ return new BandedSampleModel(this.dataType, width, height,
+ this.scanlineStride,
+ newBankIndices, newBandOffsets);
+ }
+
+ /**
+ * Creates a DataBuffer that corresponds to this BandedSampleModel,
+ * The DataBuffer's data type, number of banks, and size
+ * will be consistent with this BandedSampleModel.
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported types.
+ */
+ public DataBuffer createDataBuffer() {
+ DataBuffer dataBuffer = null;
+
+ int size = scanlineStride * height;
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ dataBuffer = new DataBufferByte(size, numBanks);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ dataBuffer = new DataBufferUShort(size, numBanks);
+ break;
+ case DataBuffer.TYPE_SHORT:
+ dataBuffer = new DataBufferShort(size, numBanks);
+ break;
+ case DataBuffer.TYPE_INT:
+ dataBuffer = new DataBufferInt(size, numBanks);
+ break;
+ case DataBuffer.TYPE_FLOAT:
+ dataBuffer = new DataBufferFloat(size, numBanks);
+ break;
+ case DataBuffer.TYPE_DOUBLE:
+ dataBuffer = new DataBufferDouble(size, numBanks);
+ break;
+ default:
+ throw new IllegalArgumentException("dataType is not one " +
+ "of the supported types.");
+ }
+
+ return dataBuffer;
+ }
+
+
+ /**
+ * Returns data for a single pixel in a primitive array of type
+ * TransferType. For a BandedSampleModel, this will be the same
+ * as the data type, and samples will be returned one per array
+ * element. Generally, obj
+ * should be passed in as null, so that the Object will be created
+ * automatically and will be of the right primitive data type.
+ * <p>
+ * The following code illustrates transferring data for one pixel from
+ * DataBuffer <code>db1</code>, whose storage layout is described by
+ * BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>,
+ * whose storage layout is described by
+ * BandedSampleModel <code>bsm2</code>.
+ * The transfer will generally be more efficient than using
+ * getPixel/setPixel.
+ * <pre>
+ * BandedSampleModel bsm1, bsm2;
+ * DataBufferInt db1, db2;
+ * bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
+ * db2);
+ * </pre>
+ * Using getDataElements/setDataElements to transfer between two
+ * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
+ * the same number of bands, corresponding bands have the same number of
+ * bits per sample, and the TransferTypes are the same.
+ * <p>
+ * If obj is non-null, it should be a primitive array of type TransferType.
+ * Otherwise, a ClassCastException is thrown. An
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds, or if obj is non-null and is not large enough to hold
+ * the pixel data.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param obj If non-null, a primitive array in which to return
+ * the pixel data.
+ * @param data The DataBuffer containing the image data.
+ * @return the data for the specified pixel.
+ * @see #setDataElements(int, int, Object, DataBuffer)
+ */
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int type = getTransferType();
+ int numDataElems = getNumDataElements();
+ int pixelOffset = y*scanlineStride + x;
+
+ switch(type) {
+
+ case DataBuffer.TYPE_BYTE:
+
+ byte[] bdata;
+
+ if (obj == null) {
+ bdata = new byte[numDataElems];
+ } else {
+ bdata = (byte[])obj;
+ }
+
+ for (int i=0; i<numDataElems; i++) {
+ bdata[i] = (byte)data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)bdata;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
+
+ short[] sdata;
+
+ if (obj == null) {
+ sdata = new short[numDataElems];
+ } else {
+ sdata = (short[])obj;
+ }
+
+ for (int i=0; i<numDataElems; i++) {
+ sdata[i] = (short)data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)sdata;
+ break;
+
+ case DataBuffer.TYPE_INT:
+
+ int[] idata;
+
+ if (obj == null) {
+ idata = new int[numDataElems];
+ } else {
+ idata = (int[])obj;
+ }
+
+ for (int i=0; i<numDataElems; i++) {
+ idata[i] = data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)idata;
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+
+ float[] fdata;
+
+ if (obj == null) {
+ fdata = new float[numDataElems];
+ } else {
+ fdata = (float[])obj;
+ }
+
+ for (int i=0; i<numDataElems; i++) {
+ fdata[i] = data.getElemFloat(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)fdata;
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+
+ double[] ddata;
+
+ if (obj == null) {
+ ddata = new double[numDataElems];
+ } else {
+ ddata = (double[])obj;
+ }
+
+ for (int i=0; i<numDataElems; i++) {
+ ddata[i] = data.getElemDouble(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)ddata;
+ break;
+ }
+
+ return obj;
+ }
+
+ /**
+ * Returns all samples for the specified pixel in an int array.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param iArray If non-null, returns the samples in this array
+ * @param data The DataBuffer containing the image data
+ * @return the samples for the specified pixel.
+ * @see #setPixel(int, int, int[], DataBuffer)
+ */
+ public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ int[] pixels;
+
+ if (iArray != null) {
+ pixels = iArray;
+ } else {
+ pixels = new int [numBands];
+ }
+
+ int pixelOffset = y*scanlineStride + x;
+ for (int i=0; i<numBands; i++) {
+ pixels[i] = data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+ return pixels;
+ }
+
+ /**
+ * Returns all samples for the specified rectangle of pixels in
+ * an int array, one sample per data array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location
+ * @param y The Y coordinate of the upper left pixel location
+ * @param w The width of the pixel rectangle
+ * @param h The height of the pixel rectangle
+ * @param iArray If non-null, returns the samples in this array
+ * @param data The DataBuffer containing the image data
+ * @return the samples for the pixels within the specified region.
+ * @see #setPixels(int, int, int, int, int[], DataBuffer)
+ */
+ public int[] getPixels(int x, int y, int w, int h,
+ int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int[] pixels;
+
+ if (iArray != null) {
+ pixels = iArray;
+ } else {
+ pixels = new int[w*h*numBands];
+ }
+
+ for (int k = 0; k < numBands; k++) {
+ int lineOffset = y*scanlineStride + x + bandOffsets[k];
+ int srcOffset = k;
+ int bank = bankIndices[k];
+
+ for (int i = 0; i < h; i++) {
+ int pixelOffset = lineOffset;
+ for (int j = 0; j < w; j++) {
+ pixels[srcOffset] = data.getElem(bank, pixelOffset++);
+ srcOffset += numBands;
+ }
+ lineOffset += scanlineStride;
+ }
+ }
+ return pixels;
+ }
+
+ /**
+ * Returns as int the sample in a specified band for the pixel
+ * located at (x,y).
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to return
+ * @param data The DataBuffer containing the image data
+ * @return the sample in the specified band for the specified pixel.
+ * @see #setSample(int, int, int, int, DataBuffer)
+ */
+ public int getSample(int x, int y, int b, DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int sample =
+ data.getElem(bankIndices[b],
+ y*scanlineStride + x + bandOffsets[b]);
+ return sample;
+ }
+
+ /**
+ * Returns the sample in a specified band
+ * for the pixel located at (x,y) as a float.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to return
+ * @param data The DataBuffer containing the image data
+ * @return a float value that represents the sample in the specified
+ * band for the specified pixel.
+ */
+ public float getSampleFloat(int x, int y, int b, DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ float sample = data.getElemFloat(bankIndices[b],
+ y*scanlineStride + x + bandOffsets[b]);
+ return sample;
+ }
+
+ /**
+ * Returns the sample in a specified band
+ * for a pixel located at (x,y) as a double.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to return
+ * @param data The DataBuffer containing the image data
+ * @return a double value that represents the sample in the specified
+ * band for the specified pixel.
+ */
+ public double getSampleDouble(int x, int y, int b, DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ double sample = data.getElemDouble(bankIndices[b],
+ y*scanlineStride + x + bandOffsets[b]);
+ return sample;
+ }
+
+ /**
+ * Returns the samples in a specified band for the specified rectangle
+ * of pixels in an int array, one sample per data array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location
+ * @param y The Y coordinate of the upper left pixel location
+ * @param w The width of the pixel rectangle
+ * @param h The height of the pixel rectangle
+ * @param b The band to return
+ * @param iArray If non-null, returns the samples in this array
+ * @param data The DataBuffer containing the image data
+ * @return the samples in the specified band for the pixels within
+ * the specified region.
+ * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
+ */
+ public int[] getSamples(int x, int y, int w, int h, int b,
+ int iArray[], DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int samples[];
+ if (iArray != null) {
+ samples = iArray;
+ } else {
+ samples = new int [w*h];
+ }
+
+ int lineOffset = y*scanlineStride + x + bandOffsets[b];
+ int srcOffset = 0;
+ int bank = bankIndices[b];
+
+ for (int i = 0; i < h; i++) {
+ int sampleOffset = lineOffset;
+ for (int j = 0; j < w; j++) {
+ samples[srcOffset++] = data.getElem(bank, sampleOffset++);
+ }
+ lineOffset += scanlineStride;
+ }
+ return samples;
+ }
+
+ /**
+ * Sets the data for a single pixel in the specified DataBuffer from a
+ * primitive array of type TransferType. For a BandedSampleModel,
+ * this will be the same as the data type, and samples are transferred
+ * one per array element.
+ * <p>
+ * The following code illustrates transferring data for one pixel from
+ * DataBuffer <code>db1</code>, whose storage layout is described by
+ * BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>,
+ * whose storage layout is described by
+ * BandedSampleModel <code>bsm2</code>.
+ * The transfer will generally be more efficient than using
+ * getPixel/setPixel.
+ * <pre>
+ * BandedSampleModel bsm1, bsm2;
+ * DataBufferInt db1, db2;
+ * bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
+ * db2);
+ * </pre>
+ * Using getDataElements/setDataElements to transfer between two
+ * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
+ * the same number of bands, corresponding bands have the same number of
+ * bits per sample, and the TransferTypes are the same.
+ * <p>
+ * obj must be a primitive array of type TransferType. Otherwise,
+ * a ClassCastException is thrown. An
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds, or if obj is not large enough to hold the pixel data.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param obj If non-null, returns the primitive array in this
+ * object
+ * @param data The DataBuffer containing the image data
+ * @see #getDataElements(int, int, Object, DataBuffer)
+ */
+ public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int type = getTransferType();
+ int numDataElems = getNumDataElements();
+ int pixelOffset = y*scanlineStride + x;
+
+ switch(type) {
+
+ case DataBuffer.TYPE_BYTE:
+
+ byte[] barray = (byte[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
+ barray[i] & 0xff);
+ }
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
+
+ short[] sarray = (short[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
+ sarray[i] & 0xffff);
+ }
+ break;
+
+ case DataBuffer.TYPE_INT:
+
+ int[] iarray = (int[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
+ iarray[i]);
+ }
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+
+ float[] farray = (float[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ data.setElemFloat(bankIndices[i], pixelOffset + bandOffsets[i],
+ farray[i]);
+ }
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+
+ double[] darray = (double[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ data.setElemDouble(bankIndices[i], pixelOffset + bandOffsets[i],
+ darray[i]);
+ }
+ break;
+
+ }
+ }
+
+ /**
+ * Sets a pixel in the DataBuffer using an int array of samples for input.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param iArray The input samples in an int array
+ * @param data The DataBuffer containing the image data
+ * @see #getPixel(int, int, int[], DataBuffer)
+ */
+ public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int pixelOffset = y*scanlineStride + x;
+ for (int i=0; i<numBands; i++) {
+ data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
+ iArray[i]);
+ }
+ }
+
+ /**
+ * Sets all samples for a rectangle of pixels from an int array containing
+ * one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location
+ * @param y The Y coordinate of the upper left pixel location
+ * @param w The width of the pixel rectangle
+ * @param h The height of the pixel rectangle
+ * @param iArray The input samples in an int array
+ * @param data The DataBuffer containing the image data
+ * @see #getPixels(int, int, int, int, int[], DataBuffer)
+ */
+ public void setPixels(int x, int y, int w, int h,
+ int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ for (int k = 0; k < numBands; k++) {
+ int lineOffset = y*scanlineStride + x + bandOffsets[k];
+ int srcOffset = k;
+ int bank = bankIndices[k];
+
+ for (int i = 0; i < h; i++) {
+ int pixelOffset = lineOffset;
+ for (int j = 0; j < w; j++) {
+ data.setElem(bank, pixelOffset++, iArray[srcOffset]);
+ srcOffset += numBands;
+ }
+ lineOffset += scanlineStride;
+ }
+ }
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the DataBuffer using an int for input.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to set
+ * @param s The input sample as an int
+ * @param data The DataBuffer containing the image data
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public void setSample(int x, int y, int b, int s,
+ DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ data.setElem(bankIndices[b],
+ y*scanlineStride + x + bandOffsets[b], s);
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the DataBuffer using a float for input.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to set
+ * @param s The input sample as a float
+ * @param data The DataBuffer containing the image data
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public void setSample(int x, int y, int b,
+ float s ,
+ DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ data.setElemFloat(bankIndices[b],
+ y*scanlineStride + x + bandOffsets[b], s);
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the DataBuffer using a double for input.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to set
+ * @param s The input sample as a double
+ * @param data The DataBuffer containing the image data
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public void setSample(int x, int y, int b,
+ double s,
+ DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ data.setElemDouble(bankIndices[b],
+ y*scanlineStride + x + bandOffsets[b], s);
+ }
+
+ /**
+ * Sets the samples in the specified band for the specified rectangle
+ * of pixels from an int array containing one sample per data array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location
+ * @param y The Y coordinate of the upper left pixel location
+ * @param w The width of the pixel rectangle
+ * @param h The height of the pixel rectangle
+ * @param b The band to set
+ * @param iArray The input sample array
+ * @param data The DataBuffer containing the image data
+ * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ int iArray[], DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int lineOffset = y*scanlineStride + x + bandOffsets[b];
+ int srcOffset = 0;
+ int bank = bankIndices[b];
+
+ for (int i = 0; i < h; i++) {
+ int sampleOffset = lineOffset;
+ for (int j = 0; j < w; j++) {
+ data.setElem(bank, sampleOffset++, iArray[srcOffset++]);
+ }
+ lineOffset += scanlineStride;
+ }
+ }
+
+ private static int[] createOffsetArray(int numBands) {
+ int[] bandOffsets = new int[numBands];
+ for (int i=0; i < numBands; i++) {
+ bandOffsets[i] = 0;
+ }
+ return bandOffsets;
+ }
+
+ private static int[] createIndicesArray(int numBands) {
+ int[] bankIndices = new int[numBands];
+ for (int i=0; i < numBands; i++) {
+ bankIndices[i] = i;
+ }
+ return bankIndices;
+ }
+
+ // Differentiate hash code from other ComponentSampleModel subclasses
+ public int hashCode() {
+ return super.hashCode() ^ 0x2;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/ColorConvertOp.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,1109 @@
+/*
+ * Portions Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.image;
+
+import java.awt.Point;
+import java.awt.Graphics2D;
+import java.awt.color.*;
+import sun.java2d.cmm.ColorTransform;
+import sun.java2d.cmm.CMSManager;
+import sun.java2d.cmm.ProfileDeferralMgr;
+import sun.java2d.cmm.PCMM;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.Point2D;
+import java.awt.RenderingHints;
+
+/**
+ * This class performs a pixel-by-pixel color conversion of the data in
+ * the source image. The resulting color values are scaled to the precision
+ * of the destination image. Color conversion can be specified
+ * via an array of ColorSpace objects or an array of ICC_Profile objects.
+ * <p>
+ * If the source is a BufferedImage with premultiplied alpha, the
+ * color components are divided by the alpha component before color conversion.
+ * If the destination is a BufferedImage with premultiplied alpha, the
+ * color components are multiplied by the alpha component after conversion.
+ * Rasters are treated as having no alpha channel, i.e. all bands are
+ * color bands.
+ * <p>
+ * If a RenderingHints object is specified in the constructor, the
+ * color rendering hint and the dithering hint may be used to control
+ * color conversion.
+ * <p>
+ * Note that Source and Destination may be the same object.
+ * <p>
+ * @see java.awt.RenderingHints#KEY_COLOR_RENDERING
+ * @see java.awt.RenderingHints#KEY_DITHERING
+ */
+public class ColorConvertOp implements BufferedImageOp, RasterOp {
+ ICC_Profile[] profileList;
+ ColorSpace[] CSList;
+ ColorTransform thisTransform, thisRasterTransform;
+ ICC_Profile thisSrcProfile, thisDestProfile;
+ RenderingHints hints;
+ boolean gotProfiles;
+ float[] srcMinVals, srcMaxVals, dstMinVals, dstMaxVals;
+
+ /* the class initializer */
+ static {
+ if (ProfileDeferralMgr.deferring) {
+ ProfileDeferralMgr.activateProfiles();
+ }
+ }
+
+ /**
+ * Constructs a new ColorConvertOp which will convert
+ * from a source color space to a destination color space.
+ * The RenderingHints argument may be null.
+ * This Op can be used only with BufferedImages, and will convert
+ * directly from the ColorSpace of the source image to that of the
+ * destination. The destination argument of the filter method
+ * cannot be specified as null.
+ * @param hints the <code>RenderingHints</code> object used to control
+ * the color conversion, or <code>null</code>
+ */
+ public ColorConvertOp (RenderingHints hints)
+ {
+ profileList = new ICC_Profile [0]; /* 0 length list */
+ this.hints = hints;
+ }
+
+ /**
+ * Constructs a new ColorConvertOp from a ColorSpace object.
+ * The RenderingHints argument may be null. This
+ * Op can be used only with BufferedImages, and is primarily useful
+ * when the {@link #filter(BufferedImage, BufferedImage) filter}
+ * method is invoked with a destination argument of null.
+ * In that case, the ColorSpace defines the destination color space
+ * for the destination created by the filter method. Otherwise, the
+ * ColorSpace defines an intermediate space to which the source is
+ * converted before being converted to the destination space.
+ * @param cspace defines the destination <code>ColorSpace</code> or an
+ * intermediate <code>ColorSpace</code>
+ * @param hints the <code>RenderingHints</code> object used to control
+ * the color conversion, or <code>null</code>
+ * @throws NullPointerException if cspace is null
+ */
+ public ColorConvertOp (ColorSpace cspace, RenderingHints hints)
+ {
+ if (cspace == null) {
+ throw new NullPointerException("ColorSpace cannot be null");
+ }
+ if (cspace instanceof ICC_ColorSpace) {
+ profileList = new ICC_Profile [1]; /* 1 profile in the list */
+
+ profileList [0] = ((ICC_ColorSpace) cspace).getProfile();
+ }
+ else {
+ CSList = new ColorSpace[1]; /* non-ICC case: 1 ColorSpace in list */
+ CSList[0] = cspace;
+ }
+ this.hints = hints;
+ }
+
+
+ /**
+ * Constructs a new ColorConvertOp from two ColorSpace objects.
+ * The RenderingHints argument may be null.
+ * This Op is primarily useful for calling the filter method on
+ * Rasters, in which case the two ColorSpaces define the operation
+ * to be performed on the Rasters. In that case, the number of bands
+ * in the source Raster must match the number of components in
+ * srcCspace, and the number of bands in the destination Raster
+ * must match the number of components in dstCspace. For BufferedImages,
+ * the two ColorSpaces define intermediate spaces through which the
+ * source is converted before being converted to the destination space.
+ * @param srcCspace the source <code>ColorSpace</code>
+ * @param dstCspace the destination <code>ColorSpace</code>
+ * @param hints the <code>RenderingHints</code> object used to control
+ * the color conversion, or <code>null</code>
+ * @throws NullPointerException if either srcCspace or dstCspace is null
+ */
+ public ColorConvertOp(ColorSpace srcCspace, ColorSpace dstCspace,
+ RenderingHints hints)
+ {
+ if ((srcCspace == null) || (dstCspace == null)) {
+ throw new NullPointerException("ColorSpaces cannot be null");
+ }
+ if ((srcCspace instanceof ICC_ColorSpace) &&
+ (dstCspace instanceof ICC_ColorSpace)) {
+ profileList = new ICC_Profile [2]; /* 2 profiles in the list */
+
+ profileList [0] = ((ICC_ColorSpace) srcCspace).getProfile();
+ profileList [1] = ((ICC_ColorSpace) dstCspace).getProfile();
+
+ getMinMaxValsFromColorSpaces(srcCspace, dstCspace);
+ } else {
+ /* non-ICC case: 2 ColorSpaces in list */
+ CSList = new ColorSpace[2];
+ CSList[0] = srcCspace;
+ CSList[1] = dstCspace;
+ }
+ this.hints = hints;
+ }
+
+
+ /**
+ * Constructs a new ColorConvertOp from an array of ICC_Profiles.
+ * The RenderingHints argument may be null.
+ * The sequence of profiles may include profiles that represent color
+ * spaces, profiles that represent effects, etc. If the whole sequence
+ * does not represent a well-defined color conversion, an exception is
+ * thrown.
+ * <p>For BufferedImages, if the ColorSpace
+ * of the source BufferedImage does not match the requirements of the
+ * first profile in the array,
+ * the first conversion is to an appropriate ColorSpace.
+ * If the requirements of the last profile in the array are not met
+ * by the ColorSpace of the destination BufferedImage,
+ * the last conversion is to the destination's ColorSpace.
+ * <p>For Rasters, the number of bands in the source Raster must match
+ * the requirements of the first profile in the array, and the
+ * number of bands in the destination Raster must match the requirements
+ * of the last profile in the array. The array must have at least two
+ * elements or calling the filter method for Rasters will throw an
+ * IllegalArgumentException.
+ * @param profiles the array of <code>ICC_Profile</code> objects
+ * @param hints the <code>RenderingHints</code> object used to control
+ * the color conversion, or <code>null</code>
+ * @exception IllegalArgumentException when the profile sequence does not
+ * specify a well-defined color conversion
+ * @exception NullPointerException if profiles is null
+ */
+ public ColorConvertOp (ICC_Profile[] profiles, RenderingHints hints)
+ {
+ if (profiles == null) {
+ throw new NullPointerException("Profiles cannot be null");
+ }
+ gotProfiles = true;
+ profileList = new ICC_Profile[profiles.length];
+ for (int i1 = 0; i1 < profiles.length; i1++) {
+ profileList[i1] = profiles[i1];
+ }
+ this.hints = hints;
+ }
+
+
+ /**
+ * Returns the array of ICC_Profiles used to construct this ColorConvertOp.
+ * Returns null if the ColorConvertOp was not constructed from such an
+ * array.
+ * @return the array of <code>ICC_Profile</code> objects of this
+ * <code>ColorConvertOp</code>, or <code>null</code> if this
+ * <code>ColorConvertOp</code> was not constructed with an
+ * array of <code>ICC_Profile</code> objects.
+ */
+ public final ICC_Profile[] getICC_Profiles() {
+ if (gotProfiles) {
+ ICC_Profile[] profiles = new ICC_Profile[profileList.length];
+ for (int i1 = 0; i1 < profileList.length; i1++) {
+ profiles[i1] = profileList[i1];
+ }
+ return profiles;
+ }
+ return null;
+ }
+
+ /**
+ * ColorConverts the source BufferedImage.
+ * If the destination image is null,
+ * a BufferedImage will be created with an appropriate ColorModel.
+ * @param src the source <code>BufferedImage</code> to be converted
+ * @param dest the destination <code>BufferedImage</code>,
+ * or <code>null</code>
+ * @return <code>dest</code> color converted from <code>src</code>
+ * or a new, converted <code>BufferedImage</code>
+ * if <code>dest</code> is <code>null</code>
+ * @exception IllegalArgumentException if dest is null and this op was
+ * constructed using the constructor which takes only a
+ * RenderingHints argument, since the operation is ill defined.
+ */
+ public final BufferedImage filter(BufferedImage src, BufferedImage dest) {
+ ColorSpace srcColorSpace, destColorSpace;
+ BufferedImage savdest = null;
+
+ if (src.getColorModel() instanceof IndexColorModel) {
+ IndexColorModel icm = (IndexColorModel) src.getColorModel();
+ src = icm.convertToIntDiscrete(src.getRaster(), true);
+ }
+ srcColorSpace = src.getColorModel().getColorSpace();
+ if (dest != null) {
+ if (dest.getColorModel() instanceof IndexColorModel) {
+ savdest = dest;
+ dest = null;
+ destColorSpace = null;
+ } else {
+ destColorSpace = dest.getColorModel().getColorSpace();
+ }
+ } else {
+ destColorSpace = null;
+ }
+
+ if ((CSList != null) ||
+ (!(srcColorSpace instanceof ICC_ColorSpace)) ||
+ ((dest != null) &&
+ (!(destColorSpace instanceof ICC_ColorSpace)))) {
+ /* non-ICC case */
+ dest = nonICCBIFilter(src, srcColorSpace, dest, destColorSpace);
+ } else {
+ dest = ICCBIFilter(src, srcColorSpace, dest, destColorSpace);
+ }
+
+ if (savdest != null) {
+ Graphics2D big = savdest.createGraphics();
+ try {
+ big.drawImage(dest, 0, 0, null);
+ } finally {
+ big.dispose();
+ }
+ return savdest;
+ } else {
+ return dest;
+ }
+ }
+
+ private final BufferedImage ICCBIFilter(BufferedImage src,
+ ColorSpace srcColorSpace,
+ BufferedImage dest,
+ ColorSpace destColorSpace) {
+ int nProfiles = profileList.length;
+ ICC_Profile srcProfile = null, destProfile = null;
+
+ srcProfile = ((ICC_ColorSpace) srcColorSpace).getProfile();
+
+ if (dest == null) { /* last profile in the list defines
+ the output color space */
+ if (nProfiles == 0) {
+ throw new IllegalArgumentException(
+ "Destination ColorSpace is undefined");
+ }
+ destProfile = profileList [nProfiles - 1];
+ dest = createCompatibleDestImage(src, null);
+ }
+ else {
+ if (src.getHeight() != dest.getHeight() ||
+ src.getWidth() != dest.getWidth()) {
+ throw new IllegalArgumentException(
+ "Width or height of BufferedImages do not match");
+ }
+ destProfile = ((ICC_ColorSpace) destColorSpace).getProfile();
+ }
+
+ /* Checking if all profiles in the transform sequence are the same.
+ * If so, performing just copying the data.
+ */
+ if (srcProfile == destProfile) {
+ boolean noTrans = true;
+ for (int i = 0; i < nProfiles; i++) {
+ if (srcProfile != profileList[i]) {
+ noTrans = false;
+ break;
+ }
+ }
+ if (noTrans) {
+ Graphics2D g = dest.createGraphics();
+ try {
+ g.drawImage(src, 0, 0, null);
+ } finally {
+ g.dispose();
+ }
+
+ return dest;
+ }
+ }
+
+ /* make a new transform if needed */
+ if ((thisTransform == null) || (thisSrcProfile != srcProfile) ||
+ (thisDestProfile != destProfile) ) {
+ updateBITransform(srcProfile, destProfile);
+ }
+
+ /* color convert the image */
+ thisTransform.colorConvert(src, dest);
+
+ return dest;
+ }
+
+ private void updateBITransform(ICC_Profile srcProfile,
+ ICC_Profile destProfile) {
+ ICC_Profile[] theProfiles;
+ int i1, nProfiles, nTransforms, whichTrans, renderState;
+ ColorTransform[] theTransforms;
+ boolean useSrc = false, useDest = false;
+
+ nProfiles = profileList.length;
+ nTransforms = nProfiles;
+ if ((nProfiles == 0) || (srcProfile != profileList[0])) {
+ nTransforms += 1;
+ useSrc = true;
+ }
+ if ((nProfiles == 0) || (destProfile != profileList[nProfiles - 1]) ||
+ (nTransforms < 2)) {
+ nTransforms += 1;
+ useDest = true;
+ }
+
+ /* make the profile list */
+ theProfiles = new ICC_Profile[nTransforms]; /* the list of profiles
+ for this Op */
+
+ int idx = 0;
+ if (useSrc) {
+ /* insert source as first profile */
+ theProfiles[idx++] = srcProfile;
+ }
+
+ for (i1 = 0; i1 < nProfiles; i1++) {
+ /* insert profiles defined in this Op */
+ theProfiles[idx++] = profileList [i1];
+ }
+
+ if (useDest) {
+ /* insert dest as last profile */
+ theProfiles[idx] = destProfile;
+ }
+
+ /* make the transform list */
+ theTransforms = new ColorTransform [nTransforms];
+
+ /* initialize transform get loop */
+ if (theProfiles[0].getProfileClass() == ICC_Profile.CLASS_OUTPUT) {
+ /* if first profile is a printer
+ render as colorimetric */
+ renderState = ICC_Profile.icRelativeColorimetric;
+ }
+ else {
+ renderState = ICC_Profile.icPerceptual; /* render any other
+ class perceptually */
+ }
+
+ whichTrans = ColorTransform.In;
+
+ PCMM mdl = CMSManager.getModule();
+
+ /* get the transforms from each profile */
+ for (i1 = 0; i1 < nTransforms; i1++) {
+ if (i1 == nTransforms -1) { /* last profile? */
+ whichTrans = ColorTransform.Out; /* get output transform */
+ }
+ else { /* check for abstract profile */
+ if ((whichTrans == ColorTransform.Simulation) &&
+ (theProfiles[i1].getProfileClass () ==
+ ICC_Profile.CLASS_ABSTRACT)) {
+ renderState = ICC_Profile.icPerceptual;
+ whichTrans = ColorTransform.In;
+ }
+ }
+
+ theTransforms[i1] = mdl.createTransform (
+ theProfiles[i1], renderState, whichTrans);
+
+ /* get this profile's rendering intent to select transform
+ from next profile */
+ renderState = getRenderingIntent(theProfiles[i1]);
+
+ /* "middle" profiles use simulation transform */
+ whichTrans = ColorTransform.Simulation;
+ }
+
+ /* make the net transform */
+ thisTransform = mdl.createTransform(theTransforms);
+
+ /* update corresponding source and dest profiles */
+ thisSrcProfile = srcProfile;
+ thisDestProfile = destProfile;
+ }
+
+ /**
+ * ColorConverts the image data in the source Raster.
+ * If the destination Raster is null, a new Raster will be created.
+ * The number of bands in the source and destination Rasters must
+ * meet the requirements explained above. The constructor used to
+ * create this ColorConvertOp must have provided enough information
+ * to define both source and destination color spaces. See above.
+ * Otherwise, an exception is thrown.
+ * @param src the source <code>Raster</code> to be converted
+ * @param dest the destination <code>WritableRaster</code>,
+ * or <code>null</code>
+ * @return <code>dest</code> color converted from <code>src</code>
+ * or a new, converted <code>WritableRaster</code>
+ * if <code>dest</code> is <code>null</code>
+ * @exception IllegalArgumentException if the number of source or
+ * destination bands is incorrect, the source or destination
+ * color spaces are undefined, or this op was constructed
+ * with one of the constructors that applies only to
+ * operations on BufferedImages.
+ */
+ public final WritableRaster filter (Raster src, WritableRaster dest) {
+
+ if (CSList != null) {
+ /* non-ICC case */
+ return nonICCRasterFilter(src, dest);
+ }
+ int nProfiles = profileList.length;
+ if (nProfiles < 2) {
+ throw new IllegalArgumentException(
+ "Source or Destination ColorSpace is undefined");
+ }
+ if (src.getNumBands() != profileList[0].getNumComponents()) {
+ throw new IllegalArgumentException(
+ "Numbers of source Raster bands and source color space " +
+ "components do not match");
+ }
+ if (dest == null) {
+ dest = createCompatibleDestRaster(src);
+ }
+ else {
+ if (src.getHeight() != dest.getHeight() ||
+ src.getWidth() != dest.getWidth()) {
+ throw new IllegalArgumentException(
+ "Width or height of Rasters do not match");
+ }
+ if (dest.getNumBands() !=
+ profileList[nProfiles-1].getNumComponents()) {
+ throw new IllegalArgumentException(
+ "Numbers of destination Raster bands and destination " +
+ "color space components do not match");
+ }
+ }
+
+ /* make a new transform if needed */
+ if (thisRasterTransform == null) {
+ int i1, whichTrans, renderState;
+ ColorTransform[] theTransforms;
+
+ /* make the transform list */
+ theTransforms = new ColorTransform [nProfiles];
+
+ /* initialize transform get loop */
+ if (profileList[0].getProfileClass() == ICC_Profile.CLASS_OUTPUT) {
+ /* if first profile is a printer
+ render as colorimetric */
+ renderState = ICC_Profile.icRelativeColorimetric;
+ }
+ else {
+ renderState = ICC_Profile.icPerceptual; /* render any other
+ class perceptually */
+ }
+
+ whichTrans = ColorTransform.In;
+
+ PCMM mdl = CMSManager.getModule();
+
+ /* get the transforms from each profile */
+ for (i1 = 0; i1 < nProfiles; i1++) {
+ if (i1 == nProfiles -1) { /* last profile? */
+ whichTrans = ColorTransform.Out; /* get output transform */
+ }
+ else { /* check for abstract profile */
+ if ((whichTrans == ColorTransform.Simulation) &&
+ (profileList[i1].getProfileClass () ==
+ ICC_Profile.CLASS_ABSTRACT)) {
+ renderState = ICC_Profile.icPerceptual;
+ whichTrans = ColorTransform.In;
+ }
+ }
+
+ theTransforms[i1] = mdl.createTransform (
+ profileList[i1], renderState, whichTrans);
+
+ /* get this profile's rendering intent to select transform
+ from next profile */
+ renderState = getRenderingIntent(profileList[i1]);
+
+ /* "middle" profiles use simulation transform */
+ whichTrans = ColorTransform.Simulation;
+ }
+
+ /* make the net transform */
+ thisRasterTransform = mdl.createTransform(theTransforms);
+ }
+
+ int srcTransferType = src.getTransferType();
+ int dstTransferType = dest.getTransferType();
+ if ((srcTransferType == DataBuffer.TYPE_FLOAT) ||
+ (srcTransferType == DataBuffer.TYPE_DOUBLE) ||
+ (dstTransferType == DataBuffer.TYPE_FLOAT) ||
+ (dstTransferType == DataBuffer.TYPE_DOUBLE)) {
+ if (srcMinVals == null) {
+ getMinMaxValsFromProfiles(profileList[0],
+ profileList[nProfiles-1]);
+ }
+ /* color convert the raster */
+ thisRasterTransform.colorConvert(src, dest,
+ srcMinVals, srcMaxVals,
+ dstMinVals, dstMaxVals);
+ } else {
+ /* color convert the raster */
+ thisRasterTransform.colorConvert(src, dest);
+ }
+
+
+ return dest;
+ }
+
+ /**
+ * Returns the bounding box of the destination, given this source.
+ * Note that this will be the same as the the bounding box of the
+ * source.
+ * @param src the source <code>BufferedImage</code>
+ * @return a <code>Rectangle2D</code> that is the bounding box
+ * of the destination, given the specified <code>src</code>
+ */
+ public final Rectangle2D getBounds2D (BufferedImage src) {
+ return getBounds2D(src.getRaster());
+ }
+
+ /**
+ * Returns the bounding box of the destination, given this source.
+ * Note that this will be the same as the the bounding box of the
+ * source.
+ * @param src the source <code>Raster</code>
+ * @return a <code>Rectangle2D</code> that is the bounding box
+ * of the destination, given the specified <code>src</code>
+ */
+ public final Rectangle2D getBounds2D (Raster src) {
+ /* return new Rectangle (src.getXOffset(),
+ src.getYOffset(),
+ src.getWidth(), src.getHeight()); */
+ return src.getBounds();
+ }
+
+ /**
+ * Creates a zeroed destination image with the correct size and number of
+ * bands, given this source.
+ * @param src Source image for the filter operation.
+ * @param destCM ColorModel of the destination. If null, an
+ * appropriate ColorModel will be used.
+ * @return a <code>BufferedImage</code> with the correct size and
+ * number of bands from the specified <code>src</code>.
+ * @throws IllegalArgumentException if <code>destCM</code> is
+ * <code>null</code> and this <code>ColorConvertOp</code> was
+ * created without any <code>ICC_Profile</code> or
+ * <code>ColorSpace</code> defined for the destination
+ */
+ public BufferedImage createCompatibleDestImage (BufferedImage src,
+ ColorModel destCM) {
+ ColorSpace cs = null;;
+ if (destCM == null) {
+ if (CSList == null) {
+ /* ICC case */
+ int nProfiles = profileList.length;
+ if (nProfiles == 0) {
+ throw new IllegalArgumentException(
+ "Destination ColorSpace is undefined");
+ }
+ ICC_Profile destProfile = profileList[nProfiles - 1];
+ cs = new ICC_ColorSpace(destProfile);
+ } else {
+ /* non-ICC case */
+ int nSpaces = CSList.length;
+ cs = CSList[nSpaces - 1];
+ }
+ }
+ return createCompatibleDestImage(src, destCM, cs);
+ }
+
+ private BufferedImage createCompatibleDestImage(BufferedImage src,
+ ColorModel destCM,
+ ColorSpace destCS) {
+ BufferedImage image;
+ if (destCM == null) {
+ ColorModel srcCM = src.getColorModel();
+ int nbands = destCS.getNumComponents();
+ boolean hasAlpha = srcCM.hasAlpha();
+ if (hasAlpha) {
+ nbands += 1;
+ }
+ int[] nbits = new int[nbands];
+ for (int i = 0; i < nbands; i++) {
+ nbits[i] = 8;
+ }
+ destCM = new ComponentColorModel(destCS, nbits, hasAlpha,
+ srcCM.isAlphaPremultiplied(),
+ srcCM.getTransparency(),
+ DataBuffer.TYPE_BYTE);
+ }
+ int w = src.getWidth();
+ int h = src.getHeight();
+ image = new BufferedImage(destCM,
+ destCM.createCompatibleWritableRaster(w, h),
+ destCM.isAlphaPremultiplied(), null);
+ return image;
+ }
+
+
+ /**
+ * Creates a zeroed destination Raster with the correct size and number of
+ * bands, given this source.
+ * @param src the specified <code>Raster</code>
+ * @return a <code>WritableRaster</code> with the correct size and number
+ * of bands from the specified <code>src</code>
+ * @throws IllegalArgumentException if this <code>ColorConvertOp</code>
+ * was created without sufficient information to define the
+ * <code>dst</code> and <code>src</code> color spaces
+ */
+ public WritableRaster createCompatibleDestRaster (Raster src) {
+ int ncomponents;
+
+ if (CSList != null) {
+ /* non-ICC case */
+ if (CSList.length != 2) {
+ throw new IllegalArgumentException(
+ "Destination ColorSpace is undefined");
+ }
+ ncomponents = CSList[1].getNumComponents();
+ } else {
+ /* ICC case */
+ int nProfiles = profileList.length;
+ if (nProfiles < 2) {
+ throw new IllegalArgumentException(
+ "Destination ColorSpace is undefined");
+ }
+ ncomponents = profileList[nProfiles-1].getNumComponents();
+ }
+
+ WritableRaster dest =
+ Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
+ src.getWidth(),
+ src.getHeight(),
+ ncomponents,
+ new Point(src.getMinX(), src.getMinY()));
+ return dest;
+ }
+
+ /**
+ * Returns the location of the destination point given a
+ * point in the source. If <code>dstPt</code> is non-null,
+ * it will be used to hold the return value. Note that
+ * for this class, the destination point will be the same
+ * as the source point.
+ * @param srcPt the specified source <code>Point2D</code>
+ * @param dstPt the destination <code>Point2D</code>
+ * @return <code>dstPt</code> after setting its location to be
+ * the same as <code>srcPt</code>
+ */
+ public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt) {
+ if (dstPt == null) {
+ dstPt = new Point2D.Float();
+ }
+ dstPt.setLocation(srcPt.getX(), srcPt.getY());
+
+ return dstPt;
+ }
+
+
+ /**
+ * Returns the RenderingIntent from the specified ICC Profile.
+ */
+ private int getRenderingIntent (ICC_Profile profile) {
+ byte[] header = profile.getData(ICC_Profile.icSigHead);
+ int index = ICC_Profile.icHdrRenderingIntent;
+ return (((header[index] & 0xff) << 24) |
+ ((header[index+1] & 0xff) << 16) |
+ ((header[index+2] & 0xff) << 8) |
+ (header[index+3] & 0xff));
+ }
+
+ /**
+ * Returns the rendering hints used by this op.
+ * @return the <code>RenderingHints</code> object of this
+ * <code>ColorConvertOp</code>
+ */
+ public final RenderingHints getRenderingHints() {
+ return hints;
+ }
+
+ private final BufferedImage nonICCBIFilter(BufferedImage src,
+ ColorSpace srcColorSpace,
+ BufferedImage dst,
+ ColorSpace dstColorSpace) {
+
+ int w = src.getWidth();
+ int h = src.getHeight();
+ ICC_ColorSpace ciespace =
+ (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_CIEXYZ);
+ if (dst == null) {
+ dst = createCompatibleDestImage(src, null);
+ dstColorSpace = dst.getColorModel().getColorSpace();
+ } else {
+ if ((h != dst.getHeight()) || (w != dst.getWidth())) {
+ throw new IllegalArgumentException(
+ "Width or height of BufferedImages do not match");
+ }
+ }
+ Raster srcRas = src.getRaster();
+ WritableRaster dstRas = dst.getRaster();
+ ColorModel srcCM = src.getColorModel();
+ ColorModel dstCM = dst.getColorModel();
+ int srcNumComp = srcCM.getNumColorComponents();
+ int dstNumComp = dstCM.getNumColorComponents();
+ boolean dstHasAlpha = dstCM.hasAlpha();
+ boolean needSrcAlpha = srcCM.hasAlpha() && dstHasAlpha;
+ ColorSpace[] list;
+ if ((CSList == null) && (profileList.length != 0)) {
+ /* possible non-ICC src, some profiles, possible non-ICC dst */
+ boolean nonICCSrc, nonICCDst;
+ ICC_Profile srcProfile, dstProfile;
+ if (!(srcColorSpace instanceof ICC_ColorSpace)) {
+ nonICCSrc = true;
+ srcProfile = ciespace.getProfile();
+ } else {
+ nonICCSrc = false;
+ srcProfile = ((ICC_ColorSpace) srcColorSpace).getProfile();
+ }
+ if (!(dstColorSpace instanceof ICC_ColorSpace)) {
+ nonICCDst = true;
+ dstProfile = ciespace.getProfile();
+ } else {
+ nonICCDst = false;
+ dstProfile = ((ICC_ColorSpace) dstColorSpace).getProfile();
+ }
+ /* make a new transform if needed */
+ if ((thisTransform == null) || (thisSrcProfile != srcProfile) ||
+ (thisDestProfile != dstProfile) ) {
+ updateBITransform(srcProfile, dstProfile);
+ }
+ // process per scanline
+ float maxNum = 65535.0f; // use 16-bit precision in CMM
+ ColorSpace cs;
+ int iccSrcNumComp;
+ if (nonICCSrc) {
+ cs = ciespace;
+ iccSrcNumComp = 3;
+ } else {
+ cs = srcColorSpace;
+ iccSrcNumComp = srcNumComp;
+ }
+ float[] srcMinVal = new float[iccSrcNumComp];
+ float[] srcInvDiffMinMax = new float[iccSrcNumComp];
+ for (int i = 0; i < srcNumComp; i++) {
+ srcMinVal[i] = cs.getMinValue(i);
+ srcInvDiffMinMax[i] = maxNum / (cs.getMaxValue(i) - srcMinVal[i]);
+ }
+ int iccDstNumComp;
+ if (nonICCDst) {
+ cs = ciespace;
+ iccDstNumComp = 3;
+ } else {
+ cs = dstColorSpace;
+ iccDstNumComp = dstNumComp;
+ }
+ float[] dstMinVal = new float[iccDstNumComp];
+ float[] dstDiffMinMax = new float[iccDstNumComp];
+ for (int i = 0; i < dstNumComp; i++) {
+ dstMinVal[i] = cs.getMinValue(i);
+ dstDiffMinMax[i] = (cs.getMaxValue(i) - dstMinVal[i]) / maxNum;
+ }
+ float[] dstColor;
+ if (dstHasAlpha) {
+ int size = ((dstNumComp + 1) > 3) ? (dstNumComp + 1) : 3;
+ dstColor = new float[size];
+ } else {
+ int size = (dstNumComp > 3) ? dstNumComp : 3;
+ dstColor = new float[size];
+ }
+ short[] srcLine = new short[w * iccSrcNumComp];
+ short[] dstLine = new short[w * iccDstNumComp];
+ Object pixel;
+ float[] color;
+ float[] alpha = null;
+ if (needSrcAlpha) {
+ alpha = new float[w];
+ }
+ int idx;
+ // process each scanline
+ for (int y = 0; y < h; y++) {
+ // convert src scanline
+ pixel = null;
+ color = null;
+ idx = 0;
+ for (int x = 0; x < w; x++) {
+ pixel = srcRas.getDataElements(x, y, pixel);
+ color = srcCM.getNormalizedComponents(pixel, color, 0);
+ if (needSrcAlpha) {
+ alpha[x] = color[srcNumComp];
+ }
+ if (nonICCSrc) {
+ color = srcColorSpace.toCIEXYZ(color);
+ }
+ for (int i = 0; i < iccSrcNumComp; i++) {
+ srcLine[idx++] = (short)
+ ((color[i] - srcMinVal[i]) * srcInvDiffMinMax[i] +
+ 0.5f);
+ }
+ }
+ // color convert srcLine to dstLine
+ thisTransform.colorConvert(srcLine, dstLine);
+ // convert dst scanline
+ pixel = null;
+ idx = 0;
+ for (int x = 0; x < w; x++) {
+ for (int i = 0; i < iccDstNumComp; i++) {
+ dstColor[i] = ((float) (dstLine[idx++] & 0xffff)) *
+ dstDiffMinMax[i] + dstMinVal[i];
+ }
+ if (nonICCDst) {
+ color = srcColorSpace.fromCIEXYZ(dstColor);
+ for (int i = 0; i < dstNumComp; i++) {
+ dstColor[i] = color[i];
+ }
+ }
+ if (needSrcAlpha) {
+ dstColor[dstNumComp] = alpha[x];
+ } else if (dstHasAlpha) {
+ dstColor[dstNumComp] = 1.0f;
+ }
+ pixel = dstCM.getDataElements(dstColor, 0, pixel);
+ dstRas.setDataElements(x, y, pixel);
+ }
+ }
+ } else {
+ /* possible non-ICC src, possible CSList, possible non-ICC dst */
+ // process per pixel
+ int numCS;
+ if (CSList == null) {
+ numCS = 0;
+ } else {
+ numCS = CSList.length;
+ }
+ float[] dstColor;
+ if (dstHasAlpha) {
+ dstColor = new float[dstNumComp + 1];
+ } else {
+ dstColor = new float[dstNumComp];
+ }
+ Object spixel = null;
+ Object dpixel = null;
+ float[] color = null;
+ float[] tmpColor;
+ // process each pixel
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ spixel = srcRas.getDataElements(x, y, spixel);
+ color = srcCM.getNormalizedComponents(spixel, color, 0);
+ tmpColor = srcColorSpace.toCIEXYZ(color);
+ for (int i = 0; i < numCS; i++) {
+ tmpColor = CSList[i].fromCIEXYZ(tmpColor);
+ tmpColor = CSList[i].toCIEXYZ(tmpColor);
+ }
+ tmpColor = dstColorSpace.fromCIEXYZ(tmpColor);
+ for (int i = 0; i < dstNumComp; i++) {
+ dstColor[i] = tmpColor[i];
+ }
+ if (needSrcAlpha) {
+ dstColor[dstNumComp] = color[srcNumComp];
+ } else if (dstHasAlpha) {
+ dstColor[dstNumComp] = 1.0f;
+ }
+ dpixel = dstCM.getDataElements(dstColor, 0, dpixel);
+ dstRas.setDataElements(x, y, dpixel);
+
+ }
+ }
+ }
+
+ return dst;
+ }
+
+ /* color convert a Raster - handles byte, ushort, int, short, float,
+ or double transferTypes */
+ private final WritableRaster nonICCRasterFilter(Raster src,
+ WritableRaster dst) {
+
+ if (CSList.length != 2) {
+ throw new IllegalArgumentException(
+ "Destination ColorSpace is undefined");
+ }
+ if (src.getNumBands() != CSList[0].getNumComponents()) {
+ throw new IllegalArgumentException(
+ "Numbers of source Raster bands and source color space " +
+ "components do not match");
+ }
+ if (dst == null) {
+ dst = createCompatibleDestRaster(src);
+ } else {
+ if (src.getHeight() != dst.getHeight() ||
+ src.getWidth() != dst.getWidth()) {
+ throw new IllegalArgumentException(
+ "Width or height of Rasters do not match");
+ }
+ if (dst.getNumBands() != CSList[1].getNumComponents()) {
+ throw new IllegalArgumentException(
+ "Numbers of destination Raster bands and destination " +
+ "color space components do not match");
+ }
+ }
+
+ if (srcMinVals == null) {
+ getMinMaxValsFromColorSpaces(CSList[0], CSList[1]);
+ }
+
+ SampleModel srcSM = src.getSampleModel();
+ SampleModel dstSM = dst.getSampleModel();
+ boolean srcIsFloat, dstIsFloat;
+ int srcTransferType = src.getTransferType();
+ int dstTransferType = dst.getTransferType();
+ if ((srcTransferType == DataBuffer.TYPE_FLOAT) ||
+ (srcTransferType == DataBuffer.TYPE_DOUBLE)) {
+ srcIsFloat = true;
+ } else {
+ srcIsFloat = false;
+ }
+ if ((dstTransferType == DataBuffer.TYPE_FLOAT) ||
+ (dstTransferType == DataBuffer.TYPE_DOUBLE)) {
+ dstIsFloat = true;
+ } else {
+ dstIsFloat = false;
+ }
+ int w = src.getWidth();
+ int h = src.getHeight();
+ int srcNumBands = src.getNumBands();
+ int dstNumBands = dst.getNumBands();
+ float[] srcScaleFactor = null;
+ float[] dstScaleFactor = null;
+ if (!srcIsFloat) {
+ srcScaleFactor = new float[srcNumBands];
+ for (int i = 0; i < srcNumBands; i++) {
+ if (srcTransferType == DataBuffer.TYPE_SHORT) {
+ srcScaleFactor[i] = (srcMaxVals[i] - srcMinVals[i]) /
+ 32767.0f;
+ } else {
+ srcScaleFactor[i] = (srcMaxVals[i] - srcMinVals[i]) /
+ ((float) ((1 << srcSM.getSampleSize(i)) - 1));
+ }
+ }
+ }
+ if (!dstIsFloat) {
+ dstScaleFactor = new float[dstNumBands];
+ for (int i = 0; i < dstNumBands; i++) {
+ if (dstTransferType == DataBuffer.TYPE_SHORT) {
+ dstScaleFactor[i] = 32767.0f /
+ (dstMaxVals[i] - dstMinVals[i]);
+ } else {
+ dstScaleFactor[i] =
+ ((float) ((1 << dstSM.getSampleSize(i)) - 1)) /
+ (dstMaxVals[i] - dstMinVals[i]);
+ }
+ }
+ }
+ int ys = src.getMinY();
+ int yd = dst.getMinY();
+ int xs, xd;
+ float sample;
+ float[] color = new float[srcNumBands];
+ float[] tmpColor;
+ ColorSpace srcColorSpace = CSList[0];
+ ColorSpace dstColorSpace = CSList[1];
+ // process each pixel
+ for (int y = 0; y < h; y++, ys++, yd++) {
+ // get src scanline
+ xs = src.getMinX();
+ xd = dst.getMinX();
+ for (int x = 0; x < w; x++, xs++, xd++) {
+ for (int i = 0; i < srcNumBands; i++) {
+ sample = src.getSampleFloat(xs, ys, i);
+ if (!srcIsFloat) {
+ sample = sample * srcScaleFactor[i] + srcMinVals[i];
+ }
+ color[i] = sample;
+ }
+ tmpColor = srcColorSpace.toCIEXYZ(color);
+ tmpColor = dstColorSpace.fromCIEXYZ(tmpColor);
+ for (int i = 0; i < dstNumBands; i++) {
+ sample = tmpColor[i];
+ if (!dstIsFloat) {
+ sample = (sample - dstMinVals[i]) * dstScaleFactor[i];
+ }
+ dst.setSample(xd, yd, i, sample);
+ }
+ }
+ }
+ return dst;
+ }
+
+ private void getMinMaxValsFromProfiles(ICC_Profile srcProfile,
+ ICC_Profile dstProfile) {
+ int type = srcProfile.getColorSpaceType();
+ int nc = srcProfile.getNumComponents();
+ srcMinVals = new float[nc];
+ srcMaxVals = new float[nc];
+ setMinMax(type, nc, srcMinVals, srcMaxVals);
+ type = dstProfile.getColorSpaceType();
+ nc = dstProfile.getNumComponents();
+ dstMinVals = new float[nc];
+ dstMaxVals = new float[nc];
+ setMinMax(type, nc, dstMinVals, dstMaxVals);
+ }
+
+ private void setMinMax(int type, int nc, float[] minVals, float[] maxVals) {
+ if (type == ColorSpace.TYPE_Lab) {
+ minVals[0] = 0.0f; // L
+ maxVals[0] = 100.0f;
+ minVals[1] = -128.0f; // a
+ maxVals[1] = 127.0f;
+ minVals[2] = -128.0f; // b
+ maxVals[2] = 127.0f;
+ } else if (type == ColorSpace.TYPE_XYZ) {
+ minVals[0] = minVals[1] = minVals[2] = 0.0f; // X, Y, Z
+ maxVals[0] = maxVals[1] = maxVals[2] = 1.0f + (32767.0f/ 32768.0f);
+ } else {
+ for (int i = 0; i < nc; i++) {
+ minVals[i] = 0.0f;
+ maxVals[i] = 1.0f;
+ }
+ }
+ }
+
+ private void getMinMaxValsFromColorSpaces(ColorSpace srcCspace,
+ ColorSpace dstCspace) {
+ int nc = srcCspace.getNumComponents();
+ srcMinVals = new float[nc];
+ srcMaxVals = new float[nc];
+ for (int i = 0; i < nc; i++) {
+ srcMinVals[i] = srcCspace.getMinValue(i);
+ srcMaxVals[i] = srcCspace.getMaxValue(i);
+ }
+ nc = dstCspace.getNumComponents();
+ dstMinVals = new float[nc];
+ dstMaxVals = new float[nc];
+ for (int i = 0; i < nc; i++) {
+ dstMinVals[i] = dstCspace.getMinValue(i);
+ dstMaxVals[i] = dstCspace.getMaxValue(i);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/ComponentSampleModel.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,1202 @@
+/*
+ * Portions Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+
+import java.util.Arrays;
+
+/**
+ * This class represents image data which is stored such that each sample
+ * of a pixel occupies one data element of the DataBuffer. It stores the
+ * N samples which make up a pixel in N separate data array elements.
+ * Different bands may be in different banks of the DataBuffer.
+ * Accessor methods are provided so that image data can be manipulated
+ * directly. This class can support different kinds of interleaving, e.g.
+ * band interleaving, scanline interleaving, and pixel interleaving.
+ * Pixel stride is the number of data array elements between two samples
+ * for the same band on the same scanline. Scanline stride is the number
+ * of data array elements between a given sample and the corresponding sample
+ * in the same column of the next scanline. Band offsets denote the number
+ * of data array elements from the first data array element of the bank
+ * of the DataBuffer holding each band to the first sample of the band.
+ * The bands are numbered from 0 to N-1. This class can represent image
+ * data for which each sample is an unsigned integral number which can be
+ * stored in 8, 16, or 32 bits (using <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>, or <code>DataBuffer.TYPE_INT</code>,
+ * respectively), data for which each sample is a signed integral number
+ * which can be stored in 16 bits (using <code>DataBuffer.TYPE_SHORT</code>),
+ * or data for which each sample is a signed float or double quantity
+ * (using <code>DataBuffer.TYPE_FLOAT</code> or
+ * <code>DataBuffer.TYPE_DOUBLE</code>, respectively).
+ * All samples of a given ComponentSampleModel
+ * are stored with the same precision. All strides and offsets must be
+ * non-negative. This class supports
+ * {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
+ * {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
+ * {@link DataBuffer#TYPE_SHORT TYPE_SHORT},
+ * {@link DataBuffer#TYPE_INT TYPE_INT},
+ * {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT},
+ * {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE},
+ * @see java.awt.image.PixelInterleavedSampleModel
+ * @see java.awt.image.BandedSampleModel
+ */
+
+public class ComponentSampleModel extends SampleModel
+{
+ /** Offsets for all bands in data array elements. */
+ protected int bandOffsets[];
+
+ /** Index for each bank storing a band of image data. */
+ protected int[] bankIndices;
+
+ /**
+ * The number of bands in this
+ * <code>ComponentSampleModel</code>.
+ */
+ protected int numBands = 1;
+
+ /**
+ * The number of banks in this
+ * <code>ComponentSampleModel</code>.
+ */
+ protected int numBanks = 1;
+
+ /**
+ * Line stride (in data array elements) of the region of image
+ * data described by this ComponentSampleModel.
+ */
+ protected int scanlineStride;
+
+ /** Pixel stride (in data array elements) of the region of image
+ * data described by this ComponentSampleModel.
+ */
+ protected int pixelStride;
+
+ static private native void initIDs();
+ static {
+ ColorModel.loadLibraries();
+ initIDs();
+ }
+
+ /**
+ * Constructs a ComponentSampleModel with the specified parameters.
+ * The number of bands will be given by the length of the bandOffsets array.
+ * All bands will be stored in the first bank of the DataBuffer.
+ * @param dataType the data type for storing samples
+ * @param w the width (in pixels) of the region of
+ * image data described
+ * @param h the height (in pixels) of the region of
+ * image data described
+ * @param pixelStride the pixel stride of the region of image
+ * data described
+ * @param scanlineStride the line stride of the region of image
+ * data described
+ * @param bandOffsets the offsets of all bands
+ * @throws IllegalArgumentException if <code>w</code> or
+ * <code>h</code> is not greater than 0
+ * @throws IllegalArgumentException if <code>pixelStride</code>
+ * is less than 0
+ * @throws IllegalArgumentException if <code>scanlineStride</code>
+ * is less than 0
+ * @throws IllegalArgumentException if <code>numBands</code>
+ * is less than 1
+ * @throws IllegalArgumentException if the product of <code>w</code>
+ * and <code>h</code> is greater than
+ * <code>Integer.MAX_VALUE</code>
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types
+ */
+ public ComponentSampleModel(int dataType,
+ int w, int h,
+ int pixelStride,
+ int scanlineStride,
+ int bandOffsets[]) {
+ super(dataType, w, h, bandOffsets.length);
+ this.dataType = dataType;
+ this.pixelStride = pixelStride;
+ this.scanlineStride = scanlineStride;
+ this.bandOffsets = (int[])bandOffsets.clone();
+ numBands = bandOffsets.length;
+ if (pixelStride < 0) {
+ throw new IllegalArgumentException("Pixel stride must be >= 0");
+ }
+ // TODO - bug 4296691 - remove this check
+ if (scanlineStride < 0) {
+ throw new IllegalArgumentException("Scanline stride must be >= 0");
+ }
+ if (numBands < 1) {
+ throw new IllegalArgumentException("Must have at least one band.");
+ }
+ if ((dataType < DataBuffer.TYPE_BYTE) ||
+ (dataType > DataBuffer.TYPE_DOUBLE)) {
+ throw new IllegalArgumentException("Unsupported dataType.");
+ }
+ bankIndices = new int[numBands];
+ for (int i=0; i<numBands; i++) {
+ bankIndices[i] = 0;
+ }
+ }
+
+
+ /**
+ * Constructs a ComponentSampleModel with the specified parameters.
+ * The number of bands will be given by the length of the bandOffsets array.
+ * Different bands may be stored in different banks of the DataBuffer.
+ *
+ * @param dataType the data type for storing samples
+ * @param w the width (in pixels) of the region of
+ * image data described
+ * @param h the height (in pixels) of the region of
+ * image data described
+ * @param pixelStride the pixel stride of the region of image
+ * data described
+ * @param scanlineStride The line stride of the region of image
+ * data described
+ * @param bankIndices the bank indices of all bands
+ * @param bandOffsets the band offsets of all bands
+ * @throws IllegalArgumentException if <code>w</code> or
+ * <code>h</code> is not greater than 0
+ * @throws IllegalArgumentException if <code>pixelStride</code>
+ * is less than 0
+ * @throws IllegalArgumentException if <code>scanlineStride</code>
+ * is less than 0
+ * @throws IllegalArgumentException if the length of
+ * <code>bankIndices</code> does not equal the length of
+ * <code>bankOffsets</code>
+ * @throws IllegalArgumentException if any of the bank indices
+ * of <code>bandIndices</code> is less than 0
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types
+ */
+ public ComponentSampleModel(int dataType,
+ int w, int h,
+ int pixelStride,
+ int scanlineStride,
+ int bankIndices[],
+ int bandOffsets[]) {
+ super(dataType, w, h, bandOffsets.length);
+ this.dataType = dataType;
+ this.pixelStride = pixelStride;
+ this.scanlineStride = scanlineStride;
+ this.bandOffsets = (int[])bandOffsets.clone();
+ this.bankIndices = (int[]) bankIndices.clone();
+ if (pixelStride < 0) {
+ throw new IllegalArgumentException("Pixel stride must be >= 0");
+ }
+ // TODO - bug 4296691 - remove this check
+ if (scanlineStride < 0) {
+ throw new IllegalArgumentException("Scanline stride must be >= 0");
+ }
+ if ((dataType < DataBuffer.TYPE_BYTE) ||
+ (dataType > DataBuffer.TYPE_DOUBLE)) {
+ throw new IllegalArgumentException("Unsupported dataType.");
+ }
+ int maxBank = bankIndices[0];
+ if (maxBank < 0) {
+ throw new IllegalArgumentException("Index of bank 0 is less than "+
+ "0 ("+maxBank+")");
+ }
+ for (int i=1; i < bankIndices.length; i++) {
+ if (bankIndices[i] > maxBank) {
+ maxBank = bankIndices[i];
+ }
+ else if (bankIndices[i] < 0) {
+ throw new IllegalArgumentException("Index of bank "+i+
+ " is less than 0 ("+
+ maxBank+")");
+ }
+ }
+ numBanks = maxBank+1;
+ numBands = bandOffsets.length;
+ if (bandOffsets.length != bankIndices.length) {
+ throw new IllegalArgumentException("Length of bandOffsets must "+
+ "equal length of bankIndices.");
+ }
+ }
+
+ /**
+ * Returns the size of the data buffer (in data elements) needed
+ * for a data buffer that matches this ComponentSampleModel.
+ */
+ private long getBufferSize() {
+ int maxBandOff=bandOffsets[0];
+ for (int i=1; i<bandOffsets.length; i++)
+ maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
+
+ long size = 0;
+ if (maxBandOff >= 0)
+ size += maxBandOff+1;
+ if (pixelStride > 0)
+ size += pixelStride * (width-1);
+ if (scanlineStride > 0)
+ size += scanlineStride*(height-1);
+ return size;
+ }
+
+ /**
+ * Preserves band ordering with new step factor...
+ */
+ int []orderBands(int orig[], int step) {
+ int map[] = new int[orig.length];
+ int ret[] = new int[orig.length];
+
+ for (int i=0; i<map.length; i++) map[i] = i;
+
+ for (int i = 0; i < ret.length; i++) {
+ int index = i;
+ for (int j = i+1; j < ret.length; j++) {
+ if (orig[map[index]] > orig[map[j]]) {
+ index = j;
+ }
+ }
+ ret[map[index]] = i*step;
+ map[index] = map[i];
+ }
+ return ret;
+ }
+
+ /**
+ * Creates a new <code>ComponentSampleModel</code> with the specified
+ * width and height. The new <code>SampleModel</code> will have the same
+ * number of bands, storage data type, interleaving scheme, and
+ * pixel stride as this <code>SampleModel</code>.
+ * @param w the width of the resulting <code>SampleModel</code>
+ * @param h the height of the resulting <code>SampleModel</code>
+ * @return a new <code>ComponentSampleModel</code> with the specified size
+ * @throws IllegalArgumentException if <code>w</code> or
+ * <code>h</code> is not greater than 0
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ SampleModel ret=null;
+ long size;
+ int minBandOff=bandOffsets[0];
+ int maxBandOff=bandOffsets[0];
+ for (int i=1; i<bandOffsets.length; i++) {
+ minBandOff = Math.min(minBandOff,bandOffsets[i]);
+ maxBandOff = Math.max(maxBandOff,bandOffsets[i]);
+ }
+ maxBandOff -= minBandOff;
+
+ int bands = bandOffsets.length;
+ int bandOff[];
+ int pStride = Math.abs(pixelStride);
+ int lStride = Math.abs(scanlineStride);
+ int bStride = Math.abs(maxBandOff);
+
+ if (pStride > lStride) {
+ if (pStride > bStride) {
+ if (lStride > bStride) { // pix > line > band
+ bandOff = new int[bandOffsets.length];
+ for (int i=0; i<bands; i++)
+ bandOff[i] = bandOffsets[i]-minBandOff;
+ lStride = bStride+1;
+ pStride = lStride*h;
+ } else { // pix > band > line
+ bandOff = orderBands(bandOffsets,lStride*h);
+ pStride = bands*lStride*h;
+ }
+ } else { // band > pix > line
+ pStride = lStride*h;
+ bandOff = orderBands(bandOffsets,pStride*w);
+ }
+ } else {
+ if (pStride > bStride) { // line > pix > band
+ bandOff = new int[bandOffsets.length];
+ for (int i=0; i<bands; i++)
+ bandOff[i] = bandOffsets[i]-minBandOff;
+ pStride = bStride+1;
+ lStride = pStride*w;
+ } else {
+ if (lStride > bStride) { // line > band > pix
+ bandOff = orderBands(bandOffsets,pStride*w);
+ lStride = bands*pStride*w;
+ } else { // band > line > pix
+ lStride = pStride*w;
+ bandOff = orderBands(bandOffsets,lStride*h);
+ }
+ }
+ }
+
+ // make sure we make room for negative offsets...
+ int base = 0;
+ if (scanlineStride < 0) {
+ base += lStride*h;
+ lStride *= -1;
+ }
+ if (pixelStride < 0) {
+ base += pStride*w;
+ pStride *= -1;
+ }
+
+ for (int i=0; i<bands; i++)
+ bandOff[i] += base;
+ return new ComponentSampleModel(dataType, w, h, pStride,
+ lStride, bankIndices, bandOff);
+ }
+
+ /**
+ * Creates a new ComponentSampleModel with a subset of the bands
+ * of this ComponentSampleModel. The new ComponentSampleModel can be
+ * used with any DataBuffer that the existing ComponentSampleModel
+ * can be used with. The new ComponentSampleModel/DataBuffer
+ * combination will represent an image with a subset of the bands
+ * of the original ComponentSampleModel/DataBuffer combination.
+ * @param bands a subset of bands from this
+ * <code>ComponentSampleModel</code>
+ * @return a <code>ComponentSampleModel</code> created with a subset
+ * of bands from this <code>ComponentSampleModel</code>.
+ */
+ public SampleModel createSubsetSampleModel(int bands[]) {
+ if (bands.length > bankIndices.length)
+ throw new RasterFormatException("There are only " +
+ bankIndices.length +
+ " bands");
+ int newBankIndices[] = new int[bands.length];
+ int newBandOffsets[] = new int[bands.length];
+
+ for (int i=0; i<bands.length; i++) {
+ newBankIndices[i] = bankIndices[bands[i]];
+ newBandOffsets[i] = bandOffsets[bands[i]];
+ }
+
+ return new ComponentSampleModel(this.dataType, width, height,
+ this.pixelStride,
+ this.scanlineStride,
+ newBankIndices, newBandOffsets);
+ }
+
+ /**
+ * Creates a <code>DataBuffer</code> that corresponds to this
+ * <code>ComponentSampleModel</code>.
+ * The <code>DataBuffer</code> object's data type, number of banks,
+ * and size are be consistent with this <code>ComponentSampleModel</code>.
+ * @return a <code>DataBuffer</code> whose data type, number of banks
+ * and size are consistent with this
+ * <code>ComponentSampleModel</code>.
+ */
+ public DataBuffer createDataBuffer() {
+ DataBuffer dataBuffer = null;
+
+ int size = (int)getBufferSize();
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ dataBuffer = new DataBufferByte(size, numBanks);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ dataBuffer = new DataBufferUShort(size, numBanks);
+ break;
+ case DataBuffer.TYPE_SHORT:
+ dataBuffer = new DataBufferShort(size, numBanks);
+ break;
+ case DataBuffer.TYPE_INT:
+ dataBuffer = new DataBufferInt(size, numBanks);
+ break;
+ case DataBuffer.TYPE_FLOAT:
+ dataBuffer = new DataBufferFloat(size, numBanks);
+ break;
+ case DataBuffer.TYPE_DOUBLE:
+ dataBuffer = new DataBufferDouble(size, numBanks);
+ break;
+ }
+
+ return dataBuffer;
+ }
+
+
+ /** Gets the offset for the first band of pixel (x,y).
+ * A sample of the first band can be retrieved from a
+ * <code>DataBuffer</code>
+ * <code>data</code> with a <code>ComponentSampleModel</code>
+ * <code>csm</code> as
+ * <pre>
+ * data.getElem(csm.getOffset(x, y));
+ * </pre>
+ * @param x the X location of the pixel
+ * @param y the Y location of the pixel
+ * @return the offset for the first band of the specified pixel.
+ */
+ public int getOffset(int x, int y) {
+ int offset = y*scanlineStride + x*pixelStride + bandOffsets[0];
+ return offset;
+ }
+
+ /** Gets the offset for band b of pixel (x,y).
+ * A sample of band <code>b</code> can be retrieved from a
+ * <code>DataBuffer</code> <code>data</code>
+ * with a <code>ComponentSampleModel</code> <code>csm</code> as
+ * <pre>
+ * data.getElem(csm.getOffset(x, y, b));
+ * </pre>
+ * @param x the X location of the specified pixel
+ * @param y the Y location of the specified pixel
+ * @param b the specified band
+ * @return the offset for the specified band of the specified pixel.
+ */
+ public int getOffset(int x, int y, int b) {
+ int offset = y*scanlineStride + x*pixelStride + bandOffsets[b];
+ return offset;
+ }
+
+ /** Returns the number of bits per sample for all bands.
+ * @return an array containing the number of bits per sample
+ * for all bands, where each element in the array
+ * represents a band.
+ */
+ public final int[] getSampleSize() {
+ int sampleSize[] = new int [numBands];
+ int sizeInBits = getSampleSize(0);
+
+ for (int i=0; i<numBands; i++)
+ sampleSize[i] = sizeInBits;
+
+ return sampleSize;
+ }
+
+ /** Returns the number of bits per sample for the specified band.
+ * @param band the specified band
+ * @return the number of bits per sample for the specified band.
+ */
+ public final int getSampleSize(int band) {
+ return DataBuffer.getDataTypeSize(dataType);
+ }
+
+ /** Returns the bank indices for all bands.
+ * @return the bank indices for all bands.
+ */
+ public final int [] getBankIndices() {
+ return (int[]) bankIndices.clone();
+ }
+
+ /** Returns the band offset for all bands.
+ * @return the band offsets for all bands.
+ */
+ public final int [] getBandOffsets() {
+ return (int[])bandOffsets.clone();
+ }
+
+ /** Returns the scanline stride of this ComponentSampleModel.
+ * @return the scanline stride of this <code>ComponentSampleModel</code>.
+ */
+ public final int getScanlineStride() {
+ return scanlineStride;
+ }
+
+ /** Returns the pixel stride of this ComponentSampleModel.
+ * @return the pixel stride of this <code>ComponentSampleModel</code>.
+ */
+ public final int getPixelStride() {
+ return pixelStride;
+ }
+
+ /**
+ * Returns the number of data elements needed to transfer a pixel
+ * with the
+ * {@link #getDataElements(int, int, Object, DataBuffer) } and
+ * {@link #setDataElements(int, int, Object, DataBuffer) }
+ * methods.
+ * For a <code>ComponentSampleModel</code>, this is identical to the
+ * number of bands.
+ * @return the number of data elements needed to transfer a pixel with
+ * the <code>getDataElements</code> and
+ * <code>setDataElements</code> methods.
+ * @see java.awt.image.SampleModel#getNumDataElements
+ * @see #getNumBands
+ */
+ public final int getNumDataElements() {
+ return getNumBands();
+ }
+
+ /**
+ * Returns data for a single pixel in a primitive array of type
+ * <code>TransferType</code>. For a <code>ComponentSampleModel</code>,
+ * this is the same as the data type, and samples are returned
+ * one per array element. Generally, <code>obj</code> should
+ * be passed in as <code>null</code>, so that the <code>Object</code>
+ * is created automatically and is the right primitive data type.
+ * <p>
+ * The following code illustrates transferring data for one pixel from
+ * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
+ * described by <code>ComponentSampleModel</code> <code>csm1</code>,
+ * to <code>DataBuffer</code> <code>db2</code>, whose storage layout
+ * is described by <code>ComponentSampleModel</code> <code>csm2</code>.
+ * The transfer is usually more efficient than using
+ * <code>getPixel</code> and <code>setPixel</code>.
+ * <pre>
+ * ComponentSampleModel csm1, csm2;
+ * DataBufferInt db1, db2;
+ * csm2.setDataElements(x, y,
+ * csm1.getDataElements(x, y, null, db1), db2);
+ * </pre>
+ *
+ * Using <code>getDataElements</code> and <code>setDataElements</code>
+ * to transfer between two <code>DataBuffer/SampleModel</code>
+ * pairs is legitimate if the <code>SampleModel</code> objects have
+ * the same number of bands, corresponding bands have the same number of
+ * bits per sample, and the <code>TransferType</code>s are the same.
+ * <p>
+ * If <code>obj</code> is not <code>null</code>, it should be a
+ * primitive array of type <code>TransferType</code>.
+ * Otherwise, a <code>ClassCastException</code> is thrown. An
+ * <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
+ * coordinates are not in bounds, or if <code>obj</code> is not
+ * <code>null</code> and is not large enough to hold
+ * the pixel data.
+ *
+ * @param x the X coordinate of the pixel location
+ * @param y the Y coordinate of the pixel location
+ * @param obj if non-<code>null</code>, a primitive array
+ * in which to return the pixel data
+ * @param data the <code>DataBuffer</code> containing the image data
+ * @return the data of the specified pixel
+ * @see #setDataElements(int, int, Object, DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if obj is too small to hold the ouput.
+ */
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ int type = getTransferType();
+ int numDataElems = getNumDataElements();
+ int pixelOffset = y*scanlineStride + x*pixelStride;
+
+ switch(type) {
+
+ case DataBuffer.TYPE_BYTE:
+
+ byte[] bdata;
+
+ if (obj == null)
+ bdata = new byte[numDataElems];
+ else
+ bdata = (byte[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ bdata[i] = (byte)data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)bdata;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
+
+ short[] sdata;
+
+ if (obj == null)
+ sdata = new short[numDataElems];
+ else
+ sdata = (short[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ sdata[i] = (short)data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)sdata;
+ break;
+
+ case DataBuffer.TYPE_INT:
+
+ int[] idata;
+
+ if (obj == null)
+ idata = new int[numDataElems];
+ else
+ idata = (int[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ idata[i] = data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)idata;
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+
+ float[] fdata;
+
+ if (obj == null)
+ fdata = new float[numDataElems];
+ else
+ fdata = (float[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ fdata[i] = data.getElemFloat(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)fdata;
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+
+ double[] ddata;
+
+ if (obj == null)
+ ddata = new double[numDataElems];
+ else
+ ddata = (double[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ ddata[i] = data.getElemDouble(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)ddata;
+ break;
+ }
+
+ return obj;
+ }
+
+ /**
+ * Returns all samples for the specified pixel in an int array,
+ * one sample per array element.
+ * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
+ * the coordinates are not in bounds.
+ * @param x the X coordinate of the pixel location
+ * @param y the Y coordinate of the pixel location
+ * @param iArray If non-null, returns the samples in this array
+ * @param data The DataBuffer containing the image data
+ * @return the samples of the specified pixel.
+ * @see #setPixel(int, int, int[], DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if iArray is too small to hold the output.
+ */
+ public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int pixels[];
+ if (iArray != null) {
+ pixels = iArray;
+ } else {
+ pixels = new int [numBands];
+ }
+ int pixelOffset = y*scanlineStride + x*pixelStride;
+ for (int i=0; i<numBands; i++) {
+ pixels[i] = data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+ return pixels;
+ }
+
+ /**
+ * Returns all samples for the specified rectangle of pixels in
+ * an int array, one sample per array element.
+ * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
+ * the coordinates are not in bounds.
+ * @param x The X coordinate of the upper left pixel location
+ * @param y The Y coordinate of the upper left pixel location
+ * @param w The width of the pixel rectangle
+ * @param h The height of the pixel rectangle
+ * @param iArray If non-null, returns the samples in this array
+ * @param data The DataBuffer containing the image data
+ * @return the samples of the pixels within the specified region.
+ * @see #setPixels(int, int, int, int, int[], DataBuffer)
+ */
+ public int[] getPixels(int x, int y, int w, int h,
+ int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int pixels[];
+ if (iArray != null) {
+ pixels = iArray;
+ } else {
+ pixels = new int [w*h*numBands];
+ }
+ int lineOffset = y*scanlineStride + x*pixelStride;
+ int srcOffset = 0;
+
+ for (int i = 0; i < h; i++) {
+ int pixelOffset = lineOffset;
+ for (int j = 0; j < w; j++) {
+ for (int k=0; k < numBands; k++) {
+ pixels[srcOffset++] =
+ data.getElem(bankIndices[k], pixelOffset + bandOffsets[k]);
+ }
+ pixelOffset += pixelStride;
+ }
+ lineOffset += scanlineStride;
+ }
+ return pixels;
+ }
+
+ /**
+ * Returns as int the sample in a specified band for the pixel
+ * located at (x,y).
+ * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
+ * the coordinates are not in bounds.
+ * @param x the X coordinate of the pixel location
+ * @param y the Y coordinate of the pixel location
+ * @param b the band to return
+ * @param data the <code>DataBuffer</code> containing the image data
+ * @return the sample in a specified band for the specified pixel
+ * @see #setSample(int, int, int, int, DataBuffer)
+ */
+ public int getSample(int x, int y, int b, DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int sample = data.getElem(bankIndices[b],
+ y*scanlineStride + x*pixelStride +
+ bandOffsets[b]);
+ return sample;
+ }
+
+ /**
+ * Returns the sample in a specified band
+ * for the pixel located at (x,y) as a float.
+ * An <code>ArrayIndexOutOfBoundsException</code> might be
+ * thrown if the coordinates are not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to return
+ * @param data The DataBuffer containing the image data
+ * @return a float value representing the sample in the specified
+ * band for the specified pixel.
+ */
+ public float getSampleFloat(int x, int y, int b, DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ float sample = data.getElemFloat(bankIndices[b],
+ y*scanlineStride + x*pixelStride +
+ bandOffsets[b]);
+ return sample;
+ }
+
+ /**
+ * Returns the sample in a specified band
+ * for a pixel located at (x,y) as a double.
+ * An <code>ArrayIndexOutOfBoundsException</code> might be
+ * thrown if the coordinates are not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to return
+ * @param data The DataBuffer containing the image data
+ * @return a double value representing the sample in the specified
+ * band for the specified pixel.
+ */
+ public double getSampleDouble(int x, int y, int b, DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ double sample = data.getElemDouble(bankIndices[b],
+ y*scanlineStride + x*pixelStride +
+ bandOffsets[b]);
+ return sample;
+ }
+
+ /**
+ * Returns the samples in a specified band for the specified rectangle
+ * of pixels in an int array, one sample per data array element.
+ * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
+ * the coordinates are not in bounds.
+ * @param x The X coordinate of the upper left pixel location
+ * @param y The Y coordinate of the upper left pixel location
+ * @param w the width of the pixel rectangle
+ * @param h the height of the pixel rectangle
+ * @param b the band to return
+ * @param iArray if non-<code>null</code>, returns the samples
+ * in this array
+ * @param data the <code>DataBuffer</code> containing the image data
+ * @return the samples in the specified band of the specified pixel
+ * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
+ */
+ public int[] getSamples(int x, int y, int w, int h, int b,
+ int iArray[], DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int samples[];
+ if (iArray != null) {
+ samples = iArray;
+ } else {
+ samples = new int [w*h];
+ }
+ int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b];
+ int srcOffset = 0;
+
+ for (int i = 0; i < h; i++) {
+ int sampleOffset = lineOffset;
+ for (int j = 0; j < w; j++) {
+ samples[srcOffset++] = data.getElem(bankIndices[b],
+ sampleOffset);
+ sampleOffset += pixelStride;
+ }
+ lineOffset += scanlineStride;
+ }
+ return samples;
+ }
+
+ /**
+ * Sets the data for a single pixel in the specified
+ * <code>DataBuffer</code> from a primitive array of type
+ * <code>TransferType</code>. For a <code>ComponentSampleModel</code>,
+ * this is the same as the data type, and samples are transferred
+ * one per array element.
+ * <p>
+ * The following code illustrates transferring data for one pixel from
+ * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
+ * described by <code>ComponentSampleModel</code> <code>csm1</code>,
+ * to <code>DataBuffer</code> <code>db2</code>, whose storage layout
+ * is described by <code>ComponentSampleModel</code> <code>csm2</code>.
+ * The transfer is usually more efficient than using
+ * <code>getPixel</code> and <code>setPixel</code>.
+ * <pre>
+ * ComponentSampleModel csm1, csm2;
+ * DataBufferInt db1, db2;
+ * csm2.setDataElements(x, y, csm1.getDataElements(x, y, null, db1),
+ * db2);
+ * </pre>
+ * Using <code>getDataElements</code> and <code>setDataElements</code>
+ * to transfer between two <code>DataBuffer/SampleModel</code> pairs
+ * is legitimate if the <code>SampleModel</code> objects have
+ * the same number of bands, corresponding bands have the same number of
+ * bits per sample, and the <code>TransferType</code>s are the same.
+ * <p>
+ * A <code>ClassCastException</code> is thrown if <code>obj</code> is not
+ * a primitive array of type <code>TransferType</code>.
+ * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
+ * the coordinates are not in bounds, or if <code>obj</code> is not large
+ * enough to hold the pixel data.
+ * @param x the X coordinate of the pixel location
+ * @param y the Y coordinate of the pixel location
+ * @param obj a primitive array containing pixel data
+ * @param data the DataBuffer containing the image data
+ * @see #getDataElements(int, int, Object, DataBuffer)
+ */
+ public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ int type = getTransferType();
+ int numDataElems = getNumDataElements();
+ int pixelOffset = y*scanlineStride + x*pixelStride;
+
+ switch(type) {
+
+ case DataBuffer.TYPE_BYTE:
+
+ byte[] barray = (byte[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
+ ((int)barray[i])&0xff);
+ }
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
+
+ short[] sarray = (short[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ data.setElem(bankIndices[i], pixelOffset + bandOffsets[i],
+ ((int)sarray[i])&0xffff);
+ }
+ break;
+
+ case DataBuffer.TYPE_INT:
+
+ int[] iarray = (int[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ data.setElem(bankIndices[i],
+ pixelOffset + bandOffsets[i], iarray[i]);
+ }
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+
+ float[] farray = (float[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ data.setElemFloat(bankIndices[i],
+ pixelOffset + bandOffsets[i], farray[i]);
+ }
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+
+ double[] darray = (double[])obj;
+
+ for (int i=0; i<numDataElems; i++) {
+ data.setElemDouble(bankIndices[i],
+ pixelOffset + bandOffsets[i], darray[i]);
+ }
+ break;
+
+ }
+ }
+
+ /**
+ * Sets a pixel in the <code>DataBuffer</code> using an int array of
+ * samples for input. An <code>ArrayIndexOutOfBoundsException</code>
+ * might be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param iArray The input samples in an int array
+ * @param data The DataBuffer containing the image data
+ * @see #getPixel(int, int, int[], DataBuffer)
+ */
+ public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int pixelOffset = y*scanlineStride + x*pixelStride;
+ for (int i=0; i<numBands; i++) {
+ data.setElem(bankIndices[i],
+ pixelOffset + bandOffsets[i],iArray[i]);
+ }
+ }
+
+ /**
+ * Sets all samples for a rectangle of pixels from an int array containing
+ * one sample per array element.
+ * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
+ * coordinates are not in bounds.
+ * @param x The X coordinate of the upper left pixel location
+ * @param y The Y coordinate of the upper left pixel location
+ * @param w The width of the pixel rectangle
+ * @param h The height of the pixel rectangle
+ * @param iArray The input samples in an int array
+ * @param data The DataBuffer containing the image data
+ * @see #getPixels(int, int, int, int, int[], DataBuffer)
+ */
+ public void setPixels(int x, int y, int w, int h,
+ int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ int lineOffset = y*scanlineStride + x*pixelStride;
+ int srcOffset = 0;
+
+ for (int i = 0; i < h; i++) {
+ int pixelOffset = lineOffset;
+ for (int j = 0; j < w; j++) {
+ for (int k=0; k < numBands; k++) {
+ data.setElem(bankIndices[k], pixelOffset + bandOffsets[k],
+ iArray[srcOffset++]);
+ }
+ pixelOffset += pixelStride;
+ }
+ lineOffset += scanlineStride;
+ }
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the <code>DataBuffer</code> using an int for input.
+ * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
+ * coordinates are not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b the band to set
+ * @param s the input sample as an int
+ * @param data the DataBuffer containing the image data
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public void setSample(int x, int y, int b, int s,
+ DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ data.setElem(bankIndices[b],
+ y*scanlineStride + x*pixelStride + bandOffsets[b], s);
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the <code>DataBuffer</code> using a float for input.
+ * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
+ * the coordinates are not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to set
+ * @param s The input sample as a float
+ * @param data The DataBuffer containing the image data
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public void setSample(int x, int y, int b,
+ float s ,
+ DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ data.setElemFloat(bankIndices[b],
+ y*scanlineStride + x*pixelStride + bandOffsets[b],
+ s);
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the <code>DataBuffer</code> using a double for input.
+ * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if
+ * the coordinates are not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to set
+ * @param s The input sample as a double
+ * @param data The DataBuffer containing the image data
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public void setSample(int x, int y, int b,
+ double s,
+ DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ data.setElemDouble(bankIndices[b],
+ y*scanlineStride + x*pixelStride + bandOffsets[b],
+ s);
+ }
+
+ /**
+ * Sets the samples in the specified band for the specified rectangle
+ * of pixels from an int array containing one sample per data array element.
+ * An <code>ArrayIndexOutOfBoundsException</code> might be thrown if the
+ * coordinates are not in bounds.
+ * @param x The X coordinate of the upper left pixel location
+ * @param y The Y coordinate of the upper left pixel location
+ * @param w The width of the pixel rectangle
+ * @param h The height of the pixel rectangle
+ * @param b The band to set
+ * @param iArray The input samples in an int array
+ * @param data The DataBuffer containing the image data
+ * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ int iArray[], DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b];
+ int srcOffset = 0;
+
+ for (int i = 0; i < h; i++) {
+ int sampleOffset = lineOffset;
+ for (int j = 0; j < w; j++) {
+ data.setElem(bankIndices[b], sampleOffset, iArray[srcOffset++]);
+ sampleOffset += pixelStride;
+ }
+ lineOffset += scanlineStride;
+ }
+ }
+
+ public boolean equals(Object o) {
+ if ((o == null) || !(o instanceof ComponentSampleModel)) {
+ return false;
+ }
+
+ ComponentSampleModel that = (ComponentSampleModel)o;
+ return this.width == that.width &&
+ this.height == that.height &&
+ this.numBands == that.numBands &&
+ this.dataType == that.dataType &&
+ Arrays.equals(this.bandOffsets, that.bandOffsets) &&
+ Arrays.equals(this.bankIndices, that.bankIndices) &&
+ this.numBands == that.numBands &&
+ this.numBanks == that.numBanks &&
+ this.scanlineStride == that.scanlineStride &&
+ this.pixelStride == that.pixelStride;
+ }
+
+ // If we implement equals() we must also implement hashCode
+ public int hashCode() {
+ int hash = 0;
+ hash = width;
+ hash <<= 8;
+ hash ^= height;
+ hash <<= 8;
+ hash ^= numBands;
+ hash <<= 8;
+ hash ^= dataType;
+ hash <<= 8;
+ for (int i = 0; i < bandOffsets.length; i++) {
+ hash ^= bandOffsets[i];
+ hash <<= 8;
+ }
+ for (int i = 0; i < bankIndices.length; i++) {
+ hash ^= bankIndices[i];
+ hash <<= 8;
+ }
+ hash ^= numBands;
+ hash <<= 8;
+ hash ^= numBanks;
+ hash <<= 8;
+ hash ^= scanlineStride;
+ hash <<= 8;
+ hash ^= pixelStride;
+ return hash;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/DataBuffer.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,535 @@
+/*
+ * Portions Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+
+import sun.java2d.StateTrackable.State;
+import static sun.java2d.StateTrackable.State.*;
+import sun.java2d.StateTrackableDelegate;
+
+import sun.awt.image.SunWritableRaster;
+
+/**
+ * This class exists to wrap one or more data arrays. Each data array in
+ * the DataBuffer is referred to as a bank. Accessor methods for getting
+ * and setting elements of the DataBuffer's banks exist with and without
+ * a bank specifier. The methods without a bank specifier use the default 0th
+ * bank. The DataBuffer can optionally take an offset per bank, so that
+ * data in an existing array can be used even if the interesting data
+ * doesn't start at array location zero. Getting or setting the 0th
+ * element of a bank, uses the (0+offset)th element of the array. The
+ * size field specifies how much of the data array is available for
+ * use. Size + offset for a given bank should never be greater
+ * than the length of the associated data array. The data type of
+ * a data buffer indicates the type of the data array(s) and may also
+ * indicate additional semantics, e.g. storing unsigned 8-bit data
+ * in elements of a byte array. The data type may be TYPE_UNDEFINED
+ * or one of the types defined below. Other types may be added in
+ * the future. Generally, an object of class DataBuffer will be cast down
+ * to one of its data type specific subclasses to access data type specific
+ * methods for improved performance. Currently, the Java 2D(tm) API
+ * image classes use TYPE_BYTE, TYPE_USHORT, TYPE_INT, TYPE_SHORT,
+ * TYPE_FLOAT, and TYPE_DOUBLE DataBuffers to store image data.
+ * @see java.awt.image.Raster
+ * @see java.awt.image.SampleModel
+ */
+public abstract class DataBuffer {
+
+ /** Tag for unsigned byte data. */
+ public static final int TYPE_BYTE = 0;
+
+ /** Tag for unsigned short data. */
+ public static final int TYPE_USHORT = 1;
+
+ /** Tag for signed short data. Placeholder for future use. */
+ public static final int TYPE_SHORT = 2;
+
+ /** Tag for int data. */
+ public static final int TYPE_INT = 3;
+
+ /** Tag for float data. Placeholder for future use. */
+ public static final int TYPE_FLOAT = 4;
+
+ /** Tag for double data. Placeholder for future use. */
+ public static final int TYPE_DOUBLE = 5;
+
+ /** Tag for undefined data. */
+ public static final int TYPE_UNDEFINED = 32;
+
+ /** The data type of this DataBuffer. */
+ protected int dataType;
+
+ /** The number of banks in this DataBuffer. */
+ protected int banks;
+
+ /** Offset into default (first) bank from which to get the first element. */
+ protected int offset;
+
+ /** Usable size of all banks. */
+ protected int size;
+
+ /** Offsets into all banks. */
+ protected int offsets[];
+
+ /* The current StateTrackable state. */
+ StateTrackableDelegate theTrackable;
+
+ /** Size of the data types indexed by DataType tags defined above. */
+ private static final int dataTypeSize[] = {8,16,16,32,32,64};
+
+ /** Returns the size (in bits) of the data type, given a datatype tag.
+ * @param type the value of one of the defined datatype tags
+ * @return the size of the data type
+ * @throws IllegalArgumentException if <code>type</code> is less than
+ * zero or greater than {@link #TYPE_DOUBLE}
+ */
+ public static int getDataTypeSize(int type) {
+ if (type < TYPE_BYTE || type > TYPE_DOUBLE) {
+ throw new IllegalArgumentException("Unknown data type "+type);
+ }
+ return dataTypeSize[type];
+ }
+
+ /**
+ * Constructs a DataBuffer containing one bank of the specified
+ * data type and size.
+ *
+ * @param dataType the data type of this <code>DataBuffer</code>
+ * @param size the size of the banks
+ */
+ protected DataBuffer(int dataType, int size) {
+ this(UNTRACKABLE, dataType, size);
+ }
+
+ /**
+ * Constructs a DataBuffer containing one bank of the specified
+ * data type and size with the indicated initial {@link State State}.
+ *
+ * @param initialState the initial {@link State State} state of the data
+ * @param dataType the data type of this <code>DataBuffer</code>
+ * @param size the size of the banks
+ * @since 1.7
+ */
+ DataBuffer(State initialState,
+ int dataType, int size)
+ {
+ this.theTrackable = StateTrackableDelegate.createInstance(initialState);
+ this.dataType = dataType;
+ this.banks = 1;
+ this.size = size;
+ this.offset = 0;
+ this.offsets = new int[1]; // init to 0 by new
+ }
+
+ /**
+ * Constructs a DataBuffer containing the specified number of
+ * banks. Each bank has the specified size and an offset of 0.
+ *
+ * @param dataType the data type of this <code>DataBuffer</code>
+ * @param size the size of the banks
+ * @param numBanks the number of banks in this
+ * <code>DataBuffer</code>
+ */
+ protected DataBuffer(int dataType, int size, int numBanks) {
+ this(UNTRACKABLE, dataType, size, numBanks);
+ }
+
+ /**
+ * Constructs a DataBuffer containing the specified number of
+ * banks with the indicated initial {@link State State}.
+ * Each bank has the specified size and an offset of 0.
+ *
+ * @param initialState the initial {@link State State} state of the data
+ * @param dataType the data type of this <code>DataBuffer</code>
+ * @param size the size of the banks
+ * @param numBanks the number of banks in this
+ * <code>DataBuffer</code>
+ * @since 1.7
+ */
+ DataBuffer(State initialState,
+ int dataType, int size, int numBanks)
+ {
+ this.theTrackable = StateTrackableDelegate.createInstance(initialState);
+ this.dataType = dataType;
+ this.banks = numBanks;
+ this.size = size;
+ this.offset = 0;
+ this.offsets = new int[banks]; // init to 0 by new
+ }
+
+ /**
+ * Constructs a DataBuffer that contains the specified number
+ * of banks. Each bank has the specified datatype, size and offset.
+ *
+ * @param dataType the data type of this <code>DataBuffer</code>
+ * @param size the size of the banks
+ * @param numBanks the number of banks in this
+ * <code>DataBuffer</code>
+ * @param offset the offset for each bank
+ */
+ protected DataBuffer(int dataType, int size, int numBanks, int offset) {
+ this(UNTRACKABLE, dataType, size, numBanks, offset);
+ }
+
+ /**
+ * Constructs a DataBuffer that contains the specified number
+ * of banks with the indicated initial {@link State State}.
+ * Each bank has the specified datatype, size and offset.
+ *
+ * @param initialState the initial {@link State State} state of the data
+ * @param dataType the data type of this <code>DataBuffer</code>
+ * @param size the size of the banks
+ * @param numBanks the number of banks in this
+ * <code>DataBuffer</code>
+ * @param offset the offset for each bank
+ * @since 1.7
+ */
+ DataBuffer(State initialState,
+ int dataType, int size, int numBanks, int offset)
+ {
+ this.theTrackable = StateTrackableDelegate.createInstance(initialState);
+ this.dataType = dataType;
+ this.banks = numBanks;
+ this.size = size;
+ this.offset = offset;
+ this.offsets = new int[numBanks];
+ for (int i = 0; i < numBanks; i++) {
+ this.offsets[i] = offset;
+ }
+ }
+
+ /**
+ * Constructs a DataBuffer which contains the specified number
+ * of banks. Each bank has the specified datatype and size. The
+ * offset for each bank is specified by its respective entry in
+ * the offsets array.
+ *
+ * @param dataType the data type of this <code>DataBuffer</code>
+ * @param size the size of the banks
+ * @param numBanks the number of banks in this
+ * <code>DataBuffer</code>
+ * @param offsets an array containing an offset for each bank.
+ * @throws ArrayIndexOutOfBoundsException if <code>numBanks</code>
+ * does not equal the length of <code>offsets</code>
+ */
+ protected DataBuffer(int dataType, int size, int numBanks, int offsets[]) {
+ this(UNTRACKABLE, dataType, size, numBanks, offsets);
+ }
+
+ /**
+ * Constructs a DataBuffer which contains the specified number
+ * of banks with the indicated initial {@link State State}.
+ * Each bank has the specified datatype and size. The
+ * offset for each bank is specified by its respective entry in
+ * the offsets array.
+ *
+ * @param initialState the initial {@link State State} state of the data
+ * @param dataType the data type of this <code>DataBuffer</code>
+ * @param size the size of the banks
+ * @param numBanks the number of banks in this
+ * <code>DataBuffer</code>
+ * @param offsets an array containing an offset for each bank.
+ * @throws ArrayIndexOutOfBoundsException if <code>numBanks</code>
+ * does not equal the length of <code>offsets</code>
+ * @since 1.7
+ */
+ DataBuffer(State initialState,
+ int dataType, int size, int numBanks, int offsets[])
+ {
+ if (numBanks != offsets.length) {
+ throw new ArrayIndexOutOfBoundsException("Number of banks" +
+ " does not match number of bank offsets");
+ }
+ this.theTrackable = StateTrackableDelegate.createInstance(initialState);
+ this.dataType = dataType;
+ this.banks = numBanks;
+ this.size = size;
+ this.offset = offsets[0];
+ this.offsets = (int[])offsets.clone();
+ }
+
+ /** Returns the data type of this DataBuffer.
+ * @return the data type of this <code>DataBuffer</code>.
+ */
+ public int getDataType() {
+ return dataType;
+ }
+
+ /** Returns the size (in array elements) of all banks.
+ * @return the size of all banks.
+ */
+ public int getSize() {
+ return size;
+ }
+
+ /** Returns the offset of the default bank in array elements.
+ * @return the offset of the default bank.
+ */
+ public int getOffset() {
+ return offset;
+ }
+
+ /** Returns the offsets (in array elements) of all the banks.
+ * @return the offsets of all banks.
+ */
+ public int[] getOffsets() {
+ return (int[])offsets.clone();
+ }
+
+ /** Returns the number of banks in this DataBuffer.
+ * @return the number of banks.
+ */
+ public int getNumBanks() {
+ return banks;
+ }
+
+ /**
+ * Returns the requested data array element from the first (default) bank
+ * as an integer.
+ * @param i the index of the requested data array element
+ * @return the data array element at the specified index.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ public int getElem(int i) {
+ return getElem(0,i);
+ }
+
+ /**
+ * Returns the requested data array element from the specified bank
+ * as an integer.
+ * @param bank the specified bank
+ * @param i the index of the requested data array element
+ * @return the data array element at the specified index from the
+ * specified bank at the specified index.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ public abstract int getElem(int bank, int i);
+
+ /**
+ * Sets the requested data array element in the first (default) bank
+ * from the given integer.
+ * @param i the specified index into the data array
+ * @param val the data to set the element at the specified index in
+ * the data array
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ public void setElem(int i, int val) {
+ setElem(0,i,val);
+ }
+
+ /**
+ * Sets the requested data array element in the specified bank
+ * from the given integer.
+ * @param bank the specified bank
+ * @param i the specified index into the data array
+ * @param val the data to set the element in the specified bank
+ * at the specified index in the data array
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ public abstract void setElem(int bank, int i, int val);
+
+ /**
+ * Returns the requested data array element from the first (default) bank
+ * as a float. The implementation in this class is to cast getElem(i)
+ * to a float. Subclasses may override this method if another
+ * implementation is needed.
+ * @param i the index of the requested data array element
+ * @return a float value representing the data array element at the
+ * specified index.
+ * @see #setElemFloat(int, float)
+ * @see #setElemFloat(int, int, float)
+ */
+ public float getElemFloat(int i) {
+ return (float)getElem(i);
+ }
+
+ /**
+ * Returns the requested data array element from the specified bank
+ * as a float. The implementation in this class is to cast
+ * {@link #getElem(int, int)}
+ * to a float. Subclasses can override this method if another
+ * implementation is needed.
+ * @param bank the specified bank
+ * @param i the index of the requested data array element
+ * @return a float value representing the data array element from the
+ * specified bank at the specified index.
+ * @see #setElemFloat(int, float)
+ * @see #setElemFloat(int, int, float)
+ */
+ public float getElemFloat(int bank, int i) {
+ return (float)getElem(bank,i);
+ }
+
+ /**
+ * Sets the requested data array element in the first (default) bank
+ * from the given float. The implementation in this class is to cast
+ * val to an int and call {@link #setElem(int, int)}. Subclasses
+ * can override this method if another implementation is needed.
+ * @param i the specified index
+ * @param val the value to set the element at the specified index in
+ * the data array
+ * @see #getElemFloat(int)
+ * @see #getElemFloat(int, int)
+ */
+ public void setElemFloat(int i, float val) {
+ setElem(i,(int)val);
+ }
+
+ /**
+ * Sets the requested data array element in the specified bank
+ * from the given float. The implementation in this class is to cast
+ * val to an int and call {@link #setElem(int, int)}. Subclasses can
+ * override this method if another implementation is needed.
+ * @param bank the specified bank
+ * @param i the specified index
+ * @param val the value to set the element in the specified bank at
+ * the specified index in the data array
+ * @see #getElemFloat(int)
+ * @see #getElemFloat(int, int)
+ */
+ public void setElemFloat(int bank, int i, float val) {
+ setElem(bank,i,(int)val);
+ }
+
+ /**
+ * Returns the requested data array element from the first (default) bank
+ * as a double. The implementation in this class is to cast
+ * {@link #getElem(int)}
+ * to a double. Subclasses can override this method if another
+ * implementation is needed.
+ * @param i the specified index
+ * @return a double value representing the element at the specified
+ * index in the data array.
+ * @see #setElemDouble(int, double)
+ * @see #setElemDouble(int, int, double)
+ */
+ public double getElemDouble(int i) {
+ return (double)getElem(i);
+ }
+
+ /**
+ * Returns the requested data array element from the specified bank as
+ * a double. The implementation in this class is to cast getElem(bank, i)
+ * to a double. Subclasses may override this method if another
+ * implementation is needed.
+ * @param bank the specified bank
+ * @param i the specified index
+ * @return a double value representing the element from the specified
+ * bank at the specified index in the data array.
+ * @see #setElemDouble(int, double)
+ * @see #setElemDouble(int, int, double)
+ */
+ public double getElemDouble(int bank, int i) {
+ return (double)getElem(bank,i);
+ }
+
+ /**
+ * Sets the requested data array element in the first (default) bank
+ * from the given double. The implementation in this class is to cast
+ * val to an int and call {@link #setElem(int, int)}. Subclasses can
+ * override this method if another implementation is needed.
+ * @param i the specified index
+ * @param val the value to set the element at the specified index
+ * in the data array
+ * @see #getElemDouble(int)
+ * @see #getElemDouble(int, int)
+ */
+ public void setElemDouble(int i, double val) {
+ setElem(i,(int)val);
+ }
+
+ /**
+ * Sets the requested data array element in the specified bank
+ * from the given double. The implementation in this class is to cast
+ * val to an int and call {@link #setElem(int, int)}. Subclasses can
+ * override this method if another implementation is needed.
+ * @param bank the specified bank
+ * @param i the specified index
+ * @param val the value to set the element in the specified bank
+ * at the specified index of the data array
+ * @see #getElemDouble(int)
+ * @see #getElemDouble(int, int)
+ */
+ public void setElemDouble(int bank, int i, double val) {
+ setElem(bank,i,(int)val);
+ }
+
+ static int[] toIntArray(Object obj) {
+ if (obj instanceof int[]) {
+ return (int[])obj;
+ } else if (obj == null) {
+ return null;
+ } else if (obj instanceof short[]) {
+ short sdata[] = (short[])obj;
+ int idata[] = new int[sdata.length];
+ for (int i = 0; i < sdata.length; i++) {
+ idata[i] = (int)sdata[i] & 0xffff;
+ }
+ return idata;
+ } else if (obj instanceof byte[]) {
+ byte bdata[] = (byte[])obj;
+ int idata[] = new int[bdata.length];
+ for (int i = 0; i < bdata.length; i++) {
+ idata[i] = 0xff & (int)bdata[i];
+ }
+ return idata;
+ }
+ return null;
+ }
+
+ static {
+ SunWritableRaster.setDataStealer(new SunWritableRaster.DataStealer() {
+ public byte[] getData(DataBufferByte dbb, int bank) {
+ return dbb.bankdata[bank];
+ }
+
+ public short[] getData(DataBufferUShort dbus, int bank) {
+ return dbus.bankdata[bank];
+ }
+
+ public int[] getData(DataBufferInt dbi, int bank) {
+ return dbi.bankdata[bank];
+ }
+
+ public StateTrackableDelegate getTrackable(DataBuffer db) {
+ return db.theTrackable;
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/DataBufferByte.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,286 @@
+/*
+ * Portions Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+
+import static sun.java2d.StateTrackable.State.*;
+
+/**
+ * This class extends <CODE>DataBuffer</CODE> and stores data internally as bytes.
+ * Values stored in the byte array(s) of this <CODE>DataBuffer</CODE> are treated as
+ * unsigned values.
+ * <p>
+ * <a name="optimizations">
+ * Note that some implementations may function more efficiently
+ * if they can maintain control over how the data for an image is
+ * stored.
+ * For example, optimizations such as caching an image in video
+ * memory require that the implementation track all modifications
+ * to that data.
+ * Other implementations may operate better if they can store the
+ * data in locations other than a Java array.
+ * To maintain optimum compatibility with various optimizations
+ * it is best to avoid constructors and methods which expose the
+ * underlying storage as a Java array, as noted below in the
+ * documentation for those methods.
+ * </a>
+ */
+public final class DataBufferByte extends DataBuffer
+{
+ /** The default data bank. */
+ byte data[];
+
+ /** All data banks */
+ byte bankdata[][];
+
+ /**
+ * Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank and the
+ * specified size.
+ *
+ * @param size The size of the <CODE>DataBuffer</CODE>.
+ */
+ public DataBufferByte(int size) {
+ super(STABLE, TYPE_BYTE, size);
+ data = new byte[size];
+ bankdata = new byte[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs a byte based <CODE>DataBuffer</CODE> with the specified number of
+ * banks all of which are the specified size.
+ *
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ * @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
+ */
+ public DataBufferByte(int size, int numBanks) {
+ super(STABLE, TYPE_BYTE, size, numBanks);
+ bankdata = new byte[numBanks][];
+ for (int i= 0; i < numBanks; i++) {
+ bankdata[i] = new byte[size];
+ }
+ data = bankdata[0];
+ }
+
+ /**
+ * Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank using the
+ * specified array.
+ * Only the first <CODE>size</CODE> elements should be used by accessors of
+ * this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
+ * hold <CODE>size</CODE> elements.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The byte array for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the <CODE>DataBuffer</CODE> bank.
+ */
+ public DataBufferByte(byte dataArray[], int size) {
+ super(UNTRACKABLE, TYPE_BYTE, size);
+ data = dataArray;
+ bankdata = new byte[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs a byte-based <CODE>DataBuffer</CODE> with a single bank using the
+ * specified array, size, and offset. <CODE>dataArray</CODE> must have at least
+ * <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
+ * through <CODE>offset</CODE> + <CODE>size</CODE> - 1
+ * should be used by accessors of this <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The byte array for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the <CODE>DataBuffer</CODE> bank.
+ * @param offset The offset into the <CODE>dataArray</CODE>. <CODE>dataArray</CODE>
+ * must have at least <CODE>offset</CODE> + <CODE>size</CODE> elements.
+ */
+ public DataBufferByte(byte dataArray[], int size, int offset){
+ super(UNTRACKABLE, TYPE_BYTE, size, 1, offset);
+ data = dataArray;
+ bankdata = new byte[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs a byte-based <CODE>DataBuffer</CODE> with the specified arrays.
+ * The number of banks is equal to <CODE>dataArray.length</CODE>.
+ * Only the first <CODE>size</CODE> elements of each array should be used by
+ * accessors of this <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The byte arrays for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ */
+ public DataBufferByte(byte dataArray[][], int size) {
+ super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length);
+ bankdata = (byte[][]) dataArray.clone();
+ data = bankdata[0];
+ }
+
+ /**
+ * Constructs a byte-based <CODE>DataBuffer</CODE> with the specified arrays, size,
+ * and offsets.
+ * The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
+ * be at least as large as <CODE>size</CODE> + the corresponding <CODE>offset</CODE>.
+ * There must be an entry in the <CODE>offset</CODE> array for each <CODE>dataArray</CODE>
+ * entry. For each bank, only elements <CODE>offset</CODE> through
+ * <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be used by accessors of this
+ * <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The byte arrays for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ * @param offsets The offsets into each array.
+ */
+ public DataBufferByte(byte dataArray[][], int size, int offsets[]) {
+ super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length, offsets);
+ bankdata = (byte[][]) dataArray.clone();
+ data = bankdata[0];
+ }
+
+ /**
+ * Returns the default (first) byte data array.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @return The first byte data array.
+ */
+ public byte[] getData() {
+ theTrackable.setUntrackable();
+ return data;
+ }
+
+ /**
+ * Returns the data array for the specified bank.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param bank The bank whose data array you want to get.
+ * @return The data array for the specified bank.
+ */
+ public byte[] getData(int bank) {
+ theTrackable.setUntrackable();
+ return bankdata[bank];
+ }
+
+ /**
+ * Returns the data arrays for all banks.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @return All of the data arrays.
+ */
+ public byte[][] getBankData() {
+ theTrackable.setUntrackable();
+ return (byte[][]) bankdata.clone();
+ }
+
+ /**
+ * Returns the requested data array element from the first (default) bank.
+ *
+ * @param i The data array element you want to get.
+ * @return The requested data array element as an integer.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ public int getElem(int i) {
+ return (int)(data[i+offset]) & 0xff;
+ }
+
+ /**
+ * Returns the requested data array element from the specified bank.
+ *
+ * @param bank The bank from which you want to get a data array element.
+ * @param i The data array element you want to get.
+ * @return The requested data array element as an integer.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ public int getElem(int bank, int i) {
+ return (int)(bankdata[bank][i+offsets[bank]]) & 0xff;
+ }
+
+ /**
+ * Sets the requested data array element in the first (default) bank
+ * to the specified value.
+ *
+ * @param i The data array element you want to set.
+ * @param val The integer value to which you want to set the data array element.
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ public void setElem(int i, int val) {
+ data[i+offset] = (byte)val;
+ theTrackable.markDirty();
+ }
+
+ /**
+ * Sets the requested data array element in the specified bank
+ * from the given integer.
+ * @param bank The bank in which you want to set the data array element.
+ * @param i The data array element you want to set.
+ * @param val The integer value to which you want to set the specified data array element.
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ public void setElem(int bank, int i, int val) {
+ bankdata[bank][i+offsets[bank]] = (byte)val;
+ theTrackable.markDirty();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/DataBufferInt.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,284 @@
+/*
+ * Portions Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+
+import static sun.java2d.StateTrackable.State.*;
+
+/**
+ * This class extends <CODE>DataBuffer</CODE> and stores data internally
+ * as integers.
+ * <p>
+ * <a name="optimizations">
+ * Note that some implementations may function more efficiently
+ * if they can maintain control over how the data for an image is
+ * stored.
+ * For example, optimizations such as caching an image in video
+ * memory require that the implementation track all modifications
+ * to that data.
+ * Other implementations may operate better if they can store the
+ * data in locations other than a Java array.
+ * To maintain optimum compatibility with various optimizations
+ * it is best to avoid constructors and methods which expose the
+ * underlying storage as a Java array as noted below in the
+ * documentation for those methods.
+ * </a>
+ */
+public final class DataBufferInt extends DataBuffer
+{
+ /** The default data bank. */
+ int data[];
+
+ /** All data banks */
+ int bankdata[][];
+
+ /**
+ * Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank
+ * and the specified size.
+ *
+ * @param size The size of the <CODE>DataBuffer</CODE>.
+ */
+ public DataBufferInt(int size) {
+ super(STABLE, TYPE_INT, size);
+ data = new int[size];
+ bankdata = new int[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs an integer-based <CODE>DataBuffer</CODE> with the specified number of
+ * banks, all of which are the specified size.
+ *
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ * @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
+ */
+ public DataBufferInt(int size, int numBanks) {
+ super(STABLE, TYPE_INT, size, numBanks);
+ bankdata = new int[numBanks][];
+ for (int i= 0; i < numBanks; i++) {
+ bankdata[i] = new int[size];
+ }
+ data = bankdata[0];
+ }
+
+ /**
+ * Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank using the
+ * specified array.
+ * Only the first <CODE>size</CODE> elements should be used by accessors of
+ * this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
+ * hold <CODE>size</CODE> elements.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The integer array for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the <CODE>DataBuffer</CODE> bank.
+ */
+ public DataBufferInt(int dataArray[], int size) {
+ super(UNTRACKABLE, TYPE_INT, size);
+ data = dataArray;
+ bankdata = new int[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank using the
+ * specified array, size, and offset. <CODE>dataArray</CODE> must have at least
+ * <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
+ * through <CODE>offset</CODE> + <CODE>size</CODE> - 1
+ * should be used by accessors of this <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The integer array for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the <CODE>DataBuffer</CODE> bank.
+ * @param offset The offset into the <CODE>dataArray</CODE>.
+ */
+ public DataBufferInt(int dataArray[], int size, int offset) {
+ super(UNTRACKABLE, TYPE_INT, size, 1, offset);
+ data = dataArray;
+ bankdata = new int[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs an integer-based <CODE>DataBuffer</CODE> with the specified arrays.
+ * The number of banks will be equal to <CODE>dataArray.length</CODE>.
+ * Only the first <CODE>size</CODE> elements of each array should be used by
+ * accessors of this <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The integer arrays for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ */
+ public DataBufferInt(int dataArray[][], int size) {
+ super(UNTRACKABLE, TYPE_INT, size, dataArray.length);
+ bankdata = (int [][]) dataArray.clone();
+ data = bankdata[0];
+ }
+
+ /**
+ * Constructs an integer-based <CODE>DataBuffer</CODE> with the specified arrays, size,
+ * and offsets.
+ * The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
+ * be at least as large as <CODE>size</CODE> + the corresponding offset. There must
+ * be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
+ * bank, only elements <CODE>offset</CODE> through
+ * <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
+ * used by accessors of this <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The integer arrays for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ * @param offsets The offsets into each array.
+ */
+ public DataBufferInt(int dataArray[][], int size, int offsets[]) {
+ super(UNTRACKABLE, TYPE_INT, size, dataArray.length, offsets);
+ bankdata = (int [][]) dataArray.clone();
+ data = bankdata[0];
+ }
+
+ /**
+ * Returns the default (first) int data array in <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @return The first integer data array.
+ */
+ public int[] getData() {
+ theTrackable.setUntrackable();
+ return data;
+ }
+
+ /**
+ * Returns the data array for the specified bank.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param bank The bank whose data array you want to get.
+ * @return The data array for the specified bank.
+ */
+ public int[] getData(int bank) {
+ theTrackable.setUntrackable();
+ return bankdata[bank];
+ }
+
+ /**
+ * Returns the data arrays for all banks.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @return All of the data arrays.
+ */
+ public int[][] getBankData() {
+ theTrackable.setUntrackable();
+ return (int [][]) bankdata.clone();
+ }
+
+ /**
+ * Returns the requested data array element from the first (default) bank.
+ *
+ * @param i The data array element you want to get.
+ * @return The requested data array element as an integer.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ public int getElem(int i) {
+ return data[i+offset];
+ }
+
+ /**
+ * Returns the requested data array element from the specified bank.
+ *
+ * @param bank The bank from which you want to get a data array element.
+ * @param i The data array element you want to get.
+ * @return The requested data array element as an integer.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ public int getElem(int bank, int i) {
+ return bankdata[bank][i+offsets[bank]];
+ }
+
+ /**
+ * Sets the requested data array element in the first (default) bank
+ * to the specified value.
+ *
+ * @param i The data array element you want to set.
+ * @param val The integer value to which you want to set the data array element.
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ public void setElem(int i, int val) {
+ data[i+offset] = val;
+ theTrackable.markDirty();
+ }
+
+ /**
+ * Sets the requested data array element in the specified bank
+ * to the integer value <CODE>i</CODE>.
+ * @param bank The bank in which you want to set the data array element.
+ * @param i The data array element you want to set.
+ * @param val The integer value to which you want to set the specified data array element.
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ public void setElem(int bank, int i, int val) {
+ bankdata[bank][i+offsets[bank]] = (int)val;
+ theTrackable.markDirty();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/DataBufferShort.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,283 @@
+/*
+ * Portions Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+
+import static sun.java2d.StateTrackable.State.*;
+
+/**
+ * This class extends <CODE>DataBuffer</CODE> and stores data internally as shorts.
+ * <p>
+ * <a name="optimizations">
+ * Note that some implementations may function more efficiently
+ * if they can maintain control over how the data for an image is
+ * stored.
+ * For example, optimizations such as caching an image in video
+ * memory require that the implementation track all modifications
+ * to that data.
+ * Other implementations may operate better if they can store the
+ * data in locations other than a Java array.
+ * To maintain optimum compatibility with various optimizations
+ * it is best to avoid constructors and methods which expose the
+ * underlying storage as a Java array as noted below in the
+ * documentation for those methods.
+ * </a>
+ */
+public final class DataBufferShort extends DataBuffer
+{
+ /** The default data bank. */
+ short data[];
+
+ /** All data banks */
+ short bankdata[][];
+
+ /**
+ * Constructs a short-based <CODE>DataBuffer</CODE> with a single bank and the
+ * specified size.
+ *
+ * @param size The size of the <CODE>DataBuffer</CODE>.
+ */
+ public DataBufferShort(int size) {
+ super(STABLE, TYPE_SHORT,size);
+ data = new short[size];
+ bankdata = new short[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs a short-based <CODE>DataBuffer</CODE> with the specified number of
+ * banks all of which are the specified size.
+ *
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ * @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
+ */
+ public DataBufferShort(int size, int numBanks) {
+ super(STABLE, TYPE_SHORT,size,numBanks);
+ bankdata = new short[numBanks][];
+ for (int i= 0; i < numBanks; i++) {
+ bankdata[i] = new short[size];
+ }
+ data = bankdata[0];
+ }
+
+ /**
+ * Constructs a short-based <CODE>DataBuffer</CODE> with a single bank using the
+ * specified array.
+ * Only the first <CODE>size</CODE> elements should be used by accessors of
+ * this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
+ * hold <CODE>size</CODE> elements.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The short array for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the <CODE>DataBuffer</CODE> bank.
+ */
+ public DataBufferShort(short dataArray[], int size) {
+ super(UNTRACKABLE, TYPE_SHORT, size);
+ data = dataArray;
+ bankdata = new short[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs a short-based <CODE>DataBuffer</CODE> with a single bank using the
+ * specified array, size, and offset. <CODE>dataArray</CODE> must have at least
+ * <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements <CODE>offset</CODE>
+ * through <CODE>offset</CODE> + <CODE>size</CODE> - 1
+ * should be used by accessors of this <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The short array for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the <CODE>DataBuffer</CODE> bank.
+ * @param offset The offset into the <CODE>dataArray</CODE>.
+ */
+ public DataBufferShort(short dataArray[], int size, int offset) {
+ super(UNTRACKABLE, TYPE_SHORT, size, 1, offset);
+ data = dataArray;
+ bankdata = new short[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs a short-based <CODE>DataBuffer</CODE> with the specified arrays.
+ * The number of banks will be equal to <CODE>dataArray.length</CODE>.
+ * Only the first <CODE>size</CODE> elements of each array should be used by
+ * accessors of this <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The short arrays for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ */
+ public DataBufferShort(short dataArray[][], int size) {
+ super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length);
+ bankdata = (short[][]) dataArray.clone();
+ data = bankdata[0];
+ }
+
+ /**
+ * Constructs a short-based <CODE>DataBuffer</CODE> with the specified arrays, size,
+ * and offsets.
+ * The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
+ * be at least as large as <CODE>size</CODE> + the corresponding offset. There must
+ * be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
+ * bank, only elements <CODE>offset</CODE> through
+ * <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
+ * used by accessors of this <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The short arrays for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ * @param offsets The offsets into each array.
+ */
+ public DataBufferShort(short dataArray[][], int size, int offsets[]) {
+ super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length, offsets);
+ bankdata = (short[][]) dataArray.clone();
+ data = bankdata[0];
+ }
+
+ /**
+ * Returns the default (first) byte data array.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @return The first short data array.
+ */
+ public short[] getData() {
+ theTrackable.setUntrackable();
+ return data;
+ }
+
+ /**
+ * Returns the data array for the specified bank.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param bank The bank whose data array you want to get.
+ * @return The data array for the specified bank.
+ */
+ public short[] getData(int bank) {
+ theTrackable.setUntrackable();
+ return bankdata[bank];
+ }
+
+ /**
+ * Returns the data arrays for all banks.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @return All of the data arrays.
+ */
+ public short[][] getBankData() {
+ theTrackable.setUntrackable();
+ return (short[][]) bankdata.clone();
+ }
+
+ /**
+ * Returns the requested data array element from the first (default) bank.
+ *
+ * @param i The data array element you want to get.
+ * @return The requested data array element as an integer.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ public int getElem(int i) {
+ return (int)(data[i+offset]);
+ }
+
+ /**
+ * Returns the requested data array element from the specified bank.
+ *
+ * @param bank The bank from which you want to get a data array element.
+ * @param i The data array element you want to get.
+ * @return The requested data array element as an integer.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ public int getElem(int bank, int i) {
+ return (int)(bankdata[bank][i+offsets[bank]]);
+ }
+
+ /**
+ * Sets the requested data array element in the first (default) bank
+ * to the specified value.
+ *
+ * @param i The data array element you want to set.
+ * @param val The integer value to which you want to set the data array element.
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ public void setElem(int i, int val) {
+ data[i+offset] = (short)val;
+ theTrackable.markDirty();
+ }
+
+ /**
+ * Sets the requested data array element in the specified bank
+ * from the given integer.
+ * @param bank The bank in which you want to set the data array element.
+ * @param i The data array element you want to set.
+ * @param val The integer value to which you want to set the specified data array element.
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ public void setElem(int bank, int i, int val) {
+ bankdata[bank][i+offsets[bank]] = (short)val;
+ theTrackable.markDirty();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/DataBufferUShort.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,318 @@
+/*
+ * Portions Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+
+import static sun.java2d.StateTrackable.State.*;
+
+/**
+ * This class extends <CODE>DataBuffer</CODE> and stores data internally as
+ * shorts. Values stored in the short array(s) of this <CODE>DataBuffer</CODE>
+ * are treated as unsigned values.
+ * <p>
+ * <a name="optimizations">
+ * Note that some implementations may function more efficiently
+ * if they can maintain control over how the data for an image is
+ * stored.
+ * For example, optimizations such as caching an image in video
+ * memory require that the implementation track all modifications
+ * to that data.
+ * Other implementations may operate better if they can store the
+ * data in locations other than a Java array.
+ * To maintain optimum compatibility with various optimizations
+ * it is best to avoid constructors and methods which expose the
+ * underlying storage as a Java array as noted below in the
+ * documentation for those methods.
+ * </a>
+ */
+public final class DataBufferUShort extends DataBuffer
+{
+ /** The default data bank. */
+ short data[];
+
+ /** All data banks */
+ short bankdata[][];
+
+ /**
+ * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank and the
+ * specified size.
+ *
+ * @param size The size of the <CODE>DataBuffer</CODE>.
+ */
+ public DataBufferUShort(int size) {
+ super(STABLE, TYPE_USHORT, size);
+ data = new short[size];
+ bankdata = new short[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with the specified number of
+ * banks, all of which are the specified size.
+ *
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ * @param numBanks The number of banks in the a<CODE>DataBuffer</CODE>.
+ */
+ public DataBufferUShort(int size, int numBanks) {
+ super(STABLE, TYPE_USHORT, size, numBanks);
+ bankdata = new short[numBanks][];
+ for (int i= 0; i < numBanks; i++) {
+ bankdata[i] = new short[size];
+ }
+ data = bankdata[0];
+ }
+
+ /**
+ * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank
+ * using the specified array.
+ * Only the first <CODE>size</CODE> elements should be used by accessors of
+ * this <CODE>DataBuffer</CODE>. <CODE>dataArray</CODE> must be large enough to
+ * hold <CODE>size</CODE> elements.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The unsigned-short array for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the <CODE>DataBuffer</CODE> bank.
+ */
+ public DataBufferUShort(short dataArray[], int size) {
+ super(UNTRACKABLE, TYPE_USHORT, size);
+ if (dataArray == null) {
+ throw new NullPointerException("dataArray is null");
+ }
+ data = dataArray;
+ bankdata = new short[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with a single bank
+ * using the specified array, size, and offset. <CODE>dataArray</CODE> must have at
+ * least <CODE>offset</CODE> + <CODE>size</CODE> elements. Only elements
+ * <CODE>offset</CODE> through <CODE>offset</CODE> + <CODE>size</CODE> - 1 should
+ * be used by accessors of this <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The unsigned-short array for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the <CODE>DataBuffer</CODE> bank.
+ * @param offset The offset into the <CODE>dataArray</CODE>.
+ */
+ public DataBufferUShort(short dataArray[], int size, int offset) {
+ super(UNTRACKABLE, TYPE_USHORT, size, 1, offset);
+ if (dataArray == null) {
+ throw new NullPointerException("dataArray is null");
+ }
+ if ((size+offset) > dataArray.length) {
+ throw new IllegalArgumentException("Length of dataArray is less "+
+ " than size+offset.");
+ }
+ data = dataArray;
+ bankdata = new short[1][];
+ bankdata[0] = data;
+ }
+
+ /**
+ * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with the specified arrays.
+ * The number of banks will be equal to <CODE>dataArray.length</CODE>.
+ * Only the first <CODE>size</CODE> elements of each array should be used by
+ * accessors of this <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The unsigned-short arrays for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ */
+ public DataBufferUShort(short dataArray[][], int size) {
+ super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length);
+ if (dataArray == null) {
+ throw new NullPointerException("dataArray is null");
+ }
+ for (int i=0; i < dataArray.length; i++) {
+ if (dataArray[i] == null) {
+ throw new NullPointerException("dataArray["+i+"] is null");
+ }
+ }
+
+ bankdata = (short[][]) dataArray.clone();
+ data = bankdata[0];
+ }
+
+ /**
+ * Constructs an unsigned-short based <CODE>DataBuffer</CODE> with specified arrays,
+ * size, and offsets.
+ * The number of banks is equal to <CODE>dataArray.length</CODE>. Each array must
+ * be at least as large as <CODE>size</CODE> + the corresponding offset. There must
+ * be an entry in the offset array for each <CODE>dataArray</CODE> entry. For each
+ * bank, only elements <CODE>offset</CODE> through
+ * <CODE>offset</CODE> + <CODE>size</CODE> - 1 should be
+ * used by accessors of this <CODE>DataBuffer</CODE>.
+ * <p>
+ * Note that {@code DataBuffer} objects created by this constructor
+ * may be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param dataArray The unsigned-short arrays for the <CODE>DataBuffer</CODE>.
+ * @param size The size of the banks in the <CODE>DataBuffer</CODE>.
+ * @param offsets The offsets into each array.
+ */
+ public DataBufferUShort(short dataArray[][], int size, int offsets[]) {
+ super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length, offsets);
+ if (dataArray == null) {
+ throw new NullPointerException("dataArray is null");
+ }
+ for (int i=0; i < dataArray.length; i++) {
+ if (dataArray[i] == null) {
+ throw new NullPointerException("dataArray["+i+"] is null");
+ }
+ if ((size+offsets[i]) > dataArray[i].length) {
+ throw new IllegalArgumentException("Length of dataArray["+i+
+ "] is less than size+"+
+ "offsets["+i+"].");
+ }
+
+ }
+ bankdata = (short[][]) dataArray.clone();
+ data = bankdata[0];
+ }
+
+ /**
+ * Returns the default (first) unsigned-short data array.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @return The first unsigned-short data array.
+ */
+ public short[] getData() {
+ theTrackable.setUntrackable();
+ return data;
+ }
+
+ /**
+ * Returns the data array for the specified bank.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @param bank The bank whose data array you want to get.
+ * @return The data array for the specified bank.
+ */
+ public short[] getData(int bank) {
+ theTrackable.setUntrackable();
+ return bankdata[bank];
+ }
+
+ /**
+ * Returns the data arrays for all banks.
+ * <p>
+ * Note that calling this method may cause this {@code DataBuffer}
+ * object to be incompatible with <a href="#optimizations">performance
+ * optimizations</a> used by some implementations (such as caching
+ * an associated image in video memory).
+ *
+ * @return All of the data arrays.
+ */
+ public short[][] getBankData() {
+ theTrackable.setUntrackable();
+ return (short[][]) bankdata.clone();
+ }
+
+ /**
+ * Returns the requested data array element from the first (default) bank.
+ *
+ * @param i The data array element you want to get.
+ * @return The requested data array element as an integer.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ public int getElem(int i) {
+ return (int)(data[i+offset]&0xffff);
+ }
+
+ /**
+ * Returns the requested data array element from the specified bank.
+ *
+ * @param bank The bank from which you want to get a data array element.
+ * @param i The data array element you want to get.
+ * @return The requested data array element as an integer.
+ * @see #setElem(int, int)
+ * @see #setElem(int, int, int)
+ */
+ public int getElem(int bank, int i) {
+ return (int)(bankdata[bank][i+offsets[bank]]&0xffff);
+ }
+
+ /**
+ * Sets the requested data array element in the first (default) bank
+ * to the specified value.
+ *
+ * @param i The data array element you want to set.
+ * @param val The integer value to which you want to set the data array element.
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ public void setElem(int i, int val) {
+ data[i+offset] = (short)(val&0xffff);
+ theTrackable.markDirty();
+ }
+
+ /**
+ * Sets the requested data array element in the specified bank
+ * from the given integer.
+ * @param bank The bank in which you want to set the data array element.
+ * @param i The data array element you want to set.
+ * @param val The integer value to which you want to set the specified data array element.
+ * @see #getElem(int)
+ * @see #getElem(int, int)
+ */
+ public void setElem(int bank, int i, int val) {
+ bankdata[bank][i+offsets[bank]] = (short)(val&0xffff);
+ theTrackable.markDirty();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/MultiPixelPackedSampleModel.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,699 @@
+/*
+ * Portions Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+
+/**
+ * The <code>MultiPixelPackedSampleModel</code> class represents
+ * one-banded images and can pack multiple one-sample
+ * pixels into one data element. Pixels are not allowed to span data elements.
+ * The data type can be DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * or DataBuffer.TYPE_INT. Each pixel must be a power of 2 number of bits
+ * and a power of 2 number of pixels must fit exactly in one data element.
+ * Pixel bit stride is equal to the number of bits per pixel. Scanline
+ * stride is in data elements and the last several data elements might be
+ * padded with unused pixels. Data bit offset is the offset in bits from
+ * the beginning of the {@link DataBuffer} to the first pixel and must be
+ * a multiple of pixel bit stride.
+ * <p>
+ * The following code illustrates extracting the bits for pixel
+ * <code>x, y</code> from <code>DataBuffer</code> <code>data</code>
+ * and storing the pixel data in data elements of type
+ * <code>dataType</code>:
+ * <pre>
+ * int dataElementSize = DataBuffer.getDataTypeSize(dataType);
+ * int bitnum = dataBitOffset + x*pixelBitStride;
+ * int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
+ * int shift = dataElementSize - (bitnum & (dataElementSize-1))
+ * - pixelBitStride;
+ * int pixel = (element >> shift) & ((1 << pixelBitStride) - 1);
+ * </pre>
+ */
+
+public class MultiPixelPackedSampleModel extends SampleModel
+{
+ /** The number of bits from one pixel to the next. */
+ int pixelBitStride;
+
+ /** Bitmask that extracts the rightmost pixel of a data element. */
+ int bitMask;
+
+ /**
+ * The number of pixels that fit in a data element. Also used
+ * as the number of bits per pixel.
+ */
+ int pixelsPerDataElement;
+
+ /** The size of a data element in bits. */
+ int dataElementSize;
+
+ /** The bit offset into the data array where the first pixel begins.
+ */
+ int dataBitOffset;
+
+ /** ScanlineStride of the data buffer described in data array elements. */
+ int scanlineStride;
+
+ /**
+ * Constructs a <code>MultiPixelPackedSampleModel</code> with the
+ * specified data type, width, height and number of bits per pixel.
+ * @param dataType the data type for storing samples
+ * @param w the width, in pixels, of the region of
+ * image data described
+ * @param h the height, in pixels, of the region of
+ * image data described
+ * @param numberOfBits the number of bits per pixel
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * either <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>, or
+ * <code>DataBuffer.TYPE_INT</code>
+ */
+ public MultiPixelPackedSampleModel(int dataType,
+ int w,
+ int h,
+ int numberOfBits) {
+ this(dataType,w,h,
+ numberOfBits,
+ (w*numberOfBits+DataBuffer.getDataTypeSize(dataType)-1)/
+ DataBuffer.getDataTypeSize(dataType),
+ 0);
+ if (dataType != DataBuffer.TYPE_BYTE &&
+ dataType != DataBuffer.TYPE_USHORT &&
+ dataType != DataBuffer.TYPE_INT) {
+ throw new IllegalArgumentException("Unsupported data type "+
+ dataType);
+ }
+ }
+
+ /**
+ * Constructs a <code>MultiPixelPackedSampleModel</code> with
+ * specified data type, width, height, number of bits per pixel,
+ * scanline stride and data bit offset.
+ * @param dataType the data type for storing samples
+ * @param w the width, in pixels, of the region of
+ * image data described
+ * @param h the height, in pixels, of the region of
+ * image data described
+ * @param numberOfBits the number of bits per pixel
+ * @param scanlineStride the line stride of the image data
+ * @param dataBitOffset the data bit offset for the region of image
+ * data described
+ * @exception RasterFormatException if the number of bits per pixel
+ * is not a power of 2 or if a power of 2 number of
+ * pixels do not fit in one data element.
+ * @throws IllegalArgumentException if <code>w</code> or
+ * <code>h</code> is not greater than 0
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * either <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>, or
+ * <code>DataBuffer.TYPE_INT</code>
+ */
+ public MultiPixelPackedSampleModel(int dataType, int w, int h,
+ int numberOfBits,
+ int scanlineStride,
+ int dataBitOffset) {
+ super(dataType, w, h, 1);
+ if (dataType != DataBuffer.TYPE_BYTE &&
+ dataType != DataBuffer.TYPE_USHORT &&
+ dataType != DataBuffer.TYPE_INT) {
+ throw new IllegalArgumentException("Unsupported data type "+
+ dataType);
+ }
+ this.dataType = dataType;
+ this.pixelBitStride = numberOfBits;
+ this.scanlineStride = scanlineStride;
+ this.dataBitOffset = dataBitOffset;
+ this.dataElementSize = DataBuffer.getDataTypeSize(dataType);
+ this.pixelsPerDataElement = dataElementSize/numberOfBits;
+ if (pixelsPerDataElement*numberOfBits != dataElementSize) {
+ throw new RasterFormatException("MultiPixelPackedSampleModel " +
+ "does not allow pixels to " +
+ "span data element boundaries");
+ }
+ this.bitMask = (1 << numberOfBits) - 1;
+ }
+
+
+ /**
+ * Creates a new <code>MultiPixelPackedSampleModel</code> with the
+ * specified width and height. The new
+ * <code>MultiPixelPackedSampleModel</code> has the
+ * same storage data type and number of bits per pixel as this
+ * <code>MultiPixelPackedSampleModel</code>.
+ * @param w the specified width
+ * @param h the specified height
+ * @return a {@link SampleModel} with the specified width and height
+ * and with the same storage data type and number of bits per pixel
+ * as this <code>MultiPixelPackedSampleModel</code>.
+ * @throws IllegalArgumentException if <code>w</code> or
+ * <code>h</code> is not greater than 0
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ SampleModel sampleModel =
+ new MultiPixelPackedSampleModel(dataType, w, h, pixelBitStride);
+ return sampleModel;
+ }
+
+ /**
+ * Creates a <code>DataBuffer</code> that corresponds to this
+ * <code>MultiPixelPackedSampleModel</code>. The
+ * <code>DataBuffer</code> object's data type and size
+ * is consistent with this <code>MultiPixelPackedSampleModel</code>.
+ * The <code>DataBuffer</code> has a single bank.
+ * @return a <code>DataBuffer</code> with the same data type and
+ * size as this <code>MultiPixelPackedSampleModel</code>.
+ */
+ public DataBuffer createDataBuffer() {
+ DataBuffer dataBuffer = null;
+
+ int size = (int)scanlineStride*height;
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ dataBuffer = new DataBufferByte(size+(dataBitOffset+7)/8);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ dataBuffer = new DataBufferUShort(size+(dataBitOffset+15)/16);
+ break;
+ case DataBuffer.TYPE_INT:
+ dataBuffer = new DataBufferInt(size+(dataBitOffset+31)/32);
+ break;
+ }
+ return dataBuffer;
+ }
+
+ /**
+ * Returns the number of data elements needed to transfer one pixel
+ * via the {@link #getDataElements} and {@link #setDataElements}
+ * methods. For a <code>MultiPixelPackedSampleModel</code>, this is
+ * one.
+ * @return the number of data elements.
+ */
+ public int getNumDataElements() {
+ return 1;
+ }
+
+ /**
+ * Returns the number of bits per sample for all bands.
+ * @return the number of bits per sample.
+ */
+ public int[] getSampleSize() {
+ int sampleSize[] = {pixelBitStride};
+ return sampleSize;
+ }
+
+ /**
+ * Returns the number of bits per sample for the specified band.
+ * @param band the specified band
+ * @return the number of bits per sample for the specified band.
+ */
+ public int getSampleSize(int band) {
+ return pixelBitStride;
+ }
+
+ /**
+ * Returns the offset of pixel (x, y) in data array elements.
+ * @param x the X coordinate of the specified pixel
+ * @param y the Y coordinate of the specified pixel
+ * @return the offset of the specified pixel.
+ */
+ public int getOffset(int x, int y) {
+ int offset = y * scanlineStride;
+ offset += (x*pixelBitStride+dataBitOffset)/dataElementSize;
+ return offset;
+ }
+
+ /**
+ * Returns the offset, in bits, into the data element in which it is
+ * stored for the <code>x</code>th pixel of a scanline.
+ * This offset is the same for all scanlines.
+ * @param x the specified pixel
+ * @return the bit offset of the specified pixel.
+ */
+ public int getBitOffset(int x){
+ return (x*pixelBitStride+dataBitOffset)%dataElementSize;
+ }
+
+ /**
+ * Returns the scanline stride.
+ * @return the scanline stride of this
+ * <code>MultiPixelPackedSampleModel</code>.
+ */
+ public int getScanlineStride() {
+ return scanlineStride;
+ }
+
+ /**
+ * Returns the pixel bit stride in bits. This value is the same as
+ * the number of bits per pixel.
+ * @return the <code>pixelBitStride</code> of this
+ * <code>MultiPixelPackedSampleModel</code>.
+ */
+ public int getPixelBitStride() {
+ return pixelBitStride;
+ }
+
+ /**
+ * Returns the data bit offset in bits.
+ * @return the <code>dataBitOffset</code> of this
+ * <code>MultiPixelPackedSampleModel</code>.
+ */
+ public int getDataBitOffset() {
+ return dataBitOffset;
+ }
+
+ /**
+ * Returns the TransferType used to transfer pixels by way of the
+ * <code>getDataElements</code> and <code>setDataElements</code>
+ * methods. The TransferType might or might not be the same as the
+ * storage DataType. The TransferType is one of
+ * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * or DataBuffer.TYPE_INT.
+ * @return the transfertype.
+ */
+ public int getTransferType() {
+ if (pixelBitStride > 16)
+ return DataBuffer.TYPE_INT;
+ else if (pixelBitStride > 8)
+ return DataBuffer.TYPE_USHORT;
+ else
+ return DataBuffer.TYPE_BYTE;
+ }
+
+ /**
+ * Creates a new <code>MultiPixelPackedSampleModel</code> with a
+ * subset of the bands of this
+ * <code>MultiPixelPackedSampleModel</code>. Since a
+ * <code>MultiPixelPackedSampleModel</code> only has one band, the
+ * bands argument must have a length of one and indicate the zeroth
+ * band.
+ * @param bands the specified bands
+ * @return a new <code>SampleModel</code> with a subset of bands of
+ * this <code>MultiPixelPackedSampleModel</code>.
+ * @exception RasterFormatException if the number of bands requested
+ * is not one.
+ * @throws IllegalArgumentException if <code>w</code> or
+ * <code>h</code> is not greater than 0
+ */
+ public SampleModel createSubsetSampleModel(int bands[]) {
+ if (bands != null) {
+ if (bands.length != 1)
+ throw new RasterFormatException("MultiPixelPackedSampleModel has "
+ + "only one band.");
+ }
+ SampleModel sm = createCompatibleSampleModel(width, height);
+ return sm;
+ }
+
+ /**
+ * Returns as <code>int</code> the sample in a specified band for the
+ * pixel located at (x, y). An
+ * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
+ * coordinates are not in bounds.
+ * @param x the X coordinate of the specified pixel
+ * @param y the Y coordinate of the specified pixel
+ * @param b the band to return, which is assumed to be 0
+ * @param data the <code>DataBuffer</code> containing the image
+ * data
+ * @return the specified band containing the sample of the specified
+ * pixel.
+ * @exception ArrayIndexOutOfBoundException if the specified
+ * coordinates are not in bounds.
+ * @see #setSample(int, int, int, int, DataBuffer)
+ */
+ public int getSample(int x, int y, int b, DataBuffer data) {
+ // 'b' must be 0
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height) ||
+ (b != 0)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int bitnum = dataBitOffset + x*pixelBitStride;
+ int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
+ int shift = dataElementSize - (bitnum & (dataElementSize-1))
+ - pixelBitStride;
+ return (element >> shift) & bitMask;
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at
+ * (x, y) in the <code>DataBuffer</code> using an
+ * <code>int</code> for input.
+ * An <code>ArrayIndexOutOfBoundsException</code> is thrown if the
+ * coordinates are not in bounds.
+ * @param x the X coordinate of the specified pixel
+ * @param y the Y coordinate of the specified pixel
+ * @param b the band to return, which is assumed to be 0
+ * @param s the input sample as an <code>int</code>
+ * @param data the <code>DataBuffer</code> where image data is stored
+ * @exception ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds.
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public void setSample(int x, int y, int b, int s,
+ DataBuffer data) {
+ // 'b' must be 0
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height) ||
+ (b != 0)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int bitnum = dataBitOffset + x * pixelBitStride;
+ int index = y * scanlineStride + (bitnum / dataElementSize);
+ int shift = dataElementSize - (bitnum & (dataElementSize-1))
+ - pixelBitStride;
+ int element = data.getElem(index);
+ element &= ~(bitMask << shift);
+ element |= (s & bitMask) << shift;
+ data.setElem(index,element);
+ }
+
+ /**
+ * Returns data for a single pixel in a primitive array of type
+ * TransferType. For a <code>MultiPixelPackedSampleModel</code>,
+ * the array has one element, and the type is the smallest of
+ * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT
+ * that can hold a single pixel. Generally, <code>obj</code>
+ * should be passed in as <code>null</code>, so that the
+ * <code>Object</code> is created automatically and is the
+ * correct primitive data type.
+ * <p>
+ * The following code illustrates transferring data for one pixel from
+ * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
+ * described by <code>MultiPixelPackedSampleModel</code>
+ * <code>mppsm1</code>, to <code>DataBuffer</code> <code>db2</code>,
+ * whose storage layout is described by
+ * <code>MultiPixelPackedSampleModel</code> <code>mppsm2</code>.
+ * The transfer is generally more efficient than using
+ * <code>getPixel</code> or <code>setPixel</code>.
+ * <pre>
+ * MultiPixelPackedSampleModel mppsm1, mppsm2;
+ * DataBufferInt db1, db2;
+ * mppsm2.setDataElements(x, y, mppsm1.getDataElements(x, y, null,
+ * db1), db2);
+ * </pre>
+ * Using <code>getDataElements</code> or <code>setDataElements</code>
+ * to transfer between two <code>DataBuffer/SampleModel</code> pairs
+ * is legitimate if the <code>SampleModels</code> have the same number
+ * of bands, corresponding bands have the same number of
+ * bits per sample, and the TransferTypes are the same.
+ * <p>
+ * If <code>obj</code> is not <code>null</code>, it should be a
+ * primitive array of type TransferType. Otherwise, a
+ * <code>ClassCastException</code> is thrown. An
+ * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
+ * coordinates are not in bounds, or if <code>obj</code> is not
+ * <code>null</code> and is not large enough to hold the pixel data.
+ * @param x the X coordinate of the specified pixel
+ * @param y the Y coordinate of the specified pixel
+ * @param obj a primitive array in which to return the pixel data or
+ * <code>null</code>.
+ * @param data the <code>DataBuffer</code> containing the image data.
+ * @return an <code>Object</code> containing data for the specified
+ * pixel.
+ * @exception ClassCastException if <code>obj</code> is not a
+ * primitive array of type TransferType or is not <code>null</code>
+ * @exception ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if <code>obj</code> is not <code>null</code> or
+ * not large enough to hold the pixel data
+ * @see #setDataElements(int, int, Object, DataBuffer)
+ */
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ int type = getTransferType();
+ int bitnum = dataBitOffset + x*pixelBitStride;
+ int shift = dataElementSize - (bitnum & (dataElementSize-1))
+ - pixelBitStride;
+ int element = 0;
+
+ switch(type) {
+
+ case DataBuffer.TYPE_BYTE:
+
+ byte[] bdata;
+
+ if (obj == null)
+ bdata = new byte[1];
+ else
+ bdata = (byte[])obj;
+
+ element = data.getElem(y*scanlineStride +
+ bitnum/dataElementSize);
+ bdata[0] = (byte)((element >> shift) & bitMask);
+
+ obj = (Object)bdata;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+
+ short[] sdata;
+
+ if (obj == null)
+ sdata = new short[1];
+ else
+ sdata = (short[])obj;
+
+ element = data.getElem(y*scanlineStride +
+ bitnum/dataElementSize);
+ sdata[0] = (short)((element >> shift) & bitMask);
+
+ obj = (Object)sdata;
+ break;
+
+ case DataBuffer.TYPE_INT:
+
+ int[] idata;
+
+ if (obj == null)
+ idata = new int[1];
+ else
+ idata = (int[])obj;
+
+ element = data.getElem(y*scanlineStride +
+ bitnum/dataElementSize);
+ idata[0] = (element >> shift) & bitMask;
+
+ obj = (Object)idata;
+ break;
+ }
+
+ return obj;
+ }
+
+ /**
+ * Returns the specified single band pixel in the first element
+ * of an <code>int</code> array.
+ * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
+ * coordinates are not in bounds.
+ * @param x the X coordinate of the specified pixel
+ * @param y the Y coordinate of the specified pixel
+ * @param iArray the array containing the pixel to be returned or
+ * <code>null</code>
+ * @param data the <code>DataBuffer</code> where image data is stored
+ * @return an array containing the specified pixel.
+ * @exception ArrayIndexOutOfBoundsException if the coordinates
+ * are not in bounds
+ * @see #setPixel(int, int, int[], DataBuffer)
+ */
+ public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int pixels[];
+ if (iArray != null) {
+ pixels = iArray;
+ } else {
+ pixels = new int [numBands];
+ }
+ int bitnum = dataBitOffset + x*pixelBitStride;
+ int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
+ int shift = dataElementSize - (bitnum & (dataElementSize-1))
+ - pixelBitStride;
+ pixels[0] = (element >> shift) & bitMask;
+ return pixels;
+ }
+
+ /**
+ * Sets the data for a single pixel in the specified
+ * <code>DataBuffer</code> from a primitive array of type
+ * TransferType. For a <code>MultiPixelPackedSampleModel</code>,
+ * only the first element of the array holds valid data,
+ * and the type must be the smallest of
+ * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT
+ * that can hold a single pixel.
+ * <p>
+ * The following code illustrates transferring data for one pixel from
+ * <code>DataBuffer</code> <code>db1</code>, whose storage layout is
+ * described by <code>MultiPixelPackedSampleModel</code>
+ * <code>mppsm1</code>, to <code>DataBuffer</code> <code>db2</code>,
+ * whose storage layout is described by
+ * <code>MultiPixelPackedSampleModel</code> <code>mppsm2</code>.
+ * The transfer is generally more efficient than using
+ * <code>getPixel</code> or <code>setPixel</code>.
+ * <pre>
+ * MultiPixelPackedSampleModel mppsm1, mppsm2;
+ * DataBufferInt db1, db2;
+ * mppsm2.setDataElements(x, y, mppsm1.getDataElements(x, y, null,
+ * db1), db2);
+ * </pre>
+ * Using <code>getDataElements</code> or <code>setDataElements</code> to
+ * transfer between two <code>DataBuffer/SampleModel</code> pairs is
+ * legitimate if the <code>SampleModel</code> objects have
+ * the same number of bands, corresponding bands have the same number of
+ * bits per sample, and the TransferTypes are the same.
+ * <p>
+ * <code>obj</code> must be a primitive array of type TransferType.
+ * Otherwise, a <code>ClassCastException</code> is thrown. An
+ * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
+ * coordinates are not in bounds, or if <code>obj</code> is not large
+ * enough to hold the pixel data.
+ * @param x the X coordinate of the pixel location
+ * @param y the Y coordinate of the pixel location
+ * @param obj a primitive array containing pixel data
+ * @param data the <code>DataBuffer</code> containing the image data
+ * @see #getDataElements(int, int, Object, DataBuffer)
+ */
+ public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ int type = getTransferType();
+ int bitnum = dataBitOffset + x * pixelBitStride;
+ int index = y * scanlineStride + (bitnum / dataElementSize);
+ int shift = dataElementSize - (bitnum & (dataElementSize-1))
+ - pixelBitStride;
+ int element = data.getElem(index);
+ element &= ~(bitMask << shift);
+
+ switch(type) {
+
+ case DataBuffer.TYPE_BYTE:
+
+ byte[] barray = (byte[])obj;
+ element |= ( ((int)(barray[0])&0xff) & bitMask) << shift;
+ data.setElem(index, element);
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+
+ short[] sarray = (short[])obj;
+ element |= ( ((int)(sarray[0])&0xffff) & bitMask) << shift;
+ data.setElem(index, element);
+ break;
+
+ case DataBuffer.TYPE_INT:
+
+ int[] iarray = (int[])obj;
+ element |= (iarray[0] & bitMask) << shift;
+ data.setElem(index, element);
+ break;
+ }
+ }
+
+ /**
+ * Sets a pixel in the <code>DataBuffer</code> using an
+ * <code>int</code> array for input.
+ * <code>ArrayIndexOutOfBoundsException</code> is thrown if
+ * the coordinates are not in bounds.
+ * @param x the X coordinate of the pixel location
+ * @param y the Y coordinate of the pixel location
+ * @param iArray the input pixel in an <code>int</code> array
+ * @param data the <code>DataBuffer</code> containing the image data
+ * @see #getPixel(int, int, int[], DataBuffer)
+ */
+ public void setPixel(int x, int y, int[] iArray, DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int bitnum = dataBitOffset + x * pixelBitStride;
+ int index = y * scanlineStride + (bitnum / dataElementSize);
+ int shift = dataElementSize - (bitnum & (dataElementSize-1))
+ - pixelBitStride;
+ int element = data.getElem(index);
+ element &= ~(bitMask << shift);
+ element |= (iArray[0] & bitMask) << shift;
+ data.setElem(index,element);
+ }
+
+ public boolean equals(Object o) {
+ if ((o == null) || !(o instanceof MultiPixelPackedSampleModel)) {
+ return false;
+ }
+
+ MultiPixelPackedSampleModel that = (MultiPixelPackedSampleModel)o;
+ return this.width == that.width &&
+ this.height == that.height &&
+ this.numBands == that.numBands &&
+ this.dataType == that.dataType &&
+ this.pixelBitStride == that.pixelBitStride &&
+ this.bitMask == that.bitMask &&
+ this.pixelsPerDataElement == that.pixelsPerDataElement &&
+ this.dataElementSize == that.dataElementSize &&
+ this.dataBitOffset == that.dataBitOffset &&
+ this.scanlineStride == that.scanlineStride;
+ }
+
+ // If we implement equals() we must also implement hashCode
+ public int hashCode() {
+ int hash = 0;
+ hash = width;
+ hash <<= 8;
+ hash ^= height;
+ hash <<= 8;
+ hash ^= numBands;
+ hash <<= 8;
+ hash ^= dataType;
+ hash <<= 8;
+ hash ^= pixelBitStride;
+ hash <<= 8;
+ hash ^= bitMask;
+ hash <<= 8;
+ hash ^= pixelsPerDataElement;
+ hash <<= 8;
+ hash ^= dataElementSize;
+ hash <<= 8;
+ hash ^= dataBitOffset;
+ hash <<= 8;
+ hash ^= scanlineStride;
+ return hash;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/Raster.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,1777 @@
+/*
+ * Portions Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+
+package java.awt.image;
+import java.awt.Rectangle;
+import java.awt.Point;
+
+import sun.awt.image.ByteInterleavedRaster;
+import sun.awt.image.ShortInterleavedRaster;
+import sun.awt.image.IntegerInterleavedRaster;
+import sun.awt.image.ByteBandedRaster;
+import sun.awt.image.ShortBandedRaster;
+import sun.awt.image.BytePackedRaster;
+import sun.awt.image.SunWritableRaster;
+
+/**
+ * A class representing a rectangular array of pixels. A Raster
+ * encapsulates a DataBuffer that stores the sample values and a
+ * SampleModel that describes how to locate a given sample value in a
+ * DataBuffer.
+ * <p>
+ * A Raster defines values for pixels occupying a particular
+ * rectangular area of the plane, not necessarily including (0, 0).
+ * The rectangle, known as the Raster's bounding rectangle and
+ * available by means of the getBounds method, is defined by minX,
+ * minY, width, and height values. The minX and minY values define
+ * the coordinate of the upper left corner of the Raster. References
+ * to pixels outside of the bounding rectangle may result in an
+ * exception being thrown, or may result in references to unintended
+ * elements of the Raster's associated DataBuffer. It is the user's
+ * responsibility to avoid accessing such pixels.
+ * <p>
+ * A SampleModel describes how samples of a Raster
+ * are stored in the primitive array elements of a DataBuffer.
+ * Samples may be stored one per data element, as in a
+ * PixelInterleavedSampleModel or BandedSampleModel, or packed several to
+ * an element, as in a SinglePixelPackedSampleModel or
+ * MultiPixelPackedSampleModel. The SampleModel is also
+ * controls whether samples are sign extended, allowing unsigned
+ * data to be stored in signed Java data types such as byte, short, and
+ * int.
+ * <p>
+ * Although a Raster may live anywhere in the plane, a SampleModel
+ * makes use of a simple coordinate system that starts at (0, 0). A
+ * Raster therefore contains a translation factor that allows pixel
+ * locations to be mapped between the Raster's coordinate system and
+ * that of the SampleModel. The translation from the SampleModel
+ * coordinate system to that of the Raster may be obtained by the
+ * getSampleModelTranslateX and getSampleModelTranslateY methods.
+ * <p>
+ * A Raster may share a DataBuffer with another Raster either by
+ * explicit construction or by the use of the createChild and
+ * createTranslatedChild methods. Rasters created by these methods
+ * can return a reference to the Raster they were created from by
+ * means of the getParent method. For a Raster that was not
+ * constructed by means of a call to createTranslatedChild or
+ * createChild, getParent will return null.
+ * <p>
+ * The createTranslatedChild method returns a new Raster that
+ * shares all of the data of the current Raster, but occupies a
+ * bounding rectangle of the same width and height but with a
+ * different starting point. For example, if the parent Raster
+ * occupied the region (10, 10) to (100, 100), and the translated
+ * Raster was defined to start at (50, 50), then pixel (20, 20) of the
+ * parent and pixel (60, 60) of the child occupy the same location in
+ * the DataBuffer shared by the two Rasters. In the first case, (-10,
+ * -10) should be added to a pixel coordinate to obtain the
+ * corresponding SampleModel coordinate, and in the second case (-50,
+ * -50) should be added.
+ * <p>
+ * The translation between a parent and child Raster may be
+ * determined by subtracting the child's sampleModelTranslateX and
+ * sampleModelTranslateY values from those of the parent.
+ * <p>
+ * The createChild method may be used to create a new Raster
+ * occupying only a subset of its parent's bounding rectangle
+ * (with the same or a translated coordinate system) or
+ * with a subset of the bands of its parent.
+ * <p>
+ * All constructors are protected. The correct way to create a
+ * Raster is to use one of the static create methods defined in this
+ * class. These methods create instances of Raster that use the
+ * standard Interleaved, Banded, and Packed SampleModels and that may
+ * be processed more efficiently than a Raster created by combining
+ * an externally generated SampleModel and DataBuffer.
+ * @see java.awt.image.DataBuffer
+ * @see java.awt.image.SampleModel
+ * @see java.awt.image.PixelInterleavedSampleModel
+ * @see java.awt.image.BandedSampleModel
+ * @see java.awt.image.SinglePixelPackedSampleModel
+ * @see java.awt.image.MultiPixelPackedSampleModel
+ */
+public class Raster {
+
+ /**
+ * The SampleModel that describes how pixels from this Raster
+ * are stored in the DataBuffer.
+ */
+ protected SampleModel sampleModel;
+
+ /** The DataBuffer that stores the image data. */
+ protected DataBuffer dataBuffer;
+
+ /** The X coordinate of the upper-left pixel of this Raster. */
+ protected int minX;
+
+ /** The Y coordinate of the upper-left pixel of this Raster. */
+ protected int minY;
+
+ /** The width of this Raster. */
+ protected int width;
+
+ /** The height of this Raster. */
+ protected int height;
+
+ /**
+ * The X translation from the coordinate space of the
+ * Raster's SampleModel to that of the Raster.
+ */
+ protected int sampleModelTranslateX;
+
+ /**
+ * The Y translation from the coordinate space of the
+ * Raster's SampleModel to that of the Raster.
+ */
+ protected int sampleModelTranslateY;
+
+ /** The number of bands in the Raster. */
+ protected int numBands;
+
+ /** The number of DataBuffer data elements per pixel. */
+ protected int numDataElements;
+
+ /** The parent of this Raster, or null. */
+ protected Raster parent;
+
+ static private native void initIDs();
+ static {
+ ColorModel.loadLibraries();
+ initIDs();
+ }
+
+ /**
+ * Creates a Raster based on a PixelInterleavedSampleModel with the
+ * specified data type, width, height, and number of bands.
+ *
+ * <p> The upper left corner of the Raster is given by the
+ * location argument. If location is null, (0, 0) will be used.
+ * The dataType parameter should be one of the enumerated values
+ * defined in the DataBuffer class.
+ *
+ * <p> Note that interleaved <code>DataBuffer.TYPE_INT</code>
+ * Rasters are not supported. To create a 1-band Raster of type
+ * <code>DataBuffer.TYPE_INT</code>, use
+ * Raster.createPackedRaster().
+ * <p> The only dataTypes supported currently are TYPE_BYTE
+ * and TYPE_USHORT.
+ * @param dataType the data type for storing samples
+ * @param w the width in pixels of the image data
+ * @param h the height in pixels of the image data
+ * @param bands the number of bands
+ * @param location the upper-left corner of the <code>Raster</code>
+ * @return a WritableRaster object with the specified data type,
+ * width, height and number of bands.
+ * @throws RasterFormatException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero, or computing either
+ * <code>location.x + w</code> or
+ * <code>location.y + h</code> results in integer
+ * overflow
+ */
+ public static WritableRaster createInterleavedRaster(int dataType,
+ int w, int h,
+ int bands,
+ Point location) {
+ int[] bandOffsets = new int[bands];
+ for (int i = 0; i < bands; i++) {
+ bandOffsets[i] = i;
+ }
+ return createInterleavedRaster(dataType, w, h, w*bands, bands,
+ bandOffsets, location);
+ }
+
+ /**
+ * Creates a Raster based on a PixelInterleavedSampleModel with the
+ * specified data type, width, height, scanline stride, pixel
+ * stride, and band offsets. The number of bands is inferred from
+ * bandOffsets.length.
+ *
+ * <p> The upper left corner of the Raster is given by the
+ * location argument. If location is null, (0, 0) will be used.
+ * The dataType parameter should be one of the enumerated values
+ * defined in the DataBuffer class.
+ *
+ * <p> Note that interleaved <code>DataBuffer.TYPE_INT</code>
+ * Rasters are not supported. To create a 1-band Raster of type
+ * <code>DataBuffer.TYPE_INT</code>, use
+ * Raster.createPackedRaster().
+ * <p> The only dataTypes supported currently are TYPE_BYTE
+ * and TYPE_USHORT.
+ * @param dataType the data type for storing samples
+ * @param w the width in pixels of the image data
+ * @param h the height in pixels of the image data
+ * @param scanlineStride the line stride of the image data
+ * @param pixelStride the pixel stride of the image data
+ * @param bandOffsets the offsets of all bands
+ * @param location the upper-left corner of the <code>Raster</code>
+ * @return a WritableRaster object with the specified data type,
+ * width, height, scanline stride, pixel stride and band
+ * offsets.
+ * @throws RasterFormatException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero, or computing either
+ * <code>location.x + w</code> or
+ * <code>location.y + h</code> results in integer
+ * overflow
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types, which are
+ * <code>DataBuffer.TYPE_BYTE</code>, or
+ * <code>DataBuffer.TYPE_USHORT</code>.
+ */
+ public static WritableRaster createInterleavedRaster(int dataType,
+ int w, int h,
+ int scanlineStride,
+ int pixelStride,
+ int bandOffsets[],
+ Point location) {
+ DataBuffer d;
+ int bands = bandOffsets.length;
+
+ int maxBandOff = bandOffsets[0];
+ for (int i=1; i < bands; i++) {
+ if (bandOffsets[i] > maxBandOff) {
+ maxBandOff = bandOffsets[i];
+ }
+ }
+ int size = maxBandOff + scanlineStride*(h-1) + pixelStride*(w-1) + 1;
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ d = new DataBufferByte(size);
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ d = new DataBufferUShort(size);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unsupported data type " +
+ dataType);
+ }
+
+ return createInterleavedRaster(d, w, h, scanlineStride,
+ pixelStride, bandOffsets, location);
+ }
+
+ /**
+ * Creates a Raster based on a BandedSampleModel with the
+ * specified data type, width, height, and number of bands.
+ *
+ * <p> The upper left corner of the Raster is given by the
+ * location argument. If location is null, (0, 0) will be used.
+ * The dataType parameter should be one of the enumerated values
+ * defined in the DataBuffer class.
+ *
+ * <p> The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT,
+ * and TYPE_INT.
+ * @param dataType the data type for storing samples
+ * @param w the width in pixels of the image data
+ * @param h the height in pixels of the image data
+ * @param bands the number of bands
+ * @param location the upper-left corner of the <code>Raster</code>
+ * @return a WritableRaster object with the specified data type,
+ * width, height and number of bands.
+ * @throws RasterFormatException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero, or computing either
+ * <code>location.x + w</code> or
+ * <code>location.y + h</code> results in integer
+ * overflow
+ * @throws ArrayIndexOutOfBoundsException if <code>bands</code>
+ * is less than 1
+ */
+ public static WritableRaster createBandedRaster(int dataType,
+ int w, int h,
+ int bands,
+ Point location) {
+ if (bands < 1) {
+ throw new ArrayIndexOutOfBoundsException("Number of bands ("+
+ bands+") must"+
+ " be greater than 0");
+ }
+ int[] bankIndices = new int[bands];
+ int[] bandOffsets = new int[bands];
+ for (int i = 0; i < bands; i++) {
+ bankIndices[i] = i;
+ bandOffsets[i] = 0;
+ }
+
+ return createBandedRaster(dataType, w, h, w,
+ bankIndices, bandOffsets,
+ location);
+ }
+
+ /**
+ * Creates a Raster based on a BandedSampleModel with the
+ * specified data type, width, height, scanline stride, bank
+ * indices and band offsets. The number of bands is inferred from
+ * bankIndices.length and bandOffsets.length, which must be the
+ * same.
+ *
+ * <p> The upper left corner of the Raster is given by the
+ * location argument. The dataType parameter should be one of the
+ * enumerated values defined in the DataBuffer class.
+ *
+ * <p> The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT,
+ * and TYPE_INT.
+ * @param dataType the data type for storing samples
+ * @param w the width in pixels of the image data
+ * @param h the height in pixels of the image data
+ * @param scanlineStride the line stride of the image data
+ * @param bankIndices the bank indices for each band
+ * @param bandOffsets the offsets of all bands
+ * @param location the upper-left corner of the <code>Raster</code>
+ * @return a WritableRaster object with the specified data type,
+ * width, height, scanline stride, bank indices and band
+ * offsets.
+ * @throws RasterFormatException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero, or computing either
+ * <code>location.x + w</code> or
+ * <code>location.y + h</code> results in integer
+ * overflow
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types, which are
+ * <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>
+ * or <code>DataBuffer.TYPE_INT</code>
+ * @throws ArrayIndexOutOfBoundsException if <code>bankIndices</code>
+ * or <code>bandOffsets</code> is <code>null</code>
+ */
+ public static WritableRaster createBandedRaster(int dataType,
+ int w, int h,
+ int scanlineStride,
+ int bankIndices[],
+ int bandOffsets[],
+ Point location) {
+ DataBuffer d;
+ int bands = bandOffsets.length;
+
+ if (bankIndices == null) {
+ throw new
+ ArrayIndexOutOfBoundsException("Bank indices array is null");
+ }
+ if (bandOffsets == null) {
+ throw new
+ ArrayIndexOutOfBoundsException("Band offsets array is null");
+ }
+
+ // Figure out the #banks and the largest band offset
+ int maxBank = bankIndices[0];
+ int maxBandOff = bandOffsets[0];
+ for (int i = 1; i < bands; i++) {
+ if (bankIndices[i] > maxBank) {
+ maxBank = bankIndices[i];
+ }
+ if (bandOffsets[i] > maxBandOff) {
+ maxBandOff = bandOffsets[i];
+ }
+ }
+ int banks = maxBank + 1;
+ int size = maxBandOff + scanlineStride*(h-1) + (w-1) + 1;
+
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ d = new DataBufferByte(size, banks);
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ d = new DataBufferUShort(size, banks);
+ break;
+
+ case DataBuffer.TYPE_INT:
+ d = new DataBufferInt(size, banks);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unsupported data type " +
+ dataType);
+ }
+
+ return createBandedRaster(d, w, h, scanlineStride,
+ bankIndices, bandOffsets, location);
+ }
+
+ /**
+ * Creates a Raster based on a SinglePixelPackedSampleModel with
+ * the specified data type, width, height, and band masks.
+ * The number of bands is inferred from bandMasks.length.
+ *
+ * <p> The upper left corner of the Raster is given by the
+ * location argument. If location is null, (0, 0) will be used.
+ * The dataType parameter should be one of the enumerated values
+ * defined in the DataBuffer class.
+ *
+ * <p> The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT,
+ * and TYPE_INT.
+ * @param dataType the data type for storing samples
+ * @param w the width in pixels of the image data
+ * @param h the height in pixels of the image data
+ * @param bandMasks an array containing an entry for each band
+ * @param location the upper-left corner of the <code>Raster</code>
+ * @return a WritableRaster object with the specified data type,
+ * width, height, and band masks.
+ * @throws RasterFormatException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero, or computing either
+ * <code>location.x + w</code> or
+ * <code>location.y + h</code> results in integer
+ * overflow
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types, which are
+ * <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>
+ * or <code>DataBuffer.TYPE_INT</code>
+ */
+ public static WritableRaster createPackedRaster(int dataType,
+ int w, int h,
+ int bandMasks[],
+ Point location) {
+ DataBuffer d;
+
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ d = new DataBufferByte(w*h);
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ d = new DataBufferUShort(w*h);
+ break;
+
+ case DataBuffer.TYPE_INT:
+ d = new DataBufferInt(w*h);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unsupported data type " +
+ dataType);
+ }
+
+ return createPackedRaster(d, w, h, w, bandMasks, location);
+ }
+
+ /**
+ * Creates a Raster based on a packed SampleModel with the
+ * specified data type, width, height, number of bands, and bits
+ * per band. If the number of bands is one, the SampleModel will
+ * be a MultiPixelPackedSampleModel.
+ *
+ * <p> If the number of bands is more than one, the SampleModel
+ * will be a SinglePixelPackedSampleModel, with each band having
+ * bitsPerBand bits. In either case, the requirements on dataType
+ * and bitsPerBand imposed by the corresponding SampleModel must
+ * be met.
+ *
+ * <p> The upper left corner of the Raster is given by the
+ * location argument. If location is null, (0, 0) will be used.
+ * The dataType parameter should be one of the enumerated values
+ * defined in the DataBuffer class.
+ *
+ * <p> The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT,
+ * and TYPE_INT.
+ * @param dataType the data type for storing samples
+ * @param w the width in pixels of the image data
+ * @param h the height in pixels of the image data
+ * @param bands the number of bands
+ * @param bitsPerBand the number of bits per band
+ * @param location the upper-left corner of the <code>Raster</code>
+ * @return a WritableRaster object with the specified data type,
+ * width, height, number of bands, and bits per band.
+ * @throws RasterFormatException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero, or computing either
+ * <code>location.x + w</code> or
+ * <code>location.y + h</code> results in integer
+ * overflow
+ * @throws IllegalArgumentException if the product of
+ * <code>bitsPerBand</code> and <code>bands</code> is
+ * greater than the number of bits held by
+ * <code>dataType</code>
+ * @throws IllegalArgumentException if <code>bitsPerBand</code> or
+ * <code>bands</code> is not greater than zero
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types, which are
+ * <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>
+ * or <code>DataBuffer.TYPE_INT</code>
+ */
+ public static WritableRaster createPackedRaster(int dataType,
+ int w, int h,
+ int bands,
+ int bitsPerBand,
+ Point location) {
+ DataBuffer d;
+
+ if (bands <= 0) {
+ throw new IllegalArgumentException("Number of bands ("+bands+
+ ") must be greater than 0");
+ }
+
+ if (bitsPerBand <= 0) {
+ throw new IllegalArgumentException("Bits per band ("+bitsPerBand+
+ ") must be greater than 0");
+ }
+
+ if (bands != 1) {
+ int[] masks = new int[bands];
+ int mask = (1 << bitsPerBand) - 1;
+ int shift = (bands-1)*bitsPerBand;
+
+ /* Make sure the total mask size will fit in the data type */
+ if (shift+bitsPerBand > DataBuffer.getDataTypeSize(dataType)) {
+ throw new IllegalArgumentException("bitsPerBand("+
+ bitsPerBand+") * bands is "+
+ " greater than data type "+
+ "size.");
+ }
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_INT:
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported data type " +
+ dataType);
+ }
+
+ for (int i = 0; i < bands; i++) {
+ masks[i] = mask << shift;
+ shift = shift - bitsPerBand;
+ }
+
+ return createPackedRaster(dataType, w, h, masks, location);
+ }
+ else {
+ double fw = w;
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ d = new DataBufferByte((int)(Math.ceil(fw/(8/bitsPerBand)))*h);
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ d = new DataBufferUShort((int)(Math.ceil(fw/(16/bitsPerBand)))*h);
+ break;
+
+ case DataBuffer.TYPE_INT:
+ d = new DataBufferInt((int)(Math.ceil(fw/(32/bitsPerBand)))*h);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unsupported data type " +
+ dataType);
+ }
+
+ return createPackedRaster(d, w, h, bitsPerBand, location);
+ }
+ }
+
+ /**
+ * Creates a Raster based on a PixelInterleavedSampleModel with the
+ * specified DataBuffer, width, height, scanline stride, pixel
+ * stride, and band offsets. The number of bands is inferred from
+ * bandOffsets.length. The upper left corner of the Raster
+ * is given by the location argument. If location is null, (0, 0)
+ * will be used.
+ * <p> Note that interleaved <code>DataBuffer.TYPE_INT</code>
+ * Rasters are not supported. To create a 1-band Raster of type
+ * <code>DataBuffer.TYPE_INT</code>, use
+ * Raster.createPackedRaster().
+ * @param dataBuffer the <code>DataBuffer</code> that contains the
+ * image data
+ * @param w the width in pixels of the image data
+ * @param h the height in pixels of the image data
+ * @param scanlineStride the line stride of the image data
+ * @param pixelStride the pixel stride of the image data
+ * @param bandOffsets the offsets of all bands
+ * @param location the upper-left corner of the <code>Raster</code>
+ * @return a WritableRaster object with the specified
+ * <code>DataBuffer</code>, width, height, scanline stride,
+ * pixel stride and band offsets.
+ * @throws RasterFormatException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero, or computing either
+ * <code>location.x + w</code> or
+ * <code>location.y + h</code> results in integer
+ * overflow
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types, which are
+ * <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>
+ * @throws RasterFormatException if <code>dataBuffer</code> has more
+ * than one bank.
+ * @throws NullPointerException if <code>dataBuffer</code> is null
+ */
+ public static WritableRaster createInterleavedRaster(DataBuffer dataBuffer,
+ int w, int h,
+ int scanlineStride,
+ int pixelStride,
+ int bandOffsets[],
+ Point location) {
+ if (dataBuffer == null) {
+ throw new NullPointerException("DataBuffer cannot be null");
+ }
+ if (location == null) {
+ location = new Point(0, 0);
+ }
+ int dataType = dataBuffer.getDataType();
+
+ PixelInterleavedSampleModel csm =
+ new PixelInterleavedSampleModel(dataType, w, h,
+ pixelStride,
+ scanlineStride,
+ bandOffsets);
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ return new ByteInterleavedRaster(csm, dataBuffer, location);
+
+ case DataBuffer.TYPE_USHORT:
+ return new ShortInterleavedRaster(csm, dataBuffer, location);
+
+ default:
+ throw new IllegalArgumentException("Unsupported data type " +
+ dataType);
+ }
+ }
+
+ /**
+ * Creates a Raster based on a BandedSampleModel with the
+ * specified DataBuffer, width, height, scanline stride, bank
+ * indices, and band offsets. The number of bands is inferred
+ * from bankIndices.length and bandOffsets.length, which must be
+ * the same. The upper left corner of the Raster is given by the
+ * location argument. If location is null, (0, 0) will be used.
+ * @param dataBuffer the <code>DataBuffer</code> that contains the
+ * image data
+ * @param w the width in pixels of the image data
+ * @param h the height in pixels of the image data
+ * @param scanlineStride the line stride of the image data
+ * @param bankIndices the bank indices for each band
+ * @param bandOffsets the offsets of all bands
+ * @param location the upper-left corner of the <code>Raster</code>
+ * @return a WritableRaster object with the specified
+ * <code>DataBuffer</code>, width, height, scanline stride,
+ * bank indices and band offsets.
+ * @throws RasterFormatException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero, or computing either
+ * <code>location.x + w</code> or
+ * <code>location.y + h</code> results in integer
+ * overflow
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types, which are
+ * <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>
+ * or <code>DataBuffer.TYPE_INT</code>
+ * @throws NullPointerException if <code>dataBuffer</code> is null
+ */
+ public static WritableRaster createBandedRaster(DataBuffer dataBuffer,
+ int w, int h,
+ int scanlineStride,
+ int bankIndices[],
+ int bandOffsets[],
+ Point location) {
+ if (dataBuffer == null) {
+ throw new NullPointerException("DataBuffer cannot be null");
+ }
+ if (location == null) {
+ location = new Point(0,0);
+ }
+ int dataType = dataBuffer.getDataType();
+
+ int bands = bankIndices.length;
+ if (bandOffsets.length != bands) {
+ throw new IllegalArgumentException(
+ "bankIndices.length != bandOffsets.length");
+ }
+
+ BandedSampleModel bsm =
+ new BandedSampleModel(dataType, w, h,
+ scanlineStride,
+ bankIndices, bandOffsets);
+
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ return new ByteBandedRaster(bsm, dataBuffer, location);
+
+ case DataBuffer.TYPE_USHORT:
+ return new ShortBandedRaster(bsm, dataBuffer, location);
+
+ case DataBuffer.TYPE_INT:
+ return new SunWritableRaster(bsm, dataBuffer, location);
+
+ default:
+ throw new IllegalArgumentException("Unsupported data type " +
+ dataType);
+ }
+ }
+
+ /**
+ * Creates a Raster based on a SinglePixelPackedSampleModel with
+ * the specified DataBuffer, width, height, scanline stride, and
+ * band masks. The number of bands is inferred from bandMasks.length.
+ * The upper left corner of the Raster is given by
+ * the location argument. If location is null, (0, 0) will be used.
+ * @param dataBuffer the <code>DataBuffer</code> that contains the
+ * image data
+ * @param w the width in pixels of the image data
+ * @param h the height in pixels of the image data
+ * @param scanlineStride the line stride of the image data
+ * @param bandMasks an array containing an entry for each band
+ * @param location the upper-left corner of the <code>Raster</code>
+ * @return a WritableRaster object with the specified
+ * <code>DataBuffer</code>, width, height, scanline stride,
+ * and band masks.
+ * @throws RasterFormatException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero, or computing either
+ * <code>location.x + w</code> or
+ * <code>location.y + h</code> results in integer
+ * overflow
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types, which are
+ * <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>
+ * or <code>DataBuffer.TYPE_INT</code>
+ * @throws RasterFormatException if <code>dataBuffer</code> has more
+ * than one bank.
+ * @throws NullPointerException if <code>dataBuffer</code> is null
+ */
+ public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
+ int w, int h,
+ int scanlineStride,
+ int bandMasks[],
+ Point location) {
+ if (dataBuffer == null) {
+ throw new NullPointerException("DataBuffer cannot be null");
+ }
+ if (location == null) {
+ location = new Point(0,0);
+ }
+ int dataType = dataBuffer.getDataType();
+
+ SinglePixelPackedSampleModel sppsm =
+ new SinglePixelPackedSampleModel(dataType, w, h, scanlineStride,
+ bandMasks);
+
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ return new ByteInterleavedRaster(sppsm, dataBuffer, location);
+
+ case DataBuffer.TYPE_USHORT:
+ return new ShortInterleavedRaster(sppsm, dataBuffer, location);
+
+ case DataBuffer.TYPE_INT:
+ return new IntegerInterleavedRaster(sppsm, dataBuffer, location);
+
+ default:
+ throw new IllegalArgumentException("Unsupported data type " +
+ dataType);
+ }
+ }
+
+ /**
+ * Creates a Raster based on a MultiPixelPackedSampleModel with the
+ * specified DataBuffer, width, height, and bits per pixel. The upper
+ * left corner of the Raster is given by the location argument. If
+ * location is null, (0, 0) will be used.
+ * @param dataBuffer the <code>DataBuffer</code> that contains the
+ * image data
+ * @param w the width in pixels of the image data
+ * @param h the height in pixels of the image data
+ * @param bitsPerPixel the number of bits for each pixel
+ * @param location the upper-left corner of the <code>Raster</code>
+ * @return a WritableRaster object with the specified
+ * <code>DataBuffer</code>, width, height, and
+ * bits per pixel.
+ * @throws RasterFormatException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero, or computing either
+ * <code>location.x + w</code> or
+ * <code>location.y + h</code> results in integer
+ * overflow
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types, which are
+ * <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>
+ * or <code>DataBuffer.TYPE_INT</code>
+ * @throws RasterFormatException if <code>dataBuffer</code> has more
+ * than one bank.
+ * @throws NullPointerException if <code>dataBuffer</code> is null
+ */
+ public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
+ int w, int h,
+ int bitsPerPixel,
+ Point location) {
+ if (dataBuffer == null) {
+ throw new NullPointerException("DataBuffer cannot be null");
+ }
+ if (location == null) {
+ location = new Point(0,0);
+ }
+ int dataType = dataBuffer.getDataType();
+
+ if (dataType != DataBuffer.TYPE_BYTE &&
+ dataType != DataBuffer.TYPE_USHORT &&
+ dataType != DataBuffer.TYPE_INT) {
+ throw new IllegalArgumentException("Unsupported data type " +
+ dataType);
+ }
+
+ if (dataBuffer.getNumBanks() != 1) {
+ throw new
+ RasterFormatException("DataBuffer for packed Rasters"+
+ " must only have 1 bank.");
+ }
+
+ MultiPixelPackedSampleModel mppsm =
+ new MultiPixelPackedSampleModel(dataType, w, h, bitsPerPixel);
+
+ if (dataType == DataBuffer.TYPE_BYTE &&
+ (bitsPerPixel == 1 || bitsPerPixel == 2 || bitsPerPixel == 4)) {
+ return new BytePackedRaster(mppsm, dataBuffer, location);
+ } else {
+ return new SunWritableRaster(mppsm, dataBuffer, location);
+ }
+ }
+
+
+ /**
+ * Creates a Raster with the specified SampleModel and DataBuffer.
+ * The upper left corner of the Raster is given by the location argument.
+ * If location is null, (0, 0) will be used.
+ * @param sm the specified <code>SampleModel</code>
+ * @param db the specified <code>DataBuffer</code>
+ * @param location the upper-left corner of the <code>Raster</code>
+ * @return a <code>Raster</code> with the specified
+ * <code>SampleModel</code>, <code>DataBuffer</code>, and
+ * location.
+ * @throws RasterFormatException if computing either
+ * <code>location.x + sm.getWidth()</code> or
+ * <code>location.y + sm.getHeight()</code> results in integer
+ * overflow
+ * @throws RasterFormatException if <code>db</code> has more
+ * than one bank and <code>sm</code> is a
+ * PixelInterleavedSampleModel, SinglePixelPackedSampleModel,
+ * or MultiPixelPackedSampleModel.
+ * @throws NullPointerException if either SampleModel or DataBuffer is
+ * null
+ */
+ public static Raster createRaster(SampleModel sm,
+ DataBuffer db,
+ Point location) {
+ if ((sm == null) || (db == null)) {
+ throw new NullPointerException("SampleModel and DataBuffer cannot be null");
+ }
+
+ if (location == null) {
+ location = new Point(0,0);
+ }
+ int dataType = sm.getDataType();
+
+ if (sm instanceof PixelInterleavedSampleModel) {
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ return new ByteInterleavedRaster(sm, db, location);
+
+ case DataBuffer.TYPE_USHORT:
+ return new ShortInterleavedRaster(sm, db, location);
+ }
+ } else if (sm instanceof SinglePixelPackedSampleModel) {
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ return new ByteInterleavedRaster(sm, db, location);
+
+ case DataBuffer.TYPE_USHORT:
+ return new ShortInterleavedRaster(sm, db, location);
+
+ case DataBuffer.TYPE_INT:
+ return new IntegerInterleavedRaster(sm, db, location);
+ }
+ } else if (sm instanceof MultiPixelPackedSampleModel &&
+ dataType == DataBuffer.TYPE_BYTE &&
+ sm.getSampleSize(0) < 8) {
+ return new BytePackedRaster(sm, db, location);
+ }
+
+ // we couldn't do anything special - do the generic thing
+
+ return new Raster(sm,db,location);
+ }
+
+ /**
+ * Creates a WritableRaster with the specified SampleModel.
+ * The upper left corner of the Raster is given by the location argument.
+ * If location is null, (0, 0) will be used.
+ * @param sm the specified <code>SampleModel</code>
+ * @param location the upper-left corner of the
+ * <code>WritableRaster</code>
+ * @return a <code>WritableRaster</code> with the specified
+ * <code>SampleModel</code> and location.
+ * @throws RasterFormatException if computing either
+ * <code>location.x + sm.getWidth()</code> or
+ * <code>location.y + sm.getHeight()</code> results in integer
+ * overflow
+ */
+ public static WritableRaster createWritableRaster(SampleModel sm,
+ Point location) {
+ if (location == null) {
+ location = new Point(0,0);
+ }
+
+ return createWritableRaster(sm, sm.createDataBuffer(), location);
+ }
+
+ /**
+ * Creates a WritableRaster with the specified SampleModel and DataBuffer.
+ * The upper left corner of the Raster is given by the location argument.
+ * If location is null, (0, 0) will be used.
+ * @param sm the specified <code>SampleModel</code>
+ * @param db the specified <code>DataBuffer</code>
+ * @param location the upper-left corner of the
+ * <code>WritableRaster</code>
+ * @return a <code>WritableRaster</code> with the specified
+ * <code>SampleModel</code>, <code>DataBuffer</code>, and
+ * location.
+ * @throws RasterFormatException if computing either
+ * <code>location.x + sm.getWidth()</code> or
+ * <code>location.y + sm.getHeight()</code> results in integer
+ * overflow
+ * @throws RasterFormatException if <code>db</code> has more
+ * than one bank and <code>sm</code> is a
+ * PixelInterleavedSampleModel, SinglePixelPackedSampleModel,
+ * or MultiPixelPackedSampleModel.
+ * @throws NullPointerException if either SampleModel or DataBuffer is null
+ */
+ public static WritableRaster createWritableRaster(SampleModel sm,
+ DataBuffer db,
+ Point location) {
+ if ((sm == null) || (db == null)) {
+ throw new NullPointerException("SampleModel and DataBuffer cannot be null");
+ }
+ if (location == null) {
+ location = new Point(0,0);
+ }
+
+ int dataType = sm.getDataType();
+
+ if (sm instanceof PixelInterleavedSampleModel) {
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ return new ByteInterleavedRaster(sm, db, location);
+
+ case DataBuffer.TYPE_USHORT:
+ return new ShortInterleavedRaster(sm, db, location);
+ }
+ } else if (sm instanceof SinglePixelPackedSampleModel) {
+ switch(dataType) {
+ case DataBuffer.TYPE_BYTE:
+ return new ByteInterleavedRaster(sm, db, location);
+
+ case DataBuffer.TYPE_USHORT:
+ return new ShortInterleavedRaster(sm, db, location);
+
+ case DataBuffer.TYPE_INT:
+ return new IntegerInterleavedRaster(sm, db, location);
+ }
+ } else if (sm instanceof MultiPixelPackedSampleModel &&
+ dataType == DataBuffer.TYPE_BYTE &&
+ sm.getSampleSize(0) < 8) {
+ return new BytePackedRaster(sm, db, location);
+ }
+
+ // we couldn't do anything special - do the generic thing
+
+ return new SunWritableRaster(sm,db,location);
+ }
+
+ /**
+ * Constructs a Raster with the given SampleModel. The Raster's
+ * upper left corner is origin and it is the same size as the
+ * SampleModel. A DataBuffer large enough to describe the
+ * Raster is automatically created.
+ * @param sampleModel The SampleModel that specifies the layout
+ * @param origin The Point that specified the origin
+ * @throws RasterFormatException if computing either
+ * <code>origin.x + sampleModel.getWidth()</code> or
+ * <code>origin.y + sampleModel.getHeight()</code> results in
+ * integer overflow
+ * @throws NullPointerException either <code>sampleModel</code> or
+ * <code>origin</code> is null
+ */
+ protected Raster(SampleModel sampleModel,
+ Point origin) {
+ this(sampleModel,
+ sampleModel.createDataBuffer(),
+ new Rectangle(origin.x,
+ origin.y,
+ sampleModel.getWidth(),
+ sampleModel.getHeight()),
+ origin,
+ null);
+ }
+
+ /**
+ * Constructs a Raster with the given SampleModel and DataBuffer.
+ * The Raster's upper left corner is origin and it is the same size
+ * as the SampleModel. The DataBuffer is not initialized and must
+ * be compatible with SampleModel.
+ * @param sampleModel The SampleModel that specifies the layout
+ * @param dataBuffer The DataBuffer that contains the image data
+ * @param origin The Point that specifies the origin
+ * @throws RasterFormatException if computing either
+ * <code>origin.x + sampleModel.getWidth()</code> or
+ * <code>origin.y + sampleModel.getHeight()</code> results in
+ * integer overflow
+ * @throws NullPointerException either <code>sampleModel</code> or
+ * <code>origin</code> is null
+ */
+ protected Raster(SampleModel sampleModel,
+ DataBuffer dataBuffer,
+ Point origin) {
+ this(sampleModel,
+ dataBuffer,
+ new Rectangle(origin.x,
+ origin.y,
+ sampleModel.getWidth(),
+ sampleModel.getHeight()),
+ origin,
+ null);
+ }
+
+ /**
+ * Constructs a Raster with the given SampleModel, DataBuffer, and
+ * parent. aRegion specifies the bounding rectangle of the new
+ * Raster. When translated into the base Raster's coordinate
+ * system, aRegion must be contained by the base Raster.
+ * (The base Raster is the Raster's ancestor which has no parent.)
+ * sampleModelTranslate specifies the sampleModelTranslateX and
+ * sampleModelTranslateY values of the new Raster.
+ *
+ * Note that this constructor should generally be called by other
+ * constructors or create methods, it should not be used directly.
+ * @param sampleModel The SampleModel that specifies the layout
+ * @param dataBuffer The DataBuffer that contains the image data
+ * @param aRegion The Rectangle that specifies the image area
+ * @param sampleModelTranslate The Point that specifies the translation
+ * from SampleModel to Raster coordinates
+ * @param parent The parent (if any) of this raster
+ * @throws NullPointerException if any of <code>sampleModel</code>,
+ * <code>dataBuffer</code>, <code>aRegion</code> or
+ * <code>sampleModelTranslate</code> is null
+ * @throws RasterFormatException if <code>aRegion</code> has width
+ * or height less than or equal to zero, or computing either
+ * <code>aRegion.x + aRegion.width</code> or
+ * <code>aRegion.y + aRegion.height</code> results in integer
+ * overflow
+ */
+ protected Raster(SampleModel sampleModel,
+ DataBuffer dataBuffer,
+ Rectangle aRegion,
+ Point sampleModelTranslate,
+ Raster parent) {
+
+ if ((sampleModel == null) || (dataBuffer == null) ||
+ (aRegion == null) || (sampleModelTranslate == null)) {
+ throw new NullPointerException("SampleModel, dataBuffer, aRegion and " +
+ "sampleModelTranslate cannot be null");
+ }
+ this.sampleModel = sampleModel;
+ this.dataBuffer = dataBuffer;
+ minX = aRegion.x;
+ minY = aRegion.y;
+ width = aRegion.width;
+ height = aRegion.height;
+ if (width <= 0 || height <= 0) {
+ throw new RasterFormatException("negative or zero " +
+ ((width <= 0) ? "width" : "height"));
+ }
+ if ((minX + width) < minX) {
+ throw new RasterFormatException(
+ "overflow condition for X coordinates of Raster");
+ }
+ if ((minY + height) < minY) {
+ throw new RasterFormatException(
+ "overflow condition for Y coordinates of Raster");
+ }
+
+ sampleModelTranslateX = sampleModelTranslate.x;
+ sampleModelTranslateY = sampleModelTranslate.y;
+
+ numBands = sampleModel.getNumBands();
+ numDataElements = sampleModel.getNumDataElements();
+ this.parent = parent;
+ }
+
+
+ /**
+ * Returns the parent Raster (if any) of this Raster or null.
+ * @return the parent Raster or <code>null</code>.
+ */
+ public Raster getParent() {
+ return parent;
+ }
+
+ /**
+ * Returns the X translation from the coordinate system of the
+ * SampleModel to that of the Raster. To convert a pixel's X
+ * coordinate from the Raster coordinate system to the SampleModel
+ * coordinate system, this value must be subtracted.
+ * @return the X translation from the coordinate space of the
+ * Raster's SampleModel to that of the Raster.
+ */
+ final public int getSampleModelTranslateX() {
+ return sampleModelTranslateX;
+ }
+
+ /**
+ * Returns the Y translation from the coordinate system of the
+ * SampleModel to that of the Raster. To convert a pixel's Y
+ * coordinate from the Raster coordinate system to the SampleModel
+ * coordinate system, this value must be subtracted.
+ * @return the Y translation from the coordinate space of the
+ * Raster's SampleModel to that of the Raster.
+ */
+ final public int getSampleModelTranslateY() {
+ return sampleModelTranslateY;
+ }
+
+ /**
+ * Create a compatible WritableRaster the same size as this Raster with
+ * the same SampleModel and a new initialized DataBuffer.
+ * @return a compatible <code>WritableRaster</code> with the same sample
+ * model and a new data buffer.
+ */
+ public WritableRaster createCompatibleWritableRaster() {
+ return new SunWritableRaster(sampleModel, new Point(0,0));
+ }
+
+ /**
+ * Create a compatible WritableRaster with the specified size, a new
+ * SampleModel, and a new initialized DataBuffer.
+ * @param w the specified width of the new <code>WritableRaster</code>
+ * @param h the specified height of the new <code>WritableRaster</code>
+ * @return a compatible <code>WritableRaster</code> with the specified
+ * size and a new sample model and data buffer.
+ * @exception RasterFormatException if the width or height is less than
+ * or equal to zero.
+ */
+ public WritableRaster createCompatibleWritableRaster(int w, int h) {
+ if (w <= 0 || h <=0) {
+ throw new RasterFormatException("negative " +
+ ((w <= 0) ? "width" : "height"));
+ }
+
+ SampleModel sm = sampleModel.createCompatibleSampleModel(w,h);
+
+ return new SunWritableRaster(sm, new Point(0,0));
+ }
+
+ /**
+ * Create a compatible WritableRaster with location (minX, minY)
+ * and size (width, height) specified by rect, a
+ * new SampleModel, and a new initialized DataBuffer.
+ * @param rect a <code>Rectangle</code> that specifies the size and
+ * location of the <code>WritableRaster</code>
+ * @return a compatible <code>WritableRaster</code> with the specified
+ * size and location and a new sample model and data buffer.
+ * @throws RasterFormatException if <code>rect</code> has width
+ * or height less than or equal to zero, or computing either
+ * <code>rect.x + rect.width</code> or
+ * <code>rect.y + rect.height</code> results in integer
+ * overflow
+ * @throws NullPointerException if <code>rect</code> is null
+ */
+ public WritableRaster createCompatibleWritableRaster(Rectangle rect) {
+ if (rect == null) {
+ throw new NullPointerException("Rect cannot be null");
+ }
+ return createCompatibleWritableRaster(rect.x, rect.y,
+ rect.width, rect.height);
+ }
+
+ /**
+ * Create a compatible WritableRaster with the specified
+ * location (minX, minY) and size (width, height), a
+ * new SampleModel, and a new initialized DataBuffer.
+ * @param x the X coordinate of the upper-left corner of
+ * the <code>WritableRaster</code>
+ * @param y the Y coordinate of the upper-left corner of
+ * the <code>WritableRaster</code>
+ * @param w the specified width of the <code>WritableRaster</code>
+ * @param h the specified height of the <code>WritableRaster</code>
+ * @return a compatible <code>WritableRaster</code> with the specified
+ * size and location and a new sample model and data buffer.
+ * @throws RasterFormatException if <code>w</code> or <code>h</code>
+ * is less than or equal to zero, or computing either
+ * <code>x + w</code> or
+ * <code>y + h</code> results in integer
+ * overflow
+ */
+ public WritableRaster createCompatibleWritableRaster(int x, int y,
+ int w, int h) {
+ WritableRaster ret = createCompatibleWritableRaster(w, h);
+ return ret.createWritableChild(0,0,w,h,x,y,null);
+ }
+
+ /**
+ * Create a Raster with the same size, SampleModel and DataBuffer
+ * as this one, but with a different location. The new Raster
+ * will possess a reference to the current Raster, accessible
+ * through its getParent() method.
+ *
+ * @param childMinX the X coordinate of the upper-left
+ * corner of the new <code>Raster</code>
+ * @param childMinY the Y coordinate of the upper-left
+ * corner of the new <code>Raster</code>
+ * @return a new <code>Raster</code> with the same size, SampleModel,
+ * and DataBuffer as this <code>Raster</code>, but with the
+ * specified location.
+ * @throws RasterFormatException if computing either
+ * <code>childMinX + this.getWidth()</code> or
+ * <code>childMinY + this.getHeight()</code> results in integer
+ * overflow
+ */
+ public Raster createTranslatedChild(int childMinX, int childMinY) {
+ return createChild(minX,minY,width,height,
+ childMinX,childMinY,null);
+ }
+
+ /**
+ * Returns a new Raster which shares all or part of this Raster's
+ * DataBuffer. The new Raster will possess a reference to the
+ * current Raster, accessible through its getParent() method.
+ *
+ * <p> The parentX, parentY, width and height parameters
+ * form a Rectangle in this Raster's coordinate space,
+ * indicating the area of pixels to be shared. An error will
+ * be thrown if this Rectangle is not contained with the bounds
+ * of the current Raster.
+ *
+ * <p> The new Raster may additionally be translated to a
+ * different coordinate system for the plane than that used by the current
+ * Raster. The childMinX and childMinY parameters give the new
+ * (x, y) coordinate of the upper-left pixel of the returned
+ * Raster; the coordinate (childMinX, childMinY) in the new Raster
+ * will map to the same pixel as the coordinate (parentX, parentY)
+ * in the current Raster.
+ *
+ * <p> The new Raster may be defined to contain only a subset of
+ * the bands of the current Raster, possibly reordered, by means
+ * of the bandList parameter. If bandList is null, it is taken to
+ * include all of the bands of the current Raster in their current
+ * order.
+ *
+ * <p> To create a new Raster that contains a subregion of the current
+ * Raster, but shares its coordinate system and bands,
+ * this method should be called with childMinX equal to parentX,
+ * childMinY equal to parentY, and bandList equal to null.
+ *
+ * @param parentX The X coordinate of the upper-left corner
+ * in this Raster's coordinates
+ * @param parentY The Y coordinate of the upper-left corner
+ * in this Raster's coordinates
+ * @param width Width of the region starting at (parentX, parentY)
+ * @param height Height of the region starting at (parentX, parentY).
+ * @param childMinX The X coordinate of the upper-left corner
+ * of the returned Raster
+ * @param childMinY The Y coordinate of the upper-left corner
+ * of the returned Raster
+ * @param bandList Array of band indices, or null to use all bands
+ * @return a new <code>Raster</code>.
+ * @exception RasterFormatException if the specified subregion is outside
+ * of the raster bounds.
+ * @throws RasterFormatException if <code>width</code> or
+ * <code>height</code>
+ * is less than or equal to zero, or computing any of
+ * <code>parentX + width</code>, <code>parentY + height</code>,
+ * <code>childMinX + width</code>, or
+ * <code>childMinY + height</code> results in integer
+ * overflow
+ */
+ public Raster createChild(int parentX, int parentY,
+ int width, int height,
+ int childMinX, int childMinY,
+ int bandList[]) {
+ if (parentX < this.minX) {
+ throw new RasterFormatException("parentX lies outside raster");
+ }
+ if (parentY < this.minY) {
+ throw new RasterFormatException("parentY lies outside raster");
+ }
+ if ((parentX + width < parentX) ||
+ (parentX + width > this.width + this.minX)) {
+ throw new RasterFormatException("(parentX + width) is outside raster");
+ }
+ if ((parentY + height < parentY) ||
+ (parentY + height > this.height + this.minY)) {
+ throw new RasterFormatException("(parentY + height) is outside raster");
+ }
+
+ SampleModel subSampleModel;
+ // Note: the SampleModel for the child Raster should have the same
+ // width and height as that for the parent, since it represents
+ // the physical layout of the pixel data. The child Raster's width
+ // and height represent a "virtual" view of the pixel data, so
+ // they may be different than those of the SampleModel.
+ if (bandList == null) {
+ subSampleModel = sampleModel;
+ } else {
+ subSampleModel = sampleModel.createSubsetSampleModel(bandList);
+ }
+
+ int deltaX = childMinX - parentX;
+ int deltaY = childMinY - parentY;
+
+ return new Raster(subSampleModel, getDataBuffer(),
+ new Rectangle(childMinX, childMinY, width, height),
+ new Point(sampleModelTranslateX + deltaX,
+ sampleModelTranslateY + deltaY), this);
+ }
+
+ /**
+ * Returns the bounding Rectangle of this Raster. This function returns
+ * the same information as getMinX/MinY/Width/Height.
+ * @return the bounding box of this <code>Raster</code>.
+ */
+ public Rectangle getBounds() {
+ return new Rectangle(minX, minY, width, height);
+ }
+
+ /** Returns the minimum valid X coordinate of the Raster.
+ * @return the minimum x coordinate of this <code>Raster</code>.
+ */
+ final public int getMinX() {
+ return minX;
+ }
+
+ /** Returns the minimum valid Y coordinate of the Raster.
+ * @return the minimum y coordinate of this <code>Raster</code>.
+ */
+ final public int getMinY() {
+ return minY;
+ }
+
+ /** Returns the width in pixels of the Raster.
+ * @return the width of this <code>Raster</code>.
+ */
+ final public int getWidth() {
+ return width;
+ }
+
+ /** Returns the height in pixels of the Raster.
+ * @return the height of this <code>Raster</code>.
+ */
+ final public int getHeight() {
+ return height;
+ }
+
+ /** Returns the number of bands (samples per pixel) in this Raster.
+ * @return the number of bands of this <code>Raster</code>.
+ */
+ final public int getNumBands() {
+ return numBands;
+ }
+
+ /**
+ * Returns the number of data elements needed to transfer one pixel
+ * via the getDataElements and setDataElements methods. When pixels
+ * are transferred via these methods, they may be transferred in a
+ * packed or unpacked format, depending on the implementation of the
+ * underlying SampleModel. Using these methods, pixels are transferred
+ * as an array of getNumDataElements() elements of a primitive type given
+ * by getTransferType(). The TransferType may or may not be the same
+ * as the storage data type of the DataBuffer.
+ * @return the number of data elements.
+ */
+ final public int getNumDataElements() {
+ return sampleModel.getNumDataElements();
+ }
+
+ /**
+ * Returns the TransferType used to transfer pixels via the
+ * getDataElements and setDataElements methods. When pixels
+ * are transferred via these methods, they may be transferred in a
+ * packed or unpacked format, depending on the implementation of the
+ * underlying SampleModel. Using these methods, pixels are transferred
+ * as an array of getNumDataElements() elements of a primitive type given
+ * by getTransferType(). The TransferType may or may not be the same
+ * as the storage data type of the DataBuffer. The TransferType will
+ * be one of the types defined in DataBuffer.
+ * @return this transfer type.
+ */
+ final public int getTransferType() {
+ return sampleModel.getTransferType();
+ }
+
+ /** Returns the DataBuffer associated with this Raster.
+ * @return the <code>DataBuffer</code> of this <code>Raster</code>.
+ */
+ public DataBuffer getDataBuffer() {
+ return dataBuffer;
+ }
+
+ /** Returns the SampleModel that describes the layout of the image data.
+ * @return the <code>SampleModel</code> of this <code>Raster</code>.
+ */
+ public SampleModel getSampleModel() {
+ return sampleModel;
+ }
+
+ /**
+ * Returns data for a single pixel in a primitive array of type
+ * TransferType. For image data supported by the Java 2D(tm) API,
+ * this will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT,
+ * or DataBuffer.TYPE_DOUBLE. Data may be returned in a packed format,
+ * thus increasing efficiency for data transfers.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * A ClassCastException will be thrown if the input object is non null
+ * and references anything other than an array of TransferType.
+ * @see java.awt.image.SampleModel#getDataElements(int, int, Object, DataBuffer)
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param outData An object reference to an array of type defined by
+ * getTransferType() and length getNumDataElements().
+ * If null, an array of appropriate type and size will be
+ * allocated
+ * @return An object reference to an array of type defined by
+ * getTransferType() with the requested pixel data.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if outData is too small to hold the output.
+ */
+ public Object getDataElements(int x, int y, Object outData) {
+ return sampleModel.getDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY,
+ outData, dataBuffer);
+ }
+
+ /**
+ * Returns the pixel data for the specified rectangle of pixels in a
+ * primitive array of type TransferType.
+ * For image data supported by the Java 2D API, this
+ * will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT,
+ * or DataBuffer.TYPE_DOUBLE. Data may be returned in a packed format,
+ * thus increasing efficiency for data transfers.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * A ClassCastException will be thrown if the input object is non null
+ * and references anything other than an array of TransferType.
+ * @see java.awt.image.SampleModel#getDataElements(int, int, int, int, Object, DataBuffer)
+ * @param x The X coordinate of the upper-left pixel location
+ * @param y The Y coordinate of the upper-left pixel location
+ * @param w Width of the pixel rectangle
+ * @param h Height of the pixel rectangle
+ * @param outData An object reference to an array of type defined by
+ * getTransferType() and length w*h*getNumDataElements().
+ * If null, an array of appropriate type and size will be
+ * allocated.
+ * @return An object reference to an array of type defined by
+ * getTransferType() with the requested pixel data.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if outData is too small to hold the output.
+ */
+ public Object getDataElements(int x, int y, int w, int h, Object outData) {
+ return sampleModel.getDataElements(x - sampleModelTranslateX,
+ y - sampleModelTranslateY,
+ w, h, outData, dataBuffer);
+ }
+
+ /**
+ * Returns the samples in an array of int for the specified pixel.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param iArray An optionally preallocated int array
+ * @return the samples for the specified pixel.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if iArray is too small to hold the output.
+ */
+ public int[] getPixel(int x, int y, int iArray[]) {
+ return sampleModel.getPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY,
+ iArray, dataBuffer);
+ }
+
+ /**
+ * Returns the samples in an array of float for the
+ * specified pixel.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param fArray An optionally preallocated float array
+ * @return the samples for the specified pixel.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if fArray is too small to hold the output.
+ */
+ public float[] getPixel(int x, int y, float fArray[]) {
+ return sampleModel.getPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY,
+ fArray, dataBuffer);
+ }
+
+ /**
+ * Returns the samples in an array of double for the specified pixel.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param dArray An optionally preallocated double array
+ * @return the samples for the specified pixel.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if dArray is too small to hold the output.
+ */
+ public double[] getPixel(int x, int y, double dArray[]) {
+ return sampleModel.getPixel(x - sampleModelTranslateX,
+ y - sampleModelTranslateY,
+ dArray, dataBuffer);
+ }
+
+ /**
+ * Returns an int array containing all samples for a rectangle of pixels,
+ * one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the upper-left pixel location
+ * @param y The Y coordinate of the upper-left pixel location
+ * @param w Width of the pixel rectangle
+ * @param h Height of the pixel rectangle
+ * @param iArray An optionally pre-allocated int array
+ * @return the samples for the specified rectangle of pixels.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if iArray is too small to hold the output.
+ */
+ public int[] getPixels(int x, int y, int w, int h, int iArray[]) {
+ return sampleModel.getPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h,
+ iArray, dataBuffer);
+ }
+
+ /**
+ * Returns a float array containing all samples for a rectangle of pixels,
+ * one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param w Width of the pixel rectangle
+ * @param h Height of the pixel rectangle
+ * @param fArray An optionally pre-allocated float array
+ * @return the samples for the specified rectangle of pixels.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if fArray is too small to hold the output.
+ */
+ public float[] getPixels(int x, int y, int w, int h,
+ float fArray[]) {
+ return sampleModel.getPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, w, h,
+ fArray, dataBuffer);
+ }
+
+ /**
+ * Returns a double array containing all samples for a rectangle of pixels,
+ * one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the upper-left pixel location
+ * @param y The Y coordinate of the upper-left pixel location
+ * @param w Width of the pixel rectangle
+ * @param h Height of the pixel rectangle
+ * @param dArray An optionally pre-allocated double array
+ * @return the samples for the specified rectangle of pixels.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if dArray is too small to hold the output.
+ */
+ public double[] getPixels(int x, int y, int w, int h,
+ double dArray[]) {
+ return sampleModel.getPixels(x - sampleModelTranslateX,
+ y - sampleModelTranslateY,
+ w, h, dArray, dataBuffer);
+ }
+
+
+ /**
+ * Returns the sample in a specified band for the pixel located
+ * at (x,y) as an int.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to return
+ * @return the sample in the specified band for the pixel at the
+ * specified coordinate.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public int getSample(int x, int y, int b) {
+ return sampleModel.getSample(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, b,
+ dataBuffer);
+ }
+
+ /**
+ * Returns the sample in a specified band
+ * for the pixel located at (x,y) as a float.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to return
+ * @return the sample in the specified band for the pixel at the
+ * specified coordinate.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public float getSampleFloat(int x, int y, int b) {
+ return sampleModel.getSampleFloat(x - sampleModelTranslateX,
+ y - sampleModelTranslateY, b,
+ dataBuffer);
+ }
+
+ /**
+ * Returns the sample in a specified band
+ * for a pixel located at (x,y) as a double.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param b The band to return
+ * @return the sample in the specified band for the pixel at the
+ * specified coordinate.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public double getSampleDouble(int x, int y, int b) {
+ return sampleModel.getSampleDouble(x - sampleModelTranslateX,
+ y - sampleModelTranslateY,
+ b, dataBuffer);
+ }
+
+ /**
+ * Returns the samples for a specified band for the specified rectangle
+ * of pixels in an int array, one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the upper-left pixel location
+ * @param y The Y coordinate of the upper-left pixel location
+ * @param w Width of the pixel rectangle
+ * @param h Height of the pixel rectangle
+ * @param b The band to return
+ * @param iArray An optionally pre-allocated int array
+ * @return the samples for the specified band for the specified
+ * rectangle of pixels.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if iArray is too small to
+ * hold the output.
+ */
+ public int[] getSamples(int x, int y, int w, int h, int b,
+ int iArray[]) {
+ return sampleModel.getSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY,
+ w, h, b, iArray,
+ dataBuffer);
+ }
+
+ /**
+ * Returns the samples for a specified band for the specified rectangle
+ * of pixels in a float array, one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the upper-left pixel location
+ * @param y The Y coordinate of the upper-left pixel location
+ * @param w Width of the pixel rectangle
+ * @param h Height of the pixel rectangle
+ * @param b The band to return
+ * @param fArray An optionally pre-allocated float array
+ * @return the samples for the specified band for the specified
+ * rectangle of pixels.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if fArray is too small to
+ * hold the output.
+ */
+ public float[] getSamples(int x, int y, int w, int h, int b,
+ float fArray[]) {
+ return sampleModel.getSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY,
+ w, h, b, fArray, dataBuffer);
+ }
+
+ /**
+ * Returns the samples for a specified band for a specified rectangle
+ * of pixels in a double array, one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown
+ * if the coordinates are not in bounds. However, explicit bounds
+ * checking is not guaranteed.
+ * @param x The X coordinate of the upper-left pixel location
+ * @param y The Y coordinate of the upper-left pixel location
+ * @param w Width of the pixel rectangle
+ * @param h Height of the pixel rectangle
+ * @param b The band to return
+ * @param dArray An optionally pre-allocated double array
+ * @return the samples for the specified band for the specified
+ * rectangle of pixels.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if dArray is too small to
+ * hold the output.
+ */
+ public double[] getSamples(int x, int y, int w, int h, int b,
+ double dArray[]) {
+ return sampleModel.getSamples(x - sampleModelTranslateX,
+ y - sampleModelTranslateY,
+ w, h, b, dArray, dataBuffer);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/RenderedImage.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,217 @@
+/*
+ * Portions Copyright 1997-2000 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+import java.awt.Rectangle;
+import java.util.Dictionary;
+import java.util.Vector;
+
+/**
+ * RenderedImage is a common interface for objects which contain
+ * or can produce image data in the form of Rasters. The image
+ * data may be stored/produced as a single tile or a regular array
+ * of tiles.
+ */
+
+public interface RenderedImage {
+
+ /**
+ * Returns a vector of RenderedImages that are the immediate sources of
+ * image data for this RenderedImage. This method returns null if
+ * the RenderedImage object has no information about its immediate
+ * sources. It returns an empty Vector if the RenderedImage object has
+ * no immediate sources.
+ * @return a Vector of <code>RenderedImage</code> objects.
+ */
+ Vector<RenderedImage> getSources();
+
+ /**
+ * Gets a property from the property set of this image. The set of
+ * properties and whether it is immutable is determined by the
+ * implementing class. This method returns
+ * java.awt.Image.UndefinedProperty if the specified property is
+ * not defined for this RenderedImage.
+ * @param name the name of the property
+ * @return the property indicated by the specified name.
+ * @see java.awt.Image#UndefinedProperty
+ */
+ Object getProperty(String name);
+
+ /**
+ * Returns an array of names recognized by
+ * {@link #getProperty(String) getProperty(String)}
+ * or <code>null</code>, if no property names are recognized.
+ * @return a <code>String</code> array containing all of the
+ * property names that <code>getProperty(String)</code> recognizes;
+ * or <code>null</code> if no property names are recognized.
+ */
+ String[] getPropertyNames();
+
+ /**
+ * Returns the ColorModel associated with this image. All Rasters
+ * returned from this image will have this as their ColorModel. This
+ * can return null.
+ * @return the <code>ColorModel</code> of this image.
+ */
+ ColorModel getColorModel();
+
+ /**
+ * Returns the SampleModel associated with this image. All Rasters
+ * returned from this image will have this as their SampleModel.
+ * @return the <code>SampleModel</code> of this image.
+ */
+ SampleModel getSampleModel();
+
+ /**
+ * Returns the width of the RenderedImage.
+ * @return the width of this <code>RenderedImage</code>.
+ */
+ int getWidth();
+
+ /**
+ * Returns the height of the RenderedImage.
+ * @return the height of this <code>RenderedImage</code>.
+ */
+ int getHeight();
+
+ /**
+ * Returns the minimum X coordinate (inclusive) of the RenderedImage.
+ * @return the X coordinate of this <code>RenderedImage</code>.
+ */
+ int getMinX();
+
+ /**
+ * Returns the minimum Y coordinate (inclusive) of the RenderedImage.
+ * @return the Y coordinate of this <code>RenderedImage</code>.
+ */
+ int getMinY();
+
+ /**
+ * Returns the number of tiles in the X direction.
+ * @return the number of tiles in the X direction.
+ */
+ int getNumXTiles();
+
+ /**
+ * Returns the number of tiles in the Y direction.
+ * @return the number of tiles in the Y direction.
+ */
+ int getNumYTiles();
+
+ /**
+ * Returns the minimum tile index in the X direction.
+ * @return the minimum tile index in the X direction.
+ */
+ int getMinTileX();
+
+ /**
+ * Returns the minimum tile index in the Y direction.
+ * @return the minimum tile index in the X direction.
+ */
+ int getMinTileY();
+
+ /**
+ * Returns the tile width in pixels. All tiles must have the same
+ * width.
+ * @return the tile width in pixels.
+ */
+ int getTileWidth();
+
+ /**
+ * Returns the tile height in pixels. All tiles must have the same
+ * height.
+ * @return the tile height in pixels.
+ */
+ int getTileHeight();
+
+ /**
+ * Returns the X offset of the tile grid relative to the origin,
+ * i.e., the X coordinate of the upper-left pixel of tile (0, 0).
+ * (Note that tile (0, 0) may not actually exist.)
+ * @return the X offset of the tile grid relative to the origin.
+ */
+ int getTileGridXOffset();
+
+ /**
+ * Returns the Y offset of the tile grid relative to the origin,
+ * i.e., the Y coordinate of the upper-left pixel of tile (0, 0).
+ * (Note that tile (0, 0) may not actually exist.)
+ * @return the Y offset of the tile grid relative to the origin.
+ */
+ int getTileGridYOffset();
+
+ /**
+ * Returns tile (tileX, tileY). Note that tileX and tileY are indices
+ * into the tile array, not pixel locations. The Raster that is returned
+ * is live and will be updated if the image is changed.
+ * @param tileX the X index of the requested tile in the tile array
+ * @param tileY the Y index of the requested tile in the tile array
+ * @return the tile given the specified indices.
+ */
+ Raster getTile(int tileX, int tileY);
+
+ /**
+ * Returns the image as one large tile (for tile based
+ * images this will require fetching the whole image
+ * and copying the image data over). The Raster returned is
+ * a copy of the image data and will not be updated if the image
+ * is changed.
+ * @return the image as one large tile.
+ */
+ Raster getData();
+
+ /**
+ * Computes and returns an arbitrary region of the RenderedImage.
+ * The Raster returned is a copy of the image data and will not
+ * be updated if the image is changed.
+ * @param rect the region of the RenderedImage to be returned.
+ * @return the region of the <code>RenderedImage</code>
+ * indicated by the specified <code>Rectangle</code>.
+ */
+ Raster getData(Rectangle rect);
+
+ /**
+ * Computes an arbitrary rectangular region of the RenderedImage
+ * and copies it into a caller-supplied WritableRaster. The region
+ * to be computed is determined from the bounds of the supplied
+ * WritableRaster. The supplied WritableRaster must have a
+ * SampleModel that is compatible with this image. If raster is null,
+ * an appropriate WritableRaster is created.
+ * @param raster a WritableRaster to hold the returned portion of the
+ * image, or null.
+ * @return a reference to the supplied or created WritableRaster.
+ */
+ WritableRaster copyData(WritableRaster raster);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/SampleModel.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,1393 @@
+/*
+ * Portions Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+
+/**
+ * This abstract class defines an interface for extracting samples of pixels
+ * in an image. All image data is expressed as a collection of pixels.
+ * Each pixel consists of a number of samples. A sample is a datum
+ * for one band of an image and a band consists of all samples of a
+ * particular type in an image. For example, a pixel might contain
+ * three samples representing its red, green and blue components.
+ * There are three bands in the image containing this pixel. One band
+ * consists of all the red samples from all pixels in the
+ * image. The second band consists of all the green samples and
+ * the remaining band consists of all of the blue samples. The pixel
+ * can be stored in various formats. For example, all samples from
+ * a particular band can be stored contiguously or all samples from a
+ * single pixel can be stored contiguously.
+ * <p>
+ * Subclasses of SampleModel specify the types of samples they can
+ * represent (e.g. unsigned 8-bit byte, signed 16-bit short, etc.)
+ * and may specify how the samples are organized in memory.
+ * In the Java 2D(tm) API, built-in image processing operators may
+ * not operate on all possible sample types, but generally will work
+ * for unsigned integral samples of 16 bits or less. Some operators
+ * support a wider variety of sample types.
+ * <p>
+ * A collection of pixels is represented as a Raster, which consists of
+ * a DataBuffer and a SampleModel. The SampleModel allows access to
+ * samples in the DataBuffer and may provide low-level information that
+ * a programmer can use to directly manipulate samples and pixels in the
+ * DataBuffer.
+ * <p>
+ * This class is generally a fall back method for dealing with
+ * images. More efficient code will cast the SampleModel to the
+ * appropriate subclass and extract the information needed to directly
+ * manipulate pixels in the DataBuffer.
+ *
+ * @see java.awt.image.DataBuffer
+ * @see java.awt.image.Raster
+ * @see java.awt.image.ComponentSampleModel
+ * @see java.awt.image.PixelInterleavedSampleModel
+ * @see java.awt.image.BandedSampleModel
+ * @see java.awt.image.MultiPixelPackedSampleModel
+ * @see java.awt.image.SinglePixelPackedSampleModel
+ */
+
+public abstract class SampleModel
+{
+
+ /** Width in pixels of the region of image data that this SampleModel
+ * describes.
+ */
+ protected int width;
+
+ /** Height in pixels of the region of image data that this SampleModel
+ * describes.
+ */
+ protected int height;
+
+ /** Number of bands of the image data that this SampleModel describes. */
+ protected int numBands;
+
+ /** Data type of the DataBuffer storing the pixel data.
+ * @see java.awt.image.DataBuffer
+ */
+ protected int dataType;
+
+ static private native void initIDs();
+ static {
+ ColorModel.loadLibraries();
+ initIDs();
+ }
+
+ /**
+ * Constructs a SampleModel with the specified parameters.
+ * @param dataType The data type of the DataBuffer storing the pixel data.
+ * @param w The width (in pixels) of the region of image data.
+ * @param h The height (in pixels) of the region of image data.
+ * @param numBands The number of bands of the image data.
+ * @throws IllegalArgumentException if <code>w</code> or <code>h</code>
+ * is not greater than 0
+ * @throws IllegalArgumentException if the product of <code>w</code>
+ * and <code>h</code> is greater than
+ * <code>Integer.MAX_VALUE</code>
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * one of the supported data types
+ */
+ public SampleModel(int dataType, int w, int h, int numBands)
+ {
+ float size = (float)w*h;
+ if (w <= 0 || h <= 0) {
+ throw new IllegalArgumentException("Width ("+w+") and height ("+
+ h+") must be > 0");
+ }
+ if (size >= Integer.MAX_VALUE) {
+ throw new IllegalArgumentException("Dimensions (width="+w+
+ " height="+h+") are too large");
+ }
+
+ if (dataType < DataBuffer.TYPE_BYTE ||
+ (dataType > DataBuffer.TYPE_DOUBLE &&
+ dataType != DataBuffer.TYPE_UNDEFINED))
+ {
+ throw new IllegalArgumentException("Unsupported dataType: "+
+ dataType);
+ }
+
+ if (numBands <= 0) {
+ throw new IllegalArgumentException("Number of bands must be > 0");
+ }
+
+ this.dataType = dataType;
+ this.width = w;
+ this.height = h;
+ this.numBands = numBands;
+ }
+
+ /** Returns the width in pixels.
+ * @return the width in pixels of the region of image data
+ * that this <code>SampleModel</code> describes.
+ */
+ final public int getWidth() {
+ return width;
+ }
+
+ /** Returns the height in pixels.
+ * @return the height in pixels of the region of image data
+ * that this <code>SampleModel</code> describes.
+ */
+ final public int getHeight() {
+ return height;
+ }
+
+ /** Returns the total number of bands of image data.
+ * @return the number of bands of image data that this
+ * <code>SampleModel</code> describes.
+ */
+ final public int getNumBands() {
+ return numBands;
+ }
+
+ /** Returns the number of data elements needed to transfer a pixel
+ * via the getDataElements and setDataElements methods. When pixels
+ * are transferred via these methods, they may be transferred in a
+ * packed or unpacked format, depending on the implementation of the
+ * SampleModel. Using these methods, pixels are transferred as an
+ * array of getNumDataElements() elements of a primitive type given
+ * by getTransferType(). The TransferType may or may not be the same
+ * as the storage DataType.
+ * @return the number of data elements.
+ * @see #getDataElements(int, int, Object, DataBuffer)
+ * @see #getDataElements(int, int, int, int, Object, DataBuffer)
+ * @see #setDataElements(int, int, Object, DataBuffer)
+ * @see #setDataElements(int, int, int, int, Object, DataBuffer)
+ * @see #getTransferType
+ */
+ public abstract int getNumDataElements();
+
+ /** Returns the data type of the DataBuffer storing the pixel data.
+ * @return the data type.
+ */
+ final public int getDataType() {
+ return dataType;
+ }
+
+ /** Returns the TransferType used to transfer pixels via the
+ * getDataElements and setDataElements methods. When pixels
+ * are transferred via these methods, they may be transferred in a
+ * packed or unpacked format, depending on the implementation of the
+ * SampleModel. Using these methods, pixels are transferred as an
+ * array of getNumDataElements() elements of a primitive type given
+ * by getTransferType(). The TransferType may or may not be the same
+ * as the storage DataType. The TransferType will be one of the types
+ * defined in DataBuffer.
+ * @return the transfer type.
+ * @see #getDataElements(int, int, Object, DataBuffer)
+ * @see #getDataElements(int, int, int, int, Object, DataBuffer)
+ * @see #setDataElements(int, int, Object, DataBuffer)
+ * @see #setDataElements(int, int, int, int, Object, DataBuffer)
+ * @see #getNumDataElements
+ * @see java.awt.image.DataBuffer
+ */
+ public int getTransferType() {
+ return dataType;
+ }
+
+ /**
+ * Returns the samples for a specified pixel in an int array,
+ * one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location
+ * @param y The Y coordinate of the pixel location
+ * @param iArray If non-null, returns the samples in this array
+ * @param data The DataBuffer containing the image data
+ * @return the samples for the specified pixel.
+ * @see #setPixel(int, int, int[], DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if iArray is too small to hold the output.
+ */
+ public int[] getPixel(int x, int y, int iArray[], DataBuffer data) {
+
+ int pixels[];
+
+ if (iArray != null)
+ pixels = iArray;
+ else
+ pixels = new int[numBands];
+
+ for (int i=0; i<numBands; i++) {
+ pixels[i] = getSample(x, y, i, data);
+ }
+
+ return pixels;
+ }
+
+ /**
+ * Returns data for a single pixel in a primitive array of type
+ * TransferType. For image data supported by the Java 2D API, this
+ * will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT,
+ * or DataBuffer.TYPE_DOUBLE. Data may be returned in a packed format,
+ * thus increasing efficiency for data transfers. Generally, obj
+ * should be passed in as null, so that the Object will be created
+ * automatically and will be of the right primitive data type.
+ * <p>
+ * The following code illustrates transferring data for one pixel from
+ * DataBuffer <code>db1</code>, whose storage layout is described by
+ * SampleModel <code>sm1</code>, to DataBuffer <code>db2</code>, whose
+ * storage layout is described by SampleModel <code>sm2</code>.
+ * The transfer will generally be more efficient than using
+ * getPixel/setPixel.
+ * <pre>
+ * SampleModel sm1, sm2;
+ * DataBuffer db1, db2;
+ * sm2.setDataElements(x, y, sm1.getDataElements(x, y, null, db1), db2);
+ * </pre>
+ * Using getDataElements/setDataElements to transfer between two
+ * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
+ * the same number of bands, corresponding bands have the same number of
+ * bits per sample, and the TransferTypes are the same.
+ * <p>
+ * If obj is non-null, it should be a primitive array of type TransferType.
+ * Otherwise, a ClassCastException is thrown. An
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds, or if obj is non-null and is not large enough to hold
+ * the pixel data.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param obj If non-null, a primitive array in which to return
+ * the pixel data.
+ * @param data The DataBuffer containing the image data.
+ * @return the data elements for the specified pixel.
+ * @see #getNumDataElements
+ * @see #getTransferType
+ * @see java.awt.image.DataBuffer
+ * @see #setDataElements(int, int, Object, DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if obj is too small to hold the output.
+ */
+ public abstract Object getDataElements(int x, int y,
+ Object obj, DataBuffer data);
+
+ /**
+ * Returns the pixel data for the specified rectangle of pixels in a
+ * primitive array of type TransferType.
+ * For image data supported by the Java 2D API, this
+ * will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
+ * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT,
+ * or DataBuffer.TYPE_DOUBLE. Data may be returned in a packed format,
+ * thus increasing efficiency for data transfers. Generally, obj
+ * should be passed in as null, so that the Object will be created
+ * automatically and will be of the right primitive data type.
+ * <p>
+ * The following code illustrates transferring data for a rectangular
+ * region of pixels from
+ * DataBuffer <code>db1</code>, whose storage layout is described by
+ * SampleModel <code>sm1</code>, to DataBuffer <code>db2</code>, whose
+ * storage layout is described by SampleModel <code>sm2</code>.
+ * The transfer will generally be more efficient than using
+ * getPixels/setPixels.
+ * <pre>
+ * SampleModel sm1, sm2;
+ * DataBuffer db1, db2;
+ * sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w,
+ * h, null, db1), db2);
+ * </pre>
+ * Using getDataElements/setDataElements to transfer between two
+ * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
+ * the same number of bands, corresponding bands have the same number of
+ * bits per sample, and the TransferTypes are the same.
+ * <p>
+ * If obj is non-null, it should be a primitive array of type TransferType.
+ * Otherwise, a ClassCastException is thrown. An
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds, or if obj is non-null and is not large enough to hold
+ * the pixel data.
+ * @param x The minimum X coordinate of the pixel rectangle.
+ * @param y The minimum Y coordinate of the pixel rectangle.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param obj If non-null, a primitive array in which to return
+ * the pixel data.
+ * @param data The DataBuffer containing the image data.
+ * @return the data elements for the specified region of pixels.
+ * @see #getNumDataElements
+ * @see #getTransferType
+ * @see #setDataElements(int, int, int, int, Object, DataBuffer)
+ * @see java.awt.image.DataBuffer
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if obj is too small to hold the output.
+ */
+ public Object getDataElements(int x, int y, int w, int h,
+ Object obj, DataBuffer data) {
+
+ int type = getTransferType();
+ int numDataElems = getNumDataElements();
+ int cnt = 0;
+ Object o = null;
+
+ switch(type) {
+
+ case DataBuffer.TYPE_BYTE:
+
+ byte[] btemp;
+ byte[] bdata;
+
+ if (obj == null)
+ bdata = new byte[numDataElems*w*h];
+ else
+ bdata = (byte[])obj;
+
+ for (int i=y; i<y+h; i++) {
+ for (int j=x; j<x+w; j++) {
+ o = getDataElements(j, i, o, data);
+ btemp = (byte[])o;
+ for (int k=0; k<numDataElems; k++) {
+ bdata[cnt++] = btemp[k];
+ }
+ }
+ }
+ obj = (Object)bdata;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
+
+ short[] sdata;
+ short[] stemp;
+
+ if (obj == null)
+ sdata = new short[numDataElems*w*h];
+ else
+ sdata = (short[])obj;
+
+ for (int i=y; i<y+h; i++) {
+ for (int j=x; j<x+w; j++) {
+ o = getDataElements(j, i, o, data);
+ stemp = (short[])o;
+ for (int k=0; k<numDataElems; k++) {
+ sdata[cnt++] = stemp[k];
+ }
+ }
+ }
+
+ obj = (Object)sdata;
+ break;
+
+ case DataBuffer.TYPE_INT:
+
+ int[] idata;
+ int[] itemp;
+
+ if (obj == null)
+ idata = new int[numDataElems*w*h];
+ else
+ idata = (int[])obj;
+
+ for (int i=y; i<y+h; i++) {
+ for (int j=x; j<x+w; j++) {
+ o = getDataElements(j, i, o, data);
+ itemp = (int[])o;
+ for (int k=0; k<numDataElems; k++) {
+ idata[cnt++] = itemp[k];
+ }
+ }
+ }
+
+ obj = (Object)idata;
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+
+ float[] fdata;
+ float[] ftemp;
+
+ if (obj == null)
+ fdata = new float[numDataElems*w*h];
+ else
+ fdata = (float[])obj;
+
+ for (int i=y; i<y+h; i++) {
+ for (int j=x; j<x+w; j++) {
+ o = getDataElements(j, i, o, data);
+ ftemp = (float[])o;
+ for (int k=0; k<numDataElems; k++) {
+ fdata[cnt++] = ftemp[k];
+ }
+ }
+ }
+
+ obj = (Object)fdata;
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+
+ double[] ddata;
+ double[] dtemp;
+
+ if (obj == null)
+ ddata = new double[numDataElems*w*h];
+ else
+ ddata = (double[])obj;
+
+ for (int i=y; i<y+h; i++) {
+ for (int j=x; j<x+w; j++) {
+ o = getDataElements(j, i, o, data);
+ dtemp = (double[])o;
+ for (int k=0; k<numDataElems; k++) {
+ ddata[cnt++] = dtemp[k];
+ }
+ }
+ }
+
+ obj = (Object)ddata;
+ break;
+ }
+
+ return obj;
+ }
+
+ /**
+ * Sets the data for a single pixel in the specified DataBuffer from a
+ * primitive array of type TransferType. For image data supported by
+ * the Java 2D API, this will be one of DataBuffer.TYPE_BYTE,
+ * DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
+ * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. Data in the array
+ * may be in a packed format, thus increasing efficiency for data
+ * transfers.
+ * <p>
+ * The following code illustrates transferring data for one pixel from
+ * DataBuffer <code>db1</code>, whose storage layout is described by
+ * SampleModel <code>sm1</code>, to DataBuffer <code>db2</code>, whose
+ * storage layout is described by SampleModel <code>sm2</code>.
+ * The transfer will generally be more efficient than using
+ * getPixel/setPixel.
+ * <pre>
+ * SampleModel sm1, sm2;
+ * DataBuffer db1, db2;
+ * sm2.setDataElements(x, y, sm1.getDataElements(x, y, null, db1),
+ * db2);
+ * </pre>
+ * Using getDataElements/setDataElements to transfer between two
+ * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
+ * the same number of bands, corresponding bands have the same number of
+ * bits per sample, and the TransferTypes are the same.
+ * <p>
+ * obj must be a primitive array of type TransferType. Otherwise,
+ * a ClassCastException is thrown. An
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds, or if obj is not large enough to hold the pixel data.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param obj A primitive array containing pixel data.
+ * @param data The DataBuffer containing the image data.
+ * @see #getNumDataElements
+ * @see #getTransferType
+ * @see #getDataElements(int, int, Object, DataBuffer)
+ * @see java.awt.image.DataBuffer
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if obj is too small to hold the input.
+ */
+ public abstract void setDataElements(int x, int y,
+ Object obj, DataBuffer data);
+
+ /**
+ * Sets the data for a rectangle of pixels in the specified DataBuffer
+ * from a primitive array of type TransferType. For image data supported
+ * by the Java 2D API, this will be one of DataBuffer.TYPE_BYTE,
+ * DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
+ * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. Data in the array
+ * may be in a packed format, thus increasing efficiency for data
+ * transfers.
+ * <p>
+ * The following code illustrates transferring data for a rectangular
+ * region of pixels from
+ * DataBuffer <code>db1</code>, whose storage layout is described by
+ * SampleModel <code>sm1</code>, to DataBuffer <code>db2</code>, whose
+ * storage layout is described by SampleModel <code>sm2</code>.
+ * The transfer will generally be more efficient than using
+ * getPixels/setPixels.
+ * <pre>
+ * SampleModel sm1, sm2;
+ * DataBuffer db1, db2;
+ * sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w, h,
+ * null, db1), db2);
+ * </pre>
+ * Using getDataElements/setDataElements to transfer between two
+ * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
+ * the same number of bands, corresponding bands have the same number of
+ * bits per sample, and the TransferTypes are the same.
+ * <p>
+ * obj must be a primitive array of type TransferType. Otherwise,
+ * a ClassCastException is thrown. An
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds, or if obj is not large enough to hold the pixel data.
+ * @param x The minimum X coordinate of the pixel rectangle.
+ * @param y The minimum Y coordinate of the pixel rectangle.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param obj A primitive array containing pixel data.
+ * @param data The DataBuffer containing the image data.
+ * @see #getNumDataElements
+ * @see #getTransferType
+ * @see #getDataElements(int, int, int, int, Object, DataBuffer)
+ * @see java.awt.image.DataBuffer
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if obj is too small to hold the input.
+ */
+ public void setDataElements(int x, int y, int w, int h,
+ Object obj, DataBuffer data) {
+
+ int cnt = 0;
+ Object o = null;
+ int type = getTransferType();
+ int numDataElems = getNumDataElements();
+
+ switch(type) {
+
+ case DataBuffer.TYPE_BYTE:
+
+ byte[] barray = (byte[])obj;
+ byte[] btemp = new byte[numDataElems];
+
+ for (int i=y; i<y+h; i++) {
+ for (int j=x; j<x+w; j++) {
+ for (int k=0; k<numDataElems; k++) {
+ btemp[k] = barray[cnt++];
+ }
+
+ setDataElements(j, i, btemp, data);
+ }
+ }
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
+
+ short[] sarray = (short[])obj;
+ short[] stemp = new short[numDataElems];
+
+ for (int i=y; i<y+h; i++) {
+ for (int j=x; j<x+w; j++) {
+ for (int k=0; k<numDataElems; k++) {
+ stemp[k] = sarray[cnt++];
+ }
+
+ setDataElements(j, i, stemp, data);
+ }
+ }
+ break;
+
+ case DataBuffer.TYPE_INT:
+
+ int[] iArray = (int[])obj;
+ int[] itemp = new int[numDataElems];
+
+ for (int i=y; i<y+h; i++) {
+ for (int j=x; j<x+w; j++) {
+ for (int k=0; k<numDataElems; k++) {
+ itemp[k] = iArray[cnt++];
+ }
+
+ setDataElements(j, i, itemp, data);
+ }
+ }
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+
+ float[] fArray = (float[])obj;
+ float[] ftemp = new float[numDataElems];
+
+ for (int i=y; i<y+h; i++) {
+ for (int j=x; j<x+w; j++) {
+ for (int k=0; k<numDataElems; k++) {
+ ftemp[k] = fArray[cnt++];
+ }
+
+ setDataElements(j, i, ftemp, data);
+ }
+ }
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+
+ double[] dArray = (double[])obj;
+ double[] dtemp = new double[numDataElems];
+
+ for (int i=y; i<y+h; i++) {
+ for (int j=x; j<x+w; j++) {
+ for (int k=0; k<numDataElems; k++) {
+ dtemp[k] = dArray[cnt++];
+ }
+
+ setDataElements(j, i, dtemp, data);
+ }
+ }
+ break;
+ }
+
+ }
+
+ /**
+ * Returns the samples for the specified pixel in an array of float.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param fArray If non-null, returns the samples in this array.
+ * @param data The DataBuffer containing the image data.
+ * @return the samples for the specified pixel.
+ * @see #setPixel(int, int, float[], DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if fArray is too small to hold the output.
+ */
+ public float[] getPixel(int x, int y, float fArray[],
+ DataBuffer data) {
+
+ float pixels[];
+
+ if (fArray != null)
+ pixels = fArray;
+ else
+ pixels = new float[numBands];
+
+ for (int i=0; i<numBands; i++)
+ pixels[i] = getSampleFloat(x, y, i, data);
+
+ return pixels;
+ }
+
+ /**
+ * Returns the samples for the specified pixel in an array of double.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param dArray If non-null, returns the samples in this array.
+ * @param data The DataBuffer containing the image data.
+ * @return the samples for the specified pixel.
+ * @see #setPixel(int, int, double[], DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if dArray is too small to hold the output.
+ */
+ public double[] getPixel(int x, int y, double dArray[],
+ DataBuffer data) {
+
+ double pixels[];
+
+ if(dArray != null)
+ pixels = dArray;
+ else
+ pixels = new double[numBands];
+
+ for (int i=0; i<numBands; i++)
+ pixels[i] = getSampleDouble(x, y, i, data);
+
+ return pixels;
+ }
+
+ /**
+ * Returns all samples for a rectangle of pixels in an
+ * int array, one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param iArray If non-null, returns the samples in this array.
+ * @param data The DataBuffer containing the image data.
+ * @return the samples for the specified region of pixels.
+ * @see #setPixels(int, int, int, int, int[], DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if iArray is too small to hold the output.
+ */
+ public int[] getPixels(int x, int y, int w, int h,
+ int iArray[], DataBuffer data) {
+
+ int pixels[];
+ int Offset=0;
+
+ if (iArray != null)
+ pixels = iArray;
+ else
+ pixels = new int[numBands * w * h];
+
+ for (int i=y; i<(h+y); i++) {
+ for (int j=x; j<(w+x); j++) {
+ for(int k=0; k<numBands; k++) {
+ pixels[Offset++] = getSample(j, i, k, data);
+ }
+ }
+ }
+
+ return pixels;
+ }
+
+ /**
+ * Returns all samples for a rectangle of pixels in a float
+ * array, one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param fArray If non-null, returns the samples in this array.
+ * @param data The DataBuffer containing the image data.
+ * @return the samples for the specified region of pixels.
+ * @see #setPixels(int, int, int, int, float[], DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if fArray is too small to hold the output.
+ */
+ public float[] getPixels(int x, int y, int w, int h,
+ float fArray[], DataBuffer data) {
+
+ float pixels[];
+ int Offset = 0;
+
+ if (fArray != null)
+ pixels = fArray;
+ else
+ pixels = new float[numBands * w * h];
+
+ for (int i=y; i<(h+y); i++) {
+ for(int j=x; j<(w+x); j++) {
+ for(int k=0; k<numBands; k++) {
+ pixels[Offset++] = getSampleFloat(j, i, k, data);
+ }
+ }
+ }
+
+ return pixels;
+ }
+
+ /**
+ * Returns all samples for a rectangle of pixels in a double
+ * array, one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param dArray If non-null, returns the samples in this array.
+ * @param data The DataBuffer containing the image data.
+ * @return the samples for the specified region of pixels.
+ * @see #setPixels(int, int, int, int, double[], DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if dArray is too small to hold the output.
+ */
+ public double[] getPixels(int x, int y, int w, int h,
+ double dArray[], DataBuffer data) {
+ double pixels[];
+ int Offset = 0;
+
+ if (dArray != null)
+ pixels = dArray;
+ else
+ pixels = new double[numBands * w * h];
+
+ // Fix 4217412
+ for (int i=y; i<(h+y); i++) {
+ for (int j=x; j<(w+x); j++) {
+ for (int k=0; k<numBands; k++) {
+ pixels[Offset++] = getSampleDouble(j, i, k, data);
+ }
+ }
+ }
+
+ return pixels;
+ }
+
+
+ /**
+ * Returns the sample in a specified band for the pixel located
+ * at (x,y) as an int.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param b The band to return.
+ * @param data The DataBuffer containing the image data.
+ * @return the sample in a specified band for the specified pixel.
+ * @see #setSample(int, int, int, int, DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public abstract int getSample(int x, int y, int b, DataBuffer data);
+
+
+ /**
+ * Returns the sample in a specified band
+ * for the pixel located at (x,y) as a float.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param b The band to return.
+ * @param data The DataBuffer containing the image data.
+ * @return the sample in a specified band for the specified pixel.
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public float getSampleFloat(int x, int y, int b, DataBuffer data) {
+
+ float sample;
+ sample = (float) getSample(x, y, b, data);
+ return sample;
+ }
+
+ /**
+ * Returns the sample in a specified band
+ * for a pixel located at (x,y) as a double.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param b The band to return.
+ * @param data The DataBuffer containing the image data.
+ * @return the sample in a specified band for the specified pixel.
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public double getSampleDouble(int x, int y, int b, DataBuffer data) {
+
+ double sample;
+
+ sample = (double) getSample(x, y, b, data);
+ return sample;
+ }
+
+ /**
+ * Returns the samples for a specified band for the specified rectangle
+ * of pixels in an int array, one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param b The band to return.
+ * @param iArray If non-null, returns the samples in this array.
+ * @param data The DataBuffer containing the image data.
+ * @return the samples for the specified band for the specified region
+ * of pixels.
+ * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if iArray is too small to
+ * hold the output.
+ */
+ public int[] getSamples(int x, int y, int w, int h, int b,
+ int iArray[], DataBuffer data) {
+ int pixels[];
+ int Offset=0;
+
+ if (iArray != null)
+ pixels = iArray;
+ else
+ pixels = new int[w * h];
+
+ for(int i=y; i<(h+y); i++) {
+ for (int j=x; j<(w+x); j++) {
+ pixels[Offset++] = getSample(j, i, b, data);
+ }
+ }
+
+ return pixels;
+ }
+
+ /**
+ * Returns the samples for a specified band for the specified rectangle
+ * of pixels in a float array, one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param b The band to return.
+ * @param fArray If non-null, returns the samples in this array.
+ * @param data The DataBuffer containing the image data.
+ * @return the samples for the specified band for the specified region
+ * of pixels.
+ * @see #setSamples(int, int, int, int, int, float[], DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if fArray is too small to
+ * hold the output.
+ */
+ public float[] getSamples(int x, int y, int w, int h,
+ int b, float fArray[],
+ DataBuffer data) {
+ float pixels[];
+ int Offset=0;
+
+ if (fArray != null)
+ pixels = fArray;
+ else
+ pixels = new float[w * h];
+
+ for (int i=y; i<(h+y); i++) {
+ for (int j=x; j<(w+x); j++) {
+ pixels[Offset++] = getSampleFloat(j, i, b, data);
+ }
+ }
+
+ return pixels;
+ }
+
+ /**
+ * Returns the samples for a specified band for a specified rectangle
+ * of pixels in a double array, one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param b The band to return.
+ * @param dArray If non-null, returns the samples in this array.
+ * @param data The DataBuffer containing the image data.
+ * @return the samples for the specified band for the specified region
+ * of pixels.
+ * @see #setSamples(int, int, int, int, int, double[], DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if dArray is too small to
+ * hold the output.
+ */
+ public double[] getSamples(int x, int y, int w, int h,
+ int b, double dArray[],
+ DataBuffer data) {
+ double pixels[];
+ int Offset=0;
+
+ if (dArray != null)
+ pixels = dArray;
+ else
+ pixels = new double[w * h];
+
+ for (int i=y; i<(y+h); i++) {
+ for (int j=x; j<(x+w); j++) {
+ pixels[Offset++] = getSampleDouble(j, i, b, data);
+ }
+ }
+
+ return pixels;
+ }
+
+ /**
+ * Sets a pixel in the DataBuffer using an int array of samples for input.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param iArray The input samples in an int array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getPixel(int, int, int[], DataBuffer)
+ *
+ * @throws NullPointerException if iArray or data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if iArray is too small to hold the input.
+ */
+ public void setPixel(int x, int y, int iArray[], DataBuffer data) {
+
+ for (int i=0; i<numBands; i++)
+ setSample(x, y, i, iArray[i], data);
+ }
+
+ /**
+ * Sets a pixel in the DataBuffer using a float array of samples for input.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param fArray The input samples in a float array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getPixel(int, int, float[], DataBuffer)
+ *
+ * @throws NullPointerException if fArray or data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if fArray is too small to hold the input.
+ */
+ public void setPixel(int x, int y, float fArray[], DataBuffer data) {
+
+ for (int i=0; i<numBands; i++)
+ setSample(x, y, i, fArray[i], data);
+ }
+
+ /**
+ * Sets a pixel in the DataBuffer using a double array of samples
+ * for input.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param dArray The input samples in a double array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getPixel(int, int, double[], DataBuffer)
+ *
+ * @throws NullPointerException if dArray or data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if fArray is too small to hold the input.
+ */
+ public void setPixel(int x, int y, double dArray[], DataBuffer data) {
+
+ for (int i=0; i<numBands; i++)
+ setSample(x, y, i, dArray[i], data);
+ }
+
+ /**
+ * Sets all samples for a rectangle of pixels from an int array containing
+ * one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param iArray The input samples in an int array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getPixels(int, int, int, int, int[], DataBuffer)
+ *
+ * @throws NullPointerException if iArray or data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if iArray is too small to hold the input.
+ */
+ public void setPixels(int x, int y, int w, int h,
+ int iArray[], DataBuffer data) {
+ int Offset=0;
+
+ for (int i=y; i<(y+h); i++) {
+ for (int j=x; j<(x+w); j++) {
+ for (int k=0; k<numBands; k++) {
+ setSample(j, i, k, iArray[Offset++], data);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets all samples for a rectangle of pixels from a float array containing
+ * one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param fArray The input samples in a float array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getPixels(int, int, int, int, float[], DataBuffer)
+ *
+ * @throws NullPointerException if fArray or data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if fArray is too small to hold the input.
+ */
+ public void setPixels(int x, int y, int w, int h,
+ float fArray[], DataBuffer data) {
+ int Offset=0;
+
+ for (int i=y; i<(y+h); i++) {
+ for (int j=x; j<(x+w); j++) {
+ for(int k=0; k<numBands; k++) {
+ setSample(j, i, k, fArray[Offset++], data);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets all samples for a rectangle of pixels from a double array
+ * containing one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param dArray The input samples in a double array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getPixels(int, int, int, int, double[], DataBuffer)
+ *
+ * @throws NullPointerException if dArray or data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are
+ * not in bounds, or if dArray is too small to hold the input.
+ */
+ public void setPixels(int x, int y, int w, int h,
+ double dArray[], DataBuffer data) {
+ int Offset=0;
+
+ for (int i=y; i<(y+h); i++) {
+ for (int j=x; j<(x+w); j++) {
+ for (int k=0; k<numBands; k++) {
+ setSample(j, i, k, dArray[Offset++], data);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the DataBuffer using an int for input.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param b The band to set.
+ * @param s The input sample as an int.
+ * @param data The DataBuffer containing the image data.
+ * @see #getSample(int, int, int, DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public abstract void setSample(int x, int y, int b,
+ int s,
+ DataBuffer data);
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the DataBuffer using a float for input.
+ * The default implementation of this method casts the input
+ * float sample to an int and then calls the
+ * <code>setSample(int, int, int, DataBuffer)</code> method using
+ * that int value.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param b The band to set.
+ * @param s The input sample as a float.
+ * @param data The DataBuffer containing the image data.
+ * @see #getSample(int, int, int, DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public void setSample(int x, int y, int b,
+ float s ,
+ DataBuffer data) {
+ int sample = (int)s;
+
+ setSample(x, y, b, sample, data);
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the DataBuffer using a double for input.
+ * The default implementation of this method casts the input
+ * double sample to an int and then calls the
+ * <code>setSample(int, int, int, DataBuffer)</code> method using
+ * that int value.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param b The band to set.
+ * @param s The input sample as a double.
+ * @param data The DataBuffer containing the image data.
+ * @see #getSample(int, int, int, DataBuffer)
+ *
+ * @throws NullPointerException if data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public void setSample(int x, int y, int b,
+ double s,
+ DataBuffer data) {
+ int sample = (int)s;
+
+ setSample(x, y, b, sample, data);
+ }
+
+ /**
+ * Sets the samples in the specified band for the specified rectangle
+ * of pixels from an int array containing one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param b The band to set.
+ * @param iArray The input samples in an int array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
+ *
+ * @throws NullPointerException if iArray or data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if iArray is too small to
+ * hold the input.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ int iArray[], DataBuffer data) {
+
+ int Offset=0;
+
+ for (int i=y; i<(y+h); i++) {
+ for (int j=x; j<(x+w); j++) {
+ setSample(j, i, b, iArray[Offset++], data);
+ }
+ }
+ }
+
+ /**
+ * Sets the samples in the specified band for the specified rectangle
+ * of pixels from a float array containing one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param b The band to set.
+ * @param fArray The input samples in a float array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getSamples(int, int, int, int, int, float[], DataBuffer)
+ *
+ * @throws NullPointerException if fArray or data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if fArray is too small to
+ * hold the input.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ float fArray[], DataBuffer data) {
+ int Offset=0;
+
+ for (int i=y; i<(y+h); i++) {
+ for (int j=x; j<(x+w); j++) {
+ setSample(j, i, b, fArray[Offset++], data);
+ }
+ }
+ }
+
+ /**
+ * Sets the samples in the specified band for the specified rectangle
+ * of pixels from a double array containing one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param b The band to set.
+ * @param dArray The input samples in a double array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getSamples(int, int, int, int, int, double[], DataBuffer)
+ *
+ * @throws NullPointerException if dArray or data is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if dArray is too small to
+ * hold the input.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ double dArray[], DataBuffer data) {
+ int Offset=0;
+
+ for (int i=y; i<(y+h); i++) {
+ for (int j=x; j<(x+w); j++) {
+ setSample(j, i, b, dArray[Offset++], data);
+ }
+ }
+ }
+
+ /**
+ * Creates a SampleModel which describes data in this SampleModel's
+ * format, but with a different width and height.
+ * @param w the width of the image data
+ * @param h the height of the image data
+ * @return a <code>SampleModel</code> describing the same image
+ * data as this <code>SampleModel</code>, but with a
+ * different size.
+ */
+ public abstract SampleModel createCompatibleSampleModel(int w, int h);
+
+ /**
+ * Creates a new SampleModel
+ * with a subset of the bands of this
+ * SampleModel.
+ * @param bands the subset of bands of this <code>SampleModel</code>
+ * @return a <code>SampleModel</code> with a subset of bands of this
+ * <code>SampleModel</code>.
+ */
+ public abstract SampleModel createSubsetSampleModel(int bands[]);
+
+ /**
+ * Creates a DataBuffer that corresponds to this SampleModel.
+ * The DataBuffer's width and height will match this SampleModel's.
+ * @return a <code>DataBuffer</code> corresponding to this
+ * <code>SampleModel</code>.
+ */
+ public abstract DataBuffer createDataBuffer();
+
+ /** Returns the size in bits of samples for all bands.
+ * @return the size of samples for all bands.
+ */
+ public abstract int[] getSampleSize();
+
+ /** Returns the size in bits of samples for the specified band.
+ * @param band the specified band
+ * @return the size of the samples of the specified band.
+ */
+ public abstract int getSampleSize(int band);
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/SinglePixelPackedSampleModel.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,805 @@
+/*
+ * Portions Copyright 1997-2001 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+
+import java.util.Arrays;
+
+/**
+ * This class represents pixel data packed such that the N samples which make
+ * up a single pixel are stored in a single data array element, and each data
+ * data array element holds samples for only one pixel.
+ * This class supports
+ * {@link DataBuffer#TYPE_BYTE TYPE_BYTE},
+ * {@link DataBuffer#TYPE_USHORT TYPE_USHORT},
+ * {@link DataBuffer#TYPE_INT TYPE_INT} data types.
+ * All data array elements reside
+ * in the first bank of a DataBuffer. Accessor methods are provided so
+ * that the image data can be manipulated directly. Scanline stride is the
+ * number of data array elements between a given sample and the corresponding
+ * sample in the same column of the next scanline. Bit masks are the masks
+ * required to extract the samples representing the bands of the pixel.
+ * Bit offsets are the offsets in bits into the data array
+ * element of the samples representing the bands of the pixel.
+ * <p>
+ * The following code illustrates extracting the bits of the sample
+ * representing band <code>b</code> for pixel <code>x,y</code>
+ * from DataBuffer <code>data</code>:
+ * <pre>
+ * int sample = data.getElem(y * scanlineStride + x);
+ * sample = (sample & bitMasks[b]) >>> bitOffsets[b];
+ * </pre>
+ */
+
+public class SinglePixelPackedSampleModel extends SampleModel
+{
+ /** Bit masks for all bands of the image data. */
+ private int bitMasks[];
+
+ /** Bit Offsets for all bands of the image data. */
+ private int bitOffsets[];
+
+ /** Bit sizes for all the bands of the image data. */
+ private int bitSizes[];
+
+ /** Maximum bit size. */
+ private int maxBitSize;
+
+ /** Line stride of the region of image data described by this
+ * SinglePixelPackedSampleModel.
+ */
+ private int scanlineStride;
+
+ private static native void initIDs();
+ static {
+ ColorModel.loadLibraries();
+ initIDs();
+ }
+
+ /**
+ * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands.
+ * Each sample is stored in a data array element in the position of
+ * its corresponding bit mask. Each bit mask must be contiguous and
+ * masks must not overlap.
+ * @param dataType The data type for storing samples.
+ * @param w The width (in pixels) of the region of the
+ * image data described.
+ * @param h The height (in pixels) of the region of the
+ * image data described.
+ * @param bitMasks The bit masks for all bands.
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * either <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>, or
+ * <code>DataBuffer.TYPE_INT</code>
+ */
+ public SinglePixelPackedSampleModel(int dataType, int w, int h,
+ int bitMasks[]) {
+ this(dataType, w, h, w, bitMasks);
+ if (dataType != DataBuffer.TYPE_BYTE &&
+ dataType != DataBuffer.TYPE_USHORT &&
+ dataType != DataBuffer.TYPE_INT) {
+ throw new IllegalArgumentException("Unsupported data type "+
+ dataType);
+ }
+ }
+
+ /**
+ * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands
+ * and a scanline stride equal to scanlineStride data array elements.
+ * Each sample is stored in a data array element in the position of
+ * its corresponding bit mask. Each bit mask must be contiguous and
+ * masks must not overlap.
+ * @param dataType The data type for storing samples.
+ * @param w The width (in pixels) of the region of
+ * image data described.
+ * @param h The height (in pixels) of the region of
+ * image data described.
+ * @param scanlineStride The line stride of the image data.
+ * @param bitMasks The bit masks for all bands.
+ * @throws IllegalArgumentException if <code>w</code> or
+ * <code>h</code> is not greater than 0
+ * @throws IllegalArgumentException if any mask in
+ * <code>bitMask</code> is not contiguous
+ * @throws IllegalArgumentException if <code>dataType</code> is not
+ * either <code>DataBuffer.TYPE_BYTE</code>,
+ * <code>DataBuffer.TYPE_USHORT</code>, or
+ * <code>DataBuffer.TYPE_INT</code>
+ */
+ public SinglePixelPackedSampleModel(int dataType, int w, int h,
+ int scanlineStride, int bitMasks[]) {
+ super(dataType, w, h, bitMasks.length);
+ if (dataType != DataBuffer.TYPE_BYTE &&
+ dataType != DataBuffer.TYPE_USHORT &&
+ dataType != DataBuffer.TYPE_INT) {
+ throw new IllegalArgumentException("Unsupported data type "+
+ dataType);
+ }
+ this.dataType = dataType;
+ this.bitMasks = (int[]) bitMasks.clone();
+ this.scanlineStride = scanlineStride;
+
+ this.bitOffsets = new int[numBands];
+ this.bitSizes = new int[numBands];
+
+ this.maxBitSize = 0;
+ for (int i=0; i<numBands; i++) {
+ int bitOffset = 0, bitSize = 0, mask;
+ mask = bitMasks[i];
+
+ if (mask != 0) {
+ while ((mask & 1) == 0) {
+ mask = mask >>> 1;
+ bitOffset++;
+ }
+ while ((mask & 1) == 1) {
+ mask = mask >>> 1;
+ bitSize++;
+ }
+ if (mask != 0) {
+ throw new IllegalArgumentException("Mask "+bitMasks[i]+
+ " must be contiguous");
+ }
+ }
+ bitOffsets[i] = bitOffset;
+ bitSizes[i] = bitSize;
+ if (bitSize > maxBitSize) {
+ maxBitSize = bitSize;
+ }
+ }
+ }
+
+ /**
+ * Returns the number of data elements needed to transfer one pixel
+ * via the getDataElements and setDataElements methods.
+ * For a SinglePixelPackedSampleModel, this is one.
+ */
+ public int getNumDataElements() {
+ return 1;
+ }
+
+ /**
+ * Returns the size of the buffer (in data array elements)
+ * needed for a data buffer that matches this
+ * SinglePixelPackedSampleModel.
+ */
+ private long getBufferSize() {
+ long size = scanlineStride * (height-1) + width;
+ return size;
+ }
+
+ /**
+ * Creates a new SinglePixelPackedSampleModel with the specified
+ * width and height. The new SinglePixelPackedSampleModel will have the
+ * same storage data type and bit masks as this
+ * SinglePixelPackedSampleModel.
+ * @param w the width of the resulting <code>SampleModel</code>
+ * @param h the height of the resulting <code>SampleModel</code>
+ * @return a <code>SinglePixelPackedSampleModel</code> with the
+ * specified width and height.
+ * @throws IllegalArgumentException if <code>w</code> or
+ * <code>h</code> is not greater than 0
+ */
+ public SampleModel createCompatibleSampleModel(int w, int h) {
+ SampleModel sampleModel = new SinglePixelPackedSampleModel(dataType, w, h,
+ bitMasks);
+ return sampleModel;
+ }
+
+ /**
+ * Creates a DataBuffer that corresponds to this
+ * SinglePixelPackedSampleModel. The DataBuffer's data type and size
+ * will be consistent with this SinglePixelPackedSampleModel. The
+ * DataBuffer will have a single bank.
+ */
+ public DataBuffer createDataBuffer() {
+ DataBuffer dataBuffer = null;
+
+ int size = (int)getBufferSize();
+ switch (dataType) {
+ case DataBuffer.TYPE_BYTE:
+ dataBuffer = new DataBufferByte(size);
+ break;
+ case DataBuffer.TYPE_USHORT:
+ dataBuffer = new DataBufferUShort(size);
+ break;
+ case DataBuffer.TYPE_INT:
+ dataBuffer = new DataBufferInt(size);
+ break;
+ }
+ return dataBuffer;
+ }
+
+ /** Returns the number of bits per sample for all bands. */
+ public int[] getSampleSize() {
+ int mask;
+ int sampleSize[] = new int [numBands];
+ for (int i=0; i<numBands; i++) {
+ sampleSize[i] = 0;
+ mask = bitMasks[i] >>> bitOffsets[i];
+ while ((mask & 1) != 0) {
+ sampleSize[i] ++;
+ mask = mask >>> 1;
+ }
+ }
+
+ return sampleSize;
+ }
+
+ /** Returns the number of bits per sample for the specified band. */
+ public int getSampleSize(int band) {
+ int sampleSize = 0;
+ int mask = bitMasks[band] >>> bitOffsets[band];
+ while ((mask & 1) != 0) {
+ sampleSize ++;
+ mask = mask >>> 1;
+ }
+
+ return sampleSize;
+ }
+
+ /** Returns the offset (in data array elements) of pixel (x,y).
+ * The data element containing pixel <code>x,y</code>
+ * can be retrieved from a DataBuffer <code>data</code> with a
+ * SinglePixelPackedSampleModel <code>sppsm</code> as:
+ * <pre>
+ * data.getElem(sppsm.getOffset(x, y));
+ * </pre>
+ * @param x the X coordinate of the specified pixel
+ * @param y the Y coordinate of the specified pixel
+ * @return the offset of the specified pixel.
+ */
+ public int getOffset(int x, int y) {
+ int offset = y * scanlineStride + x;
+ return offset;
+ }
+
+ /** Returns the bit offsets into the data array element representing
+ * a pixel for all bands.
+ * @return the bit offsets representing a pixel for all bands.
+ */
+ public int [] getBitOffsets() {
+ return (int[])bitOffsets.clone();
+ }
+
+ /** Returns the bit masks for all bands.
+ * @return the bit masks for all bands.
+ */
+ public int [] getBitMasks() {
+ return (int[])bitMasks.clone();
+ }
+
+ /** Returns the scanline stride of this SinglePixelPackedSampleModel.
+ * @return the scanline stride of this
+ * <code>SinglePixelPackedSampleModel</code>.
+ */
+ public int getScanlineStride() {
+ return scanlineStride;
+ }
+
+ /**
+ * This creates a new SinglePixelPackedSampleModel with a subset of the
+ * bands of this SinglePixelPackedSampleModel. The new
+ * SinglePixelPackedSampleModel can be used with any DataBuffer that the
+ * existing SinglePixelPackedSampleModel can be used with. The new
+ * SinglePixelPackedSampleModel/DataBuffer combination will represent
+ * an image with a subset of the bands of the original
+ * SinglePixelPackedSampleModel/DataBuffer combination.
+ * @exception RasterFormatException if the length of the bands argument is
+ * greater than the number of bands in
+ * the sample model.
+ */
+ public SampleModel createSubsetSampleModel(int bands[]) {
+ if (bands.length > numBands)
+ throw new RasterFormatException("There are only " +
+ numBands +
+ " bands");
+ int newBitMasks[] = new int[bands.length];
+ for (int i=0; i<bands.length; i++)
+ newBitMasks[i] = bitMasks[bands[i]];
+
+ return new SinglePixelPackedSampleModel(this.dataType, width, height,
+ this.scanlineStride, newBitMasks);
+ }
+
+ /**
+ * Returns data for a single pixel in a primitive array of type
+ * TransferType. For a SinglePixelPackedSampleModel, the array will
+ * have one element, and the type will be the same as the storage
+ * data type. Generally, obj
+ * should be passed in as null, so that the Object will be created
+ * automatically and will be of the right primitive data type.
+ * <p>
+ * The following code illustrates transferring data for one pixel from
+ * DataBuffer <code>db1</code>, whose storage layout is described by
+ * SinglePixelPackedSampleModel <code>sppsm1</code>, to
+ * DataBuffer <code>db2</code>, whose storage layout is described by
+ * SinglePixelPackedSampleModel <code>sppsm2</code>.
+ * The transfer will generally be more efficient than using
+ * getPixel/setPixel.
+ * <pre>
+ * SinglePixelPackedSampleModel sppsm1, sppsm2;
+ * DataBufferInt db1, db2;
+ * sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
+ * db1), db2);
+ * </pre>
+ * Using getDataElements/setDataElements to transfer between two
+ * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
+ * the same number of bands, corresponding bands have the same number of
+ * bits per sample, and the TransferTypes are the same.
+ * <p>
+ * If obj is non-null, it should be a primitive array of type TransferType.
+ * Otherwise, a ClassCastException is thrown. An
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds, or if obj is non-null and is not large enough to hold
+ * the pixel data.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param obj If non-null, a primitive array in which to return
+ * the pixel data.
+ * @param data The DataBuffer containing the image data.
+ * @return the data for the specified pixel.
+ * @see #setDataElements(int, int, Object, DataBuffer)
+ */
+ public Object getDataElements(int x, int y, Object obj, DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ int type = getTransferType();
+
+ switch(type) {
+
+ case DataBuffer.TYPE_BYTE:
+
+ byte[] bdata;
+
+ if (obj == null)
+ bdata = new byte[1];
+ else
+ bdata = (byte[])obj;
+
+ bdata[0] = (byte)data.getElem(y * scanlineStride + x);
+
+ obj = (Object)bdata;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+
+ short[] sdata;
+
+ if (obj == null)
+ sdata = new short[1];
+ else
+ sdata = (short[])obj;
+
+ sdata[0] = (short)data.getElem(y * scanlineStride + x);
+
+ obj = (Object)sdata;
+ break;
+
+ case DataBuffer.TYPE_INT:
+
+ int[] idata;
+
+ if (obj == null)
+ idata = new int[1];
+ else
+ idata = (int[])obj;
+
+ idata[0] = data.getElem(y * scanlineStride + x);
+
+ obj = (Object)idata;
+ break;
+ }
+
+ return obj;
+ }
+
+ /**
+ * Returns all samples in for the specified pixel in an int array.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param iArray If non-null, returns the samples in this array
+ * @param data The DataBuffer containing the image data.
+ * @return all samples for the specified pixel.
+ * @see #setPixel(int, int, int[], DataBuffer)
+ */
+ public int [] getPixel(int x, int y, int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int pixels[];
+ if (iArray == null) {
+ pixels = new int [numBands];
+ } else {
+ pixels = iArray;
+ }
+
+ int value = data.getElem(y * scanlineStride + x);
+ for (int i=0; i<numBands; i++) {
+ pixels[i] = (value & bitMasks[i]) >>> bitOffsets[i];
+ }
+ return pixels;
+ }
+
+ /**
+ * Returns all samples for the specified rectangle of pixels in
+ * an int array, one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param iArray If non-null, returns the samples in this array.
+ * @param data The DataBuffer containing the image data.
+ * @return all samples for the specified region of pixels.
+ * @see #setPixels(int, int, int, int, int[], DataBuffer)
+ */
+ public int[] getPixels(int x, int y, int w, int h,
+ int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int pixels[];
+ if (iArray != null) {
+ pixels = iArray;
+ } else {
+ pixels = new int [w*h*numBands];
+ }
+ int lineOffset = y*scanlineStride + x;
+ int dstOffset = 0;
+
+ for (int i = 0; i < h; i++) {
+ for (int j = 0; j < w; j++) {
+ int value = data.getElem(lineOffset+j);
+ for (int k=0; k < numBands; k++) {
+ pixels[dstOffset++] =
+ ((value & bitMasks[k]) >>> bitOffsets[k]);
+ }
+ }
+ lineOffset += scanlineStride;
+ }
+ return pixels;
+ }
+
+ /**
+ * Returns as int the sample in a specified band for the pixel
+ * located at (x,y).
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param b The band to return.
+ * @param data The DataBuffer containing the image data.
+ * @return the sample in a specified band for the specified
+ * pixel.
+ * @see #setSample(int, int, int, int, DataBuffer)
+ */
+ public int getSample(int x, int y, int b, DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int sample = data.getElem(y * scanlineStride + x);
+ return ((sample & bitMasks[b]) >>> bitOffsets[b]);
+ }
+
+ /**
+ * Returns the samples for a specified band for the specified rectangle
+ * of pixels in an int array, one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param b The band to return.
+ * @param iArray If non-null, returns the samples in this array.
+ * @param data The DataBuffer containing the image data.
+ * @return the samples for the specified band for the specified
+ * region of pixels.
+ * @see #setSamples(int, int, int, int, int, int[], DataBuffer)
+ */
+ public int[] getSamples(int x, int y, int w, int h, int b,
+ int iArray[], DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int samples[];
+ if (iArray != null) {
+ samples = iArray;
+ } else {
+ samples = new int [w*h];
+ }
+ int lineOffset = y*scanlineStride + x;
+ int dstOffset = 0;
+
+ for (int i = 0; i < h; i++) {
+ for (int j = 0; j < w; j++) {
+ int value = data.getElem(lineOffset+j);
+ samples[dstOffset++] =
+ ((value & bitMasks[b]) >>> bitOffsets[b]);
+ }
+ lineOffset += scanlineStride;
+ }
+ return samples;
+ }
+
+ /**
+ * Sets the data for a single pixel in the specified DataBuffer from a
+ * primitive array of type TransferType. For a
+ * SinglePixelPackedSampleModel, only the first element of the array
+ * will hold valid data, and the type of the array must be the same as
+ * the storage data type of the SinglePixelPackedSampleModel.
+ * <p>
+ * The following code illustrates transferring data for one pixel from
+ * DataBuffer <code>db1</code>, whose storage layout is described by
+ * SinglePixelPackedSampleModel <code>sppsm1</code>,
+ * to DataBuffer <code>db2</code>, whose storage layout is described by
+ * SinglePixelPackedSampleModel <code>sppsm2</code>.
+ * The transfer will generally be more efficient than using
+ * getPixel/setPixel.
+ * <pre>
+ * SinglePixelPackedSampleModel sppsm1, sppsm2;
+ * DataBufferInt db1, db2;
+ * sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
+ * db1), db2);
+ * </pre>
+ * Using getDataElements/setDataElements to transfer between two
+ * DataBuffer/SampleModel pairs is legitimate if the SampleModels have
+ * the same number of bands, corresponding bands have the same number of
+ * bits per sample, and the TransferTypes are the same.
+ * <p>
+ * obj must be a primitive array of type TransferType. Otherwise,
+ * a ClassCastException is thrown. An
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds, or if obj is not large enough to hold the pixel data.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param obj A primitive array containing pixel data.
+ * @param data The DataBuffer containing the image data.
+ * @see #getDataElements(int, int, Object, DataBuffer)
+ */
+ public void setDataElements(int x, int y, Object obj, DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ int type = getTransferType();
+
+ switch(type) {
+
+ case DataBuffer.TYPE_BYTE:
+
+ byte[] barray = (byte[])obj;
+ data.setElem(y*scanlineStride+x, ((int)barray[0])&0xff);
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+
+ short[] sarray = (short[])obj;
+ data.setElem(y*scanlineStride+x, ((int)sarray[0])&0xffff);
+ break;
+
+ case DataBuffer.TYPE_INT:
+
+ int[] iarray = (int[])obj;
+ data.setElem(y*scanlineStride+x, iarray[0]);
+ break;
+ }
+ }
+
+ /**
+ * Sets a pixel in the DataBuffer using an int array of samples for input.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param iArray The input samples in an int array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getPixel(int, int, int[], DataBuffer)
+ */
+ public void setPixel(int x, int y,
+ int iArray[],
+ DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int lineOffset = y * scanlineStride + x;
+ int value = data.getElem(lineOffset);
+ for (int i=0; i < numBands; i++) {
+ value &= ~bitMasks[i];
+ value |= ((iArray[i] << bitOffsets[i]) & bitMasks[i]);
+ }
+ data.setElem(lineOffset, value);
+ }
+
+ /**
+ * Sets all samples for a rectangle of pixels from an int array containing
+ * one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param iArray The input samples in an int array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getPixels(int, int, int, int, int[], DataBuffer)
+ */
+ public void setPixels(int x, int y, int w, int h,
+ int iArray[], DataBuffer data) {
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ int lineOffset = y*scanlineStride + x;
+ int srcOffset = 0;
+
+ for (int i = 0; i < h; i++) {
+ for (int j = 0; j < w; j++) {
+ int value = data.getElem(lineOffset+j);
+ for (int k=0; k < numBands; k++) {
+ value &= ~bitMasks[k];
+ int srcValue = iArray[srcOffset++];
+ value |= ((srcValue << bitOffsets[k])
+ & bitMasks[k]);
+ }
+ data.setElem(lineOffset+j, value);
+ }
+ lineOffset += scanlineStride;
+ }
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the DataBuffer using an int for input.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param b The band to set.
+ * @param s The input sample as an int.
+ * @param data The DataBuffer containing the image data.
+ * @see #getSample(int, int, int, DataBuffer)
+ */
+ public void setSample(int x, int y, int b, int s,
+ DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int value = data.getElem(y*scanlineStride + x);
+ value &= ~bitMasks[b];
+ value |= (s << bitOffsets[b]) & bitMasks[b];
+ data.setElem(y*scanlineStride + x,value);
+ }
+
+ /**
+ * Sets the samples in the specified band for the specified rectangle
+ * of pixels from an int array containing one sample per array element.
+ * ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w The width of the pixel rectangle.
+ * @param h The height of the pixel rectangle.
+ * @param b The band to set.
+ * @param iArray The input samples in an int array.
+ * @param data The DataBuffer containing the image data.
+ * @see #getSamples(int, int, int, int, int, int[], DataBuffer)
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ int iArray[], DataBuffer data) {
+ // Bounds check for 'b' will be performed automatically
+ if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+ int lineOffset = y*scanlineStride + x;
+ int srcOffset = 0;
+
+ for (int i = 0; i < h; i++) {
+ for (int j = 0; j < w; j++) {
+ int value = data.getElem(lineOffset+j);
+ value &= ~bitMasks[b];
+ int sample = iArray[srcOffset++];
+ value |= ((int)sample << bitOffsets[b]) & bitMasks[b];
+ data.setElem(lineOffset+j,value);
+ }
+ lineOffset += scanlineStride;
+ }
+ }
+
+ public boolean equals(Object o) {
+ if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) {
+ return false;
+ }
+
+ SinglePixelPackedSampleModel that = (SinglePixelPackedSampleModel)o;
+ return this.width == that.width &&
+ this.height == that.height &&
+ this.numBands == that.numBands &&
+ this.dataType == that.dataType &&
+ Arrays.equals(this.bitMasks, that.bitMasks) &&
+ Arrays.equals(this.bitOffsets, that.bitOffsets) &&
+ Arrays.equals(this.bitSizes, that.bitSizes) &&
+ this.maxBitSize == that.maxBitSize &&
+ this.scanlineStride == that.scanlineStride;
+ }
+
+ // If we implement equals() we must also implement hashCode
+ public int hashCode() {
+ int hash = 0;
+ hash = width;
+ hash <<= 8;
+ hash ^= height;
+ hash <<= 8;
+ hash ^= numBands;
+ hash <<= 8;
+ hash ^= dataType;
+ hash <<= 8;
+ for (int i = 0; i < bitMasks.length; i++) {
+ hash ^= bitMasks[i];
+ hash <<= 8;
+ }
+ for (int i = 0; i < bitOffsets.length; i++) {
+ hash ^= bitOffsets[i];
+ hash <<= 8;
+ }
+ for (int i = 0; i < bitSizes.length; i++) {
+ hash ^= bitSizes[i];
+ hash <<= 8;
+ }
+ hash ^= maxBitSize;
+ hash <<= 8;
+ hash ^= scanlineStride;
+ return hash;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/WritableRaster.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,741 @@
+/*
+ * Portions Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+import java.awt.Rectangle;
+import java.awt.Point;
+
+/**
+ * This class extends Raster to provide pixel writing capabilities.
+ * Refer to the class comment for Raster for descriptions of how
+ * a Raster stores pixels.
+ *
+ * <p> The constructors of this class are protected. To instantiate
+ * a WritableRaster, use one of the createWritableRaster factory methods
+ * in the Raster class.
+ */
+public class WritableRaster extends Raster {
+
+ /**
+ * Constructs a WritableRaster with the given SampleModel. The
+ * WritableRaster's upper left corner is origin and it is the
+ * same size as the SampleModel. A DataBuffer large enough to
+ * describe the WritableRaster is automatically created.
+ * @param sampleModel The SampleModel that specifies the layout.
+ * @param origin The Point that specifies the origin.
+ * @throws RasterFormatException if computing either
+ * <code>origin.x + sampleModel.getWidth()</code> or
+ * <code>origin.y + sampleModel.getHeight()</code> results
+ * in integer overflow
+ */
+ protected WritableRaster(SampleModel sampleModel,
+ Point origin) {
+ this(sampleModel,
+ sampleModel.createDataBuffer(),
+ new Rectangle(origin.x,
+ origin.y,
+ sampleModel.getWidth(),
+ sampleModel.getHeight()),
+ origin,
+ null);
+ }
+
+ /**
+ * Constructs a WritableRaster with the given SampleModel and DataBuffer.
+ * The WritableRaster's upper left corner is origin and it is the same
+ * size as the SampleModel. The DataBuffer is not initialized and must
+ * be compatible with SampleModel.
+ * @param sampleModel The SampleModel that specifies the layout.
+ * @param dataBuffer The DataBuffer that contains the image data.
+ * @param origin The Point that specifies the origin.
+ * @throws RasterFormatException if computing either
+ * <code>origin.x + sampleModel.getWidth()</code> or
+ * <code>origin.y + sampleModel.getHeight()</code> results
+ * in integer overflow
+ */
+ protected WritableRaster(SampleModel sampleModel,
+ DataBuffer dataBuffer,
+ Point origin) {
+ this(sampleModel,
+ dataBuffer,
+ new Rectangle(origin.x,
+ origin.y,
+ sampleModel.getWidth(),
+ sampleModel.getHeight()),
+ origin,
+ null);
+ }
+
+ /**
+ * Constructs a WritableRaster with the given SampleModel, DataBuffer,
+ * and parent. aRegion specifies the bounding rectangle of the new
+ * Raster. When translated into the base Raster's coordinate
+ * system, aRegion must be contained by the base Raster.
+ * (The base Raster is the Raster's ancestor which has no parent.)
+ * sampleModelTranslate specifies the sampleModelTranslateX and
+ * sampleModelTranslateY values of the new Raster.
+ *
+ * Note that this constructor should generally be called by other
+ * constructors or create methods, it should not be used directly.
+ * @param sampleModel The SampleModel that specifies the layout.
+ * @param dataBuffer The DataBuffer that contains the image data.
+ * @param aRegion The Rectangle that specifies the image area.
+ * @param sampleModelTranslate The Point that specifies the translation
+ * from SampleModel to Raster coordinates.
+ * @param parent The parent (if any) of this raster.
+ * @throws RasterFormatException if <code>aRegion</code> has width
+ * or height less than or equal to zero, or computing either
+ * <code>aRegion.x + aRegion.width</code> or
+ * <code>aRegion.y + aRegion.height</code> results in integer
+ * overflow
+ */
+ protected WritableRaster(SampleModel sampleModel,
+ DataBuffer dataBuffer,
+ Rectangle aRegion,
+ Point sampleModelTranslate,
+ WritableRaster parent){
+ super(sampleModel,dataBuffer,aRegion,sampleModelTranslate,parent);
+ }
+
+ /** Returns the parent WritableRaster (if any) of this WritableRaster,
+ * or else null.
+ * @return the parent of this <code>WritableRaster</code>, or
+ * <code>null</code>.
+ */
+ public WritableRaster getWritableParent() {
+ return (WritableRaster)parent;
+ }
+
+ /**
+ * Create a WritableRaster with the same size, SampleModel and DataBuffer
+ * as this one, but with a different location. The new WritableRaster
+ * will possess a reference to the current WritableRaster, accessible
+ * through its getParent() and getWritableParent() methods.
+ *
+ * @param childMinX X coord of the upper left corner of the new Raster.
+ * @param childMinY Y coord of the upper left corner of the new Raster.
+ * @return a <code>WritableRaster</code> the same as this one except
+ * for the specified location.
+ * @throws RasterFormatException if computing either
+ * <code>childMinX + this.getWidth()</code> or
+ * <code>childMinY + this.getHeight()</code> results in integer
+ * overflow
+ */
+ public WritableRaster createWritableTranslatedChild(int childMinX,
+ int childMinY) {
+ return createWritableChild(minX,minY,width,height,
+ childMinX,childMinY,null);
+ }
+
+ /**
+ * Returns a new WritableRaster which shares all or part of this
+ * WritableRaster's DataBuffer. The new WritableRaster will
+ * possess a reference to the current WritableRaster, accessible
+ * through its getParent() and getWritableParent() methods.
+ *
+ * <p> The parentX, parentY, width and height parameters form a
+ * Rectangle in this WritableRaster's coordinate space, indicating
+ * the area of pixels to be shared. An error will be thrown if
+ * this Rectangle is not contained with the bounds of the current
+ * WritableRaster.
+ *
+ * <p> The new WritableRaster may additionally be translated to a
+ * different coordinate system for the plane than that used by the current
+ * WritableRaster. The childMinX and childMinY parameters give
+ * the new (x, y) coordinate of the upper-left pixel of the
+ * returned WritableRaster; the coordinate (childMinX, childMinY)
+ * in the new WritableRaster will map to the same pixel as the
+ * coordinate (parentX, parentY) in the current WritableRaster.
+ *
+ * <p> The new WritableRaster may be defined to contain only a
+ * subset of the bands of the current WritableRaster, possibly
+ * reordered, by means of the bandList parameter. If bandList is
+ * null, it is taken to include all of the bands of the current
+ * WritableRaster in their current order.
+ *
+ * <p> To create a new WritableRaster that contains a subregion of
+ * the current WritableRaster, but shares its coordinate system
+ * and bands, this method should be called with childMinX equal to
+ * parentX, childMinY equal to parentY, and bandList equal to
+ * null.
+ *
+ * @param parentX X coordinate of the upper left corner in this
+ * WritableRaster's coordinates.
+ * @param parentY Y coordinate of the upper left corner in this
+ * WritableRaster's coordinates.
+ * @param w Width of the region starting at (parentX, parentY).
+ * @param h Height of the region starting at (parentX, parentY).
+ * @param childMinX X coordinate of the upper left corner of
+ * the returned WritableRaster.
+ * @param childMinY Y coordinate of the upper left corner of
+ * the returned WritableRaster.
+ * @param bandList Array of band indices, or null to use all bands.
+ * @return a <code>WritableRaster</code> sharing all or part of the
+ * <code>DataBuffer</code> of this <code>WritableRaster</code>.
+ * @exception RasterFormatException if the subregion is outside of the
+ * raster bounds.
+ * @throws RasterFormatException if <code>w</code> or
+ * <code>h</code>
+ * is less than or equal to zero, or computing any of
+ * <code>parentX + w</code>, <code>parentY + h</code>,
+ * <code>childMinX + w</code>, or
+ * <code>childMinY + h</code> results in integer
+ * overflow
+ */
+ public WritableRaster createWritableChild(int parentX, int parentY,
+ int w, int h,
+ int childMinX, int childMinY,
+ int bandList[]) {
+ if (parentX < this.minX) {
+ throw new RasterFormatException("parentX lies outside raster");
+ }
+ if (parentY < this.minY) {
+ throw new RasterFormatException("parentY lies outside raster");
+ }
+ if ((parentX+w < parentX) || (parentX+w > this.width + this.minX)) {
+ throw new RasterFormatException("(parentX + width) is outside raster");
+ }
+ if ((parentY+h < parentY) || (parentY+h > this.height + this.minY)) {
+ throw new RasterFormatException("(parentY + height) is outside raster");
+ }
+
+ SampleModel sm;
+ // Note: the SampleModel for the child Raster should have the same
+ // width and height as that for the parent, since it represents
+ // the physical layout of the pixel data. The child Raster's width
+ // and height represent a "virtual" view of the pixel data, so
+ // they may be different than those of the SampleModel.
+ if (bandList != null) {
+ sm = sampleModel.createSubsetSampleModel(bandList);
+ }
+ else {
+ sm = sampleModel;
+ }
+
+ int deltaX = childMinX - parentX;
+ int deltaY = childMinY - parentY;
+
+ return new WritableRaster(sm,
+ getDataBuffer(),
+ new Rectangle(childMinX,childMinY,
+ w, h),
+ new Point(sampleModelTranslateX+deltaX,
+ sampleModelTranslateY+deltaY),
+ this);
+ }
+
+ /**
+ * Sets the data for a single pixel from a
+ * primitive array of type TransferType. For image data supported by
+ * the Java 2D(tm) API, this will be one of DataBuffer.TYPE_BYTE,
+ * DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
+ * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. Data in the array
+ * may be in a packed format, thus increasing efficiency for data
+ * transfers.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds, or if inData is not large enough to hold the pixel data.
+ * However, explicit bounds checking is not guaranteed.
+ * A ClassCastException will be thrown if the input object is not null
+ * and references anything other than an array of TransferType.
+ * @see java.awt.image.SampleModel#setDataElements(int, int, Object, DataBuffer)
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param inData An object reference to an array of type defined by
+ * getTransferType() and length getNumDataElements()
+ * containing the pixel data to place at x,y.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if inData is too small to hold the input.
+ */
+ public void setDataElements(int x, int y, Object inData) {
+ sampleModel.setDataElements(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ inData, dataBuffer);
+ }
+
+ /**
+ * Sets the data for a rectangle of pixels from an input Raster.
+ * The input Raster must be compatible with this WritableRaster
+ * in that they must have the same number of bands, corresponding bands
+ * must have the same number of bits per sample, the TransferTypes
+ * and NumDataElements must be the same, and the packing used by
+ * the getDataElements/setDataElements must be identical.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param inRaster Raster containing data to place at x,y.
+ *
+ * @throws NullPointerException if inRaster is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds.
+ */
+ public void setDataElements(int x, int y, Raster inRaster) {
+ int dstOffX = x+inRaster.getMinX();
+ int dstOffY = y+inRaster.getMinY();
+ int width = inRaster.getWidth();
+ int height = inRaster.getHeight();
+ if ((dstOffX < this.minX) || (dstOffY < this.minY) ||
+ (dstOffX + width > this.minX + this.width) ||
+ (dstOffY + height > this.minY + this.height)) {
+ throw new ArrayIndexOutOfBoundsException
+ ("Coordinate out of bounds!");
+ }
+
+ int srcOffX = inRaster.getMinX();
+ int srcOffY = inRaster.getMinY();
+ Object tdata = null;
+
+ for (int startY=0; startY < height; startY++) {
+ tdata = inRaster.getDataElements(srcOffX, srcOffY+startY,
+ width, 1, tdata);
+ setDataElements(dstOffX, dstOffY+startY,
+ width, 1, tdata);
+ }
+ }
+
+ /**
+ * Sets the data for a rectangle of pixels from a
+ * primitive array of type TransferType. For image data supported by
+ * the Java 2D API, this will be one of DataBuffer.TYPE_BYTE,
+ * DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT,
+ * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. Data in the array
+ * may be in a packed format, thus increasing efficiency for data
+ * transfers.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds, or if inData is not large enough to hold the pixel data.
+ * However, explicit bounds checking is not guaranteed.
+ * A ClassCastException will be thrown if the input object is not null
+ * and references anything other than an array of TransferType.
+ * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, Object, DataBuffer)
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w Width of the pixel rectangle.
+ * @param h Height of the pixel rectangle.
+ * @param inData An object reference to an array of type defined by
+ * getTransferType() and length w*h*getNumDataElements()
+ * containing the pixel data to place between x,y and
+ * x+w-1, y+h-1.
+ *
+ * @throws NullPointerException if inData is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if inData is too small to hold the input.
+ */
+ public void setDataElements(int x, int y, int w, int h, Object inData) {
+ sampleModel.setDataElements(x-sampleModelTranslateX,
+ y-sampleModelTranslateY,
+ w,h,inData,dataBuffer);
+ }
+
+ /**
+ * Copies pixels from Raster srcRaster to this WritableRaster. Each pixel
+ * in srcRaster is copied to the same x,y address in this raster, unless
+ * the address falls outside the bounds of this raster. srcRaster
+ * must have the same number of bands as this WritableRaster. The
+ * copy is a simple copy of source samples to the corresponding destination
+ * samples.
+ * <p>
+ * If all samples of both source and destination Rasters are of
+ * integral type and less than or equal to 32 bits in size, then calling
+ * this method is equivalent to executing the following code for all
+ * <code>x,y</code> addresses valid in both Rasters.
+ * <pre>
+ * Raster srcRaster;
+ * WritableRaster dstRaster;
+ * for (int b = 0; b < srcRaster.getNumBands(); b++) {
+ * dstRaster.setSample(x, y, b, srcRaster.getSample(x, y, b));
+ * }
+ * </pre>
+ * Thus, when copying an integral type source to an integral type
+ * destination, if the source sample size is greater than the destination
+ * sample size for a particular band, the high order bits of the source
+ * sample are truncated. If the source sample size is less than the
+ * destination size for a particular band, the high order bits of the
+ * destination are zero-extended or sign-extended depending on whether
+ * srcRaster's SampleModel treats the sample as a signed or unsigned
+ * quantity.
+ * <p>
+ * When copying a float or double source to an integral type destination,
+ * each source sample is cast to the destination type. When copying an
+ * integral type source to a float or double destination, the source
+ * is first converted to a 32-bit int (if necessary), using the above
+ * rules for integral types, and then the int is cast to float or
+ * double.
+ * <p>
+ * @param srcRaster The Raster from which to copy pixels.
+ *
+ * @throws NullPointerException if srcRaster is null.
+ */
+ public void setRect(Raster srcRaster) {
+ setRect(0,0,srcRaster);
+ }
+
+ /**
+ * Copies pixels from Raster srcRaster to this WritableRaster.
+ * For each (x, y) address in srcRaster, the corresponding pixel
+ * is copied to address (x+dx, y+dy) in this WritableRaster,
+ * unless (x+dx, y+dy) falls outside the bounds of this raster.
+ * srcRaster must have the same number of bands as this WritableRaster.
+ * The copy is a simple copy of source samples to the corresponding
+ * destination samples. For details, see
+ * {@link WritableRaster#setRect(Raster)}.
+ *
+ * @param dx The X translation factor from src space to dst space
+ * of the copy.
+ * @param dy The Y translation factor from src space to dst space
+ * of the copy.
+ * @param srcRaster The Raster from which to copy pixels.
+ *
+ * @throws NullPointerException if srcRaster is null.
+ */
+ public void setRect(int dx, int dy, Raster srcRaster) {
+ int width = srcRaster.getWidth();
+ int height = srcRaster.getHeight();
+ int srcOffX = srcRaster.getMinX();
+ int srcOffY = srcRaster.getMinY();
+ int dstOffX = dx+srcOffX;
+ int dstOffY = dy+srcOffY;
+
+ // Clip to this raster
+ if (dstOffX < this.minX) {
+ int skipX = this.minX - dstOffX;
+ width -= skipX;
+ srcOffX += skipX;
+ dstOffX = this.minX;
+ }
+ if (dstOffY < this.minY) {
+ int skipY = this.minY - dstOffY;
+ height -= skipY;
+ srcOffY += skipY;
+ dstOffY = this.minY;
+ }
+ if (dstOffX+width > this.minX+this.width) {
+ width = this.minX + this.width - dstOffX;
+ }
+ if (dstOffY+height > this.minY+this.height) {
+ height = this.minY + this.height - dstOffY;
+ }
+
+ if (width <= 0 || height <= 0) {
+ return;
+ }
+
+ switch (srcRaster.getSampleModel().getDataType()) {
+ case DataBuffer.TYPE_BYTE:
+ case DataBuffer.TYPE_SHORT:
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_INT:
+ int[] iData = null;
+ for (int startY=0; startY < height; startY++) {
+ // Grab one scanline at a time
+ iData =
+ srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
+ iData);
+ setPixels(dstOffX, dstOffY+startY, width, 1, iData);
+ }
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+ float[] fData = null;
+ for (int startY=0; startY < height; startY++) {
+ fData =
+ srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
+ fData);
+ setPixels(dstOffX, dstOffY+startY, width, 1, fData);
+ }
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+ double[] dData = null;
+ for (int startY=0; startY < height; startY++) {
+ // Grab one scanline at a time
+ dData =
+ srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1,
+ dData);
+ setPixels(dstOffX, dstOffY+startY, width, 1, dData);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Sets a pixel in the DataBuffer using an int array of samples for input.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param iArray The input samples in a int array.
+ *
+ * @throws NullPointerException if iArray is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if iArray is too small to hold the input.
+ */
+ public void setPixel(int x, int y, int iArray[]) {
+ sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
+ iArray,dataBuffer);
+ }
+
+ /**
+ * Sets a pixel in the DataBuffer using a float array of samples for input.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param fArray The input samples in a float array.
+ *
+ * @throws NullPointerException if fArray is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if fArray is too small to hold the input.
+ */
+ public void setPixel(int x, int y, float fArray[]) {
+ sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
+ fArray,dataBuffer);
+ }
+
+ /**
+ * Sets a pixel in the DataBuffer using a double array of samples for input.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param dArray The input samples in a double array.
+ *
+ * @throws NullPointerException if dArray is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if dArray is too small to hold the input.
+ */
+ public void setPixel(int x, int y, double dArray[]) {
+ sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY,
+ dArray,dataBuffer);
+ }
+
+ /**
+ * Sets all samples for a rectangle of pixels from an int array containing
+ * one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w Width of the pixel rectangle.
+ * @param h Height of the pixel rectangle.
+ * @param iArray The input int pixel array.
+ *
+ * @throws NullPointerException if iArray is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if iArray is too small to hold the input.
+ */
+ public void setPixels(int x, int y, int w, int h, int iArray[]) {
+ sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
+ w,h,iArray,dataBuffer);
+ }
+
+ /**
+ * Sets all samples for a rectangle of pixels from a float array containing
+ * one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w Width of the pixel rectangle.
+ * @param h Height of the pixel rectangle.
+ * @param fArray The input float pixel array.
+ *
+ * @throws NullPointerException if fArray is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if fArray is too small to hold the input.
+ */
+ public void setPixels(int x, int y, int w, int h, float fArray[]) {
+ sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
+ w,h,fArray,dataBuffer);
+ }
+
+ /**
+ * Sets all samples for a rectangle of pixels from a double array containing
+ * one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w Width of the pixel rectangle.
+ * @param h Height of the pixel rectangle.
+ * @param dArray The input double pixel array.
+ *
+ * @throws NullPointerException if dArray is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates are not
+ * in bounds, or if dArray is too small to hold the input.
+ */
+ public void setPixels(int x, int y, int w, int h, double dArray[]) {
+ sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY,
+ w,h,dArray,dataBuffer);
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the DataBuffer using an int for input.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param b The band to set.
+ * @param s The input sample.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public void setSample(int x, int y, int b, int s) {
+ sampleModel.setSample(x-sampleModelTranslateX,
+ y-sampleModelTranslateY, b, s,
+ dataBuffer);
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the DataBuffer using a float for input.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param b The band to set.
+ * @param s The input sample as a float.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public void setSample(int x, int y, int b, float s){
+ sampleModel.setSample(x-sampleModelTranslateX,y-sampleModelTranslateY,
+ b,s,dataBuffer);
+ }
+
+ /**
+ * Sets a sample in the specified band for the pixel located at (x,y)
+ * in the DataBuffer using a double for input.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the pixel location.
+ * @param y The Y coordinate of the pixel location.
+ * @param b The band to set.
+ * @param s The input sample as a double.
+ *
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds.
+ */
+ public void setSample(int x, int y, int b, double s){
+ sampleModel.setSample(x-sampleModelTranslateX,y-sampleModelTranslateY,
+ b,s,dataBuffer);
+ }
+
+ /**
+ * Sets the samples in the specified band for the specified rectangle
+ * of pixels from an int array containing one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w Width of the pixel rectangle.
+ * @param h Height of the pixel rectangle.
+ * @param b The band to set.
+ * @param iArray The input int sample array.
+ *
+ * @throws NullPointerException if iArray is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if iArray is too small to
+ * hold the input.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ int iArray[]) {
+ sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY,
+ w,h,b,iArray,dataBuffer);
+ }
+
+ /**
+ * Sets the samples in the specified band for the specified rectangle
+ * of pixels from a float array containing one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w Width of the pixel rectangle.
+ * @param h Height of the pixel rectangle.
+ * @param b The band to set.
+ * @param fArray The input float sample array.
+ *
+ * @throws NullPointerException if fArray is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if fArray is too small to
+ * hold the input.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ float fArray[]) {
+ sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY,
+ w,h,b,fArray,dataBuffer);
+ }
+
+ /**
+ * Sets the samples in the specified band for the specified rectangle
+ * of pixels from a double array containing one sample per array element.
+ * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are
+ * not in bounds.
+ * However, explicit bounds checking is not guaranteed.
+ * @param x The X coordinate of the upper left pixel location.
+ * @param y The Y coordinate of the upper left pixel location.
+ * @param w Width of the pixel rectangle.
+ * @param h Height of the pixel rectangle.
+ * @param b The band to set.
+ * @param dArray The input double sample array.
+ *
+ * @throws NullPointerException if dArray is null.
+ * @throws ArrayIndexOutOfBoundsException if the coordinates or
+ * the band index are not in bounds, or if dArray is too small to
+ * hold the input.
+ */
+ public void setSamples(int x, int y, int w, int h, int b,
+ double dArray[]) {
+ sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY,
+ w,h,b,dArray,dataBuffer);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/WritableRenderedImage.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,151 @@
+/*
+ * Portions Copyright 1997-2000 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ****************************************************************
+ ******************************************************************
+ ******************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997
+ *** As an unpublished work pursuant to Title 17 of the United
+ *** States Code. All rights reserved.
+ ******************************************************************
+ ******************************************************************
+ ******************************************************************/
+
+package java.awt.image;
+import java.awt.Point;
+
+/**
+ * WriteableRenderedImage is a common interface for objects which
+ * contain or can produce image data in the form of Rasters and
+ * which can be modified and/or written over. The image
+ * data may be stored/produced as a single tile or a regular array
+ * of tiles.
+ * <p>
+ * WritableRenderedImage provides notification to other interested
+ * objects when a tile is checked out for writing (via the
+ * getWritableTile method) and when the last writer of a particular
+ * tile relinquishes its access (via a call to releaseWritableTile).
+ * Additionally, it allows any caller to determine whether any tiles
+ * are currently checked out (via hasTileWriters), and to obtain a
+ * list of such tiles (via getWritableTileIndices, in the form of a Vector
+ * of Point objects).
+ * <p>
+ * Objects wishing to be notified of changes in tile writability must
+ * implement the TileObserver interface, and are added by a
+ * call to addTileObserver. Multiple calls to
+ * addTileObserver for the same object will result in multiple
+ * notifications. An existing observer may reduce its notifications
+ * by calling removeTileObserver; if the observer had no
+ * notifications the operation is a no-op.
+ * <p>
+ * It is necessary for a WritableRenderedImage to ensure that
+ * notifications occur only when the first writer acquires a tile and
+ * the last writer releases it.
+ *
+ */
+
+public interface WritableRenderedImage extends RenderedImage
+{
+
+ /**
+ * Adds an observer. If the observer is already present,
+ * it will receive multiple notifications.
+ * @param to the specified <code>TileObserver</code>
+ */
+ public void addTileObserver(TileObserver to);
+
+ /**
+ * Removes an observer. If the observer was not registered,
+ * nothing happens. If the observer was registered for multiple
+ * notifications, it will now be registered for one fewer.
+ * @param to the specified <code>TileObserver</code>
+ */
+ public void removeTileObserver(TileObserver to);
+
+ /**
+ * Checks out a tile for writing.
+ *
+ * The WritableRenderedImage is responsible for notifying all
+ * of its TileObservers when a tile goes from having
+ * no writers to having one writer.
+ *
+ * @param tileX the X index of the tile.
+ * @param tileY the Y index of the tile.
+ * @return a writable tile.
+ */
+ public WritableRaster getWritableTile(int tileX, int tileY);
+
+ /**
+ * Relinquishes the right to write to a tile. If the caller
+ * continues to write to the tile, the results are undefined.
+ * Calls to this method should only appear in matching pairs
+ * with calls to getWritableTile; any other use will lead
+ * to undefined results.
+ *
+ * The WritableRenderedImage is responsible for notifying all of
+ * its TileObservers when a tile goes from having one writer
+ * to having no writers.
+ *
+ * @param tileX the X index of the tile.
+ * @param tileY the Y index of the tile.
+ */
+ public void releaseWritableTile(int tileX, int tileY);
+
+ /**
+ * Returns whether a tile is currently checked out for writing.
+ *
+ * @param tileX the X index of the tile.
+ * @param tileY the Y index of the tile.
+ * @return <code>true</code> if specified tile is checked out
+ * for writing; <code>false</code> otherwise.
+ */
+ public boolean isTileWritable(int tileX, int tileY);
+
+ /**
+ * Returns an array of Point objects indicating which tiles
+ * are checked out for writing. Returns null if none are
+ * checked out.
+ * @return an array containing the locations of tiles that are
+ * checked out for writing.
+ */
+ public Point[] getWritableTileIndices();
+
+ /**
+ * Returns whether any tile is checked out for writing.
+ * Semantically equivalent to (getWritableTileIndices() != null).
+ * @return <code>true</code> if any tiles are checked out for
+ * writing; <code>false</code> otherwise.
+ */
+ public boolean hasTileWriters();
+
+ /**
+ * Sets a rect of the image to the contents of the Raster r, which is
+ * assumed to be in the same coordinate space as the WritableRenderedImage.
+ * The operation is clipped to the bounds of the WritableRenderedImage.
+ * @param r the specified <code>Raster</code>
+ */
+ public void setData(Raster r);
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/renderable/ContextualRenderedImageFactory.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,143 @@
+/*
+ * Portions Copyright 1998-2000 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.image.renderable;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.RenderedImage;
+
+/**
+ * ContextualRenderedImageFactory provides an interface for the
+ * functionality that may differ between instances of
+ * RenderableImageOp. Thus different operations on RenderableImages
+ * may be performed by a single class such as RenderedImageOp through
+ * the use of multiple instances of ContextualRenderedImageFactory.
+ * The name ContextualRenderedImageFactory is commonly shortened to
+ * "CRIF."
+ *
+ * <p> All operations that are to be used in a rendering-independent
+ * chain must implement ContextualRenderedImageFactory.
+ *
+ * <p> Classes that implement this interface must provide a
+ * constructor with no arguments.
+ */
+public interface ContextualRenderedImageFactory extends RenderedImageFactory {
+
+ /**
+ * Maps the operation's output RenderContext into a RenderContext
+ * for each of the operation's sources. This is useful for
+ * operations that can be expressed in whole or in part simply as
+ * alterations in the RenderContext, such as an affine mapping, or
+ * operations that wish to obtain lower quality renderings of
+ * their sources in order to save processing effort or
+ * transmission bandwith. Some operations, such as blur, can also
+ * use this mechanism to avoid obtaining sources of higher quality
+ * than necessary.
+ *
+ * @param i the index of the source image.
+ * @param renderContext the RenderContext being applied to the operation.
+ * @param paramBlock a ParameterBlock containing the operation's
+ * sources and parameters.
+ * @param image the RenderableImage being rendered.
+ * @return a <code>RenderContext</code> for
+ * the source at the specified index of the parameters
+ * Vector contained in the specified ParameterBlock.
+ */
+ RenderContext mapRenderContext(int i,
+ RenderContext renderContext,
+ ParameterBlock paramBlock,
+ RenderableImage image);
+
+ /**
+ * Creates a rendering, given a RenderContext and a ParameterBlock
+ * containing the operation's sources and parameters. The output
+ * is a RenderedImage that takes the RenderContext into account to
+ * determine its dimensions and placement on the image plane.
+ * This method houses the "intelligence" that allows a
+ * rendering-independent operation to adapt to a specific
+ * RenderContext.
+ *
+ * @param renderContext The RenderContext specifying the rendering
+ * @param paramBlock a ParameterBlock containing the operation's
+ * sources and parameters
+ * @return a <code>RenderedImage</code> from the sources and parameters
+ * in the specified ParameterBlock and according to the
+ * rendering instructions in the specified RenderContext.
+ */
+ RenderedImage create(RenderContext renderContext,
+ ParameterBlock paramBlock);
+
+ /**
+ * Returns the bounding box for the output of the operation,
+ * performed on a given set of sources, in rendering-independent
+ * space. The bounds are returned as a Rectangle2D, that is, an
+ * axis-aligned rectangle with floating-point corner coordinates.
+ *
+ * @param paramBlock a ParameterBlock containing the operation's
+ * sources and parameters.
+ * @return a Rectangle2D specifying the rendering-independent
+ * bounding box of the output.
+ */
+ Rectangle2D getBounds2D(ParameterBlock paramBlock);
+
+ /**
+ * Gets the appropriate instance of the property specified by the name
+ * parameter. This method must determine which instance of a property to
+ * return when there are multiple sources that each specify the property.
+ *
+ * @param paramBlock a ParameterBlock containing the operation's
+ * sources and parameters.
+ * @param name a String naming the desired property.
+ * @return an object reference to the value of the property requested.
+ */
+ Object getProperty(ParameterBlock paramBlock, String name);
+
+ /**
+ * Returns a list of names recognized by getProperty.
+ * @return the list of property names.
+ */
+ String[] getPropertyNames();
+
+ /**
+ * Returns true if successive renderings (that is, calls to
+ * create(RenderContext, ParameterBlock)) with the same arguments
+ * may produce different results. This method may be used to
+ * determine whether an existing rendering may be cached and
+ * reused. It is always safe to return true.
+ * @return <code>true</code> if successive renderings with the
+ * same arguments might produce different results;
+ * <code>false</code> otherwise.
+ */
+ boolean isDynamic();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/renderable/RenderContext.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,272 @@
+/*
+ * Portions Copyright 1998-2000 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.image.renderable;
+import java.util.*;
+import java.awt.geom.*;
+import java.awt.*;
+import java.awt.image.*;
+
+/**
+ * A RenderContext encapsulates the information needed to produce a
+ * specific rendering from a RenderableImage. It contains the area to
+ * be rendered specified in rendering-independent terms, the
+ * resolution at which the rendering is to be performed, and hints
+ * used to control the rendering process.
+ *
+ * <p> Users create RenderContexts and pass them to the
+ * RenderableImage via the createRendering method. Most of the methods of
+ * RenderContexts are not meant to be used directly by applications,
+ * but by the RenderableImage and operator classes to which it is
+ * passed.
+ *
+ * <p> The AffineTransform parameter passed into and out of this class
+ * are cloned. The RenderingHints and Shape parameters are not
+ * necessarily cloneable and are therefore only reference copied.
+ * Altering RenderingHints or Shape instances that are in use by
+ * instances of RenderContext may have undesired side effects.
+ */
+public class RenderContext implements Cloneable {
+
+ /** Table of hints. May be null. */
+ RenderingHints hints;
+
+ /** Transform to convert user coordinates to device coordinates. */
+ AffineTransform usr2dev;
+
+ /** The area of interest. May be null. */
+ Shape aoi;
+
+ // Various constructors that allow different levels of
+ // specificity. If the Shape is missing the whole renderable area
+ // is assumed. If hints is missing no hints are assumed.
+
+ /**
+ * Constructs a RenderContext with a given transform.
+ * The area of interest is supplied as a Shape,
+ * and the rendering hints are supplied as a RenderingHints object.
+ *
+ * @param usr2dev an AffineTransform.
+ * @param aoi a Shape representing the area of interest.
+ * @param hints a RenderingHints object containing rendering hints.
+ */
+ public RenderContext(AffineTransform usr2dev,
+ Shape aoi,
+ RenderingHints hints) {
+ this.hints = hints;
+ this.aoi = aoi;
+ this.usr2dev = (AffineTransform)usr2dev.clone();
+ }
+
+ /**
+ * Constructs a RenderContext with a given transform.
+ * The area of interest is taken to be the entire renderable area.
+ * No rendering hints are used.
+ *
+ * @param usr2dev an AffineTransform.
+ */
+ public RenderContext(AffineTransform usr2dev) {
+ this(usr2dev, null, null);
+ }
+
+ /**
+ * Constructs a RenderContext with a given transform and rendering hints.
+ * The area of interest is taken to be the entire renderable area.
+ *
+ * @param usr2dev an AffineTransform.
+ * @param hints a RenderingHints object containing rendering hints.
+ */
+ public RenderContext(AffineTransform usr2dev, RenderingHints hints) {
+ this(usr2dev, null, hints);
+ }
+
+ /**
+ * Constructs a RenderContext with a given transform and area of interest.
+ * The area of interest is supplied as a Shape.
+ * No rendering hints are used.
+ *
+ * @param usr2dev an AffineTransform.
+ * @param aoi a Shape representing the area of interest.
+ */
+ public RenderContext(AffineTransform usr2dev, Shape aoi) {
+ this(usr2dev, aoi, null);
+ }
+
+ /**
+ * Gets the rendering hints of this <code>RenderContext</code>.
+ * @return a <code>RenderingHints</code> object that represents
+ * the rendering hints of this <code>RenderContext</code>.
+ * @see #setRenderingHints(RenderingHints)
+ */
+ public RenderingHints getRenderingHints() {
+ return hints;
+ }
+
+ /**
+ * Sets the rendering hints of this <code>RenderContext</code>.
+ * @param hints a <code>RenderingHints</code> object that represents
+ * the rendering hints to assign to this <code>RenderContext</code>.
+ * @see #getRenderingHints
+ */
+ public void setRenderingHints(RenderingHints hints) {
+ this.hints = hints;
+ }
+
+ /**
+ * Sets the current user-to-device AffineTransform contained
+ * in the RenderContext to a given transform.
+ *
+ * @param newTransform the new AffineTransform.
+ * @see #getTransform
+ */
+ public void setTransform(AffineTransform newTransform) {
+ usr2dev = (AffineTransform)newTransform.clone();
+ }
+
+ /**
+ * Modifies the current user-to-device transform by prepending another
+ * transform. In matrix notation the operation is:
+ * <pre>
+ * [this] = [modTransform] x [this]
+ * </pre>
+ *
+ * @param modTransform the AffineTransform to prepend to the
+ * current usr2dev transform.
+ * @since 1.3
+ */
+ public void preConcatenateTransform(AffineTransform modTransform) {
+ this.preConcetenateTransform(modTransform);
+ }
+
+ /**
+ * Modifies the current user-to-device transform by prepending another
+ * transform. In matrix notation the operation is:
+ * <pre>
+ * [this] = [modTransform] x [this]
+ * </pre>
+ * This method does the same thing as the preConcatenateTransform
+ * method. It is here for backward compatibility with previous releases
+ * which misspelled the method name.
+ *
+ * @param modTransform the AffineTransform to prepend to the
+ * current usr2dev transform.
+ * @deprecated replaced by
+ * <code>preConcatenateTransform(AffineTransform)</code>.
+ */
+ @Deprecated
+ public void preConcetenateTransform(AffineTransform modTransform) {
+ usr2dev.preConcatenate(modTransform);
+ }
+
+ /**
+ * Modifies the current user-to-device transform by appending another
+ * transform. In matrix notation the operation is:
+ * <pre>
+ * [this] = [this] x [modTransform]
+ * </pre>
+ *
+ * @param modTransform the AffineTransform to append to the
+ * current usr2dev transform.
+ * @since 1.3
+ */
+ public void concatenateTransform(AffineTransform modTransform) {
+ this.concetenateTransform(modTransform);
+ }
+
+ /**
+ * Modifies the current user-to-device transform by appending another
+ * transform. In matrix notation the operation is:
+ * <pre>
+ * [this] = [this] x [modTransform]
+ * </pre>
+ * This method does the same thing as the concatenateTransform
+ * method. It is here for backward compatibility with previous releases
+ * which misspelled the method name.
+ *
+ * @param modTransform the AffineTransform to append to the
+ * current usr2dev transform.
+ * @deprecated replaced by
+ * <code>concatenateTransform(AffineTransform)</code>.
+ */
+ @Deprecated
+ public void concetenateTransform(AffineTransform modTransform) {
+ usr2dev.concatenate(modTransform);
+ }
+
+ /**
+ * Gets the current user-to-device AffineTransform.
+ *
+ * @return a reference to the current AffineTransform.
+ * @see #setTransform(AffineTransform)
+ */
+ public AffineTransform getTransform() {
+ return (AffineTransform)usr2dev.clone();
+ }
+
+ /**
+ * Sets the current area of interest. The old area is discarded.
+ *
+ * @param newAoi The new area of interest.
+ * @see #getAreaOfInterest
+ */
+ public void setAreaOfInterest(Shape newAoi) {
+ aoi = newAoi;
+ }
+
+ /**
+ * Gets the ares of interest currently contained in the
+ * RenderContext.
+ *
+ * @return a reference to the area of interest of the RenderContext,
+ * or null if none is specified.
+ * @see #setAreaOfInterest(Shape)
+ */
+ public Shape getAreaOfInterest() {
+ return aoi;
+ }
+
+ /**
+ * Makes a copy of a RenderContext. The area of interest is copied
+ * by reference. The usr2dev AffineTransform and hints are cloned,
+ * while the area of interest is copied by reference.
+ *
+ * @return the new cloned RenderContext.
+ */
+ public Object clone() {
+ RenderContext newRenderContext = new RenderContext(usr2dev,
+ aoi, hints);
+ return newRenderContext;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/renderable/RenderableImage.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,198 @@
+/*
+ * Portions Copyright 1998-2000 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.image.renderable;
+import java.util.Vector;
+import java.awt.RenderingHints;
+import java.awt.image.*;
+
+/**
+ * A RenderableImage is a common interface for rendering-independent
+ * images (a notion which subsumes resolution independence). That is,
+ * images which are described and have operations applied to them
+ * independent of any specific rendering of the image. For example, a
+ * RenderableImage can be rotated and cropped in
+ * resolution-independent terms. Then, it can be rendered for various
+ * specific contexts, such as a draft preview, a high-quality screen
+ * display, or a printer, each in an optimal fashion.
+ *
+ * <p> A RenderedImage is returned from a RenderableImage via the
+ * createRendering() method, which takes a RenderContext. The
+ * RenderContext specifies how the RenderedImage should be
+ * constructed. Note that it is not possible to extract pixels
+ * directly from a RenderableImage.
+ *
+ * <p> The createDefaultRendering() and createScaledRendering() methods are
+ * convenience methods that construct an appropriate RenderContext
+ * internally. All of the rendering methods may return a reference to a
+ * previously produced rendering.
+ */
+public interface RenderableImage {
+
+ /**
+ * String constant that can be used to identify a property on
+ * a RenderedImage obtained via the createRendering or
+ * createScaledRendering methods. If such a property exists,
+ * the value of the propoery will be a RenderingHints object
+ * specifying which hints were observed in creating the rendering.
+ */
+ static final String HINTS_OBSERVED = "HINTS_OBSERVED";
+
+ /**
+ * Returns a vector of RenderableImages that are the sources of
+ * image data for this RenderableImage. Note that this method may
+ * return an empty vector, to indicate that the image has no sources,
+ * or null, to indicate that no information is available.
+ *
+ * @return a (possibly empty) Vector of RenderableImages, or null.
+ */
+ Vector<RenderableImage> getSources();
+
+ /**
+ * Gets a property from the property set of this image.
+ * If the property name is not recognized, java.awt.Image.UndefinedProperty
+ * will be returned.
+ *
+ * @param name the name of the property to get, as a String.
+ * @return a reference to the property Object, or the value
+ * java.awt.Image.UndefinedProperty.
+ */
+ Object getProperty(String name);
+
+ /**
+ * Returns a list of names recognized by getProperty.
+ * @return a list of property names.
+ */
+ String[] getPropertyNames();
+
+ /**
+ * Returns true if successive renderings (that is, calls to
+ * createRendering() or createScaledRendering()) with the same arguments
+ * may produce different results. This method may be used to
+ * determine whether an existing rendering may be cached and
+ * reused. It is always safe to return true.
+ * @return <code>true</code> if successive renderings with the
+ * same arguments might produce different results;
+ * <code>false</code> otherwise.
+ */
+ boolean isDynamic();
+
+ /**
+ * Gets the width in user coordinate space. By convention, the
+ * usual width of a RenderableImage is equal to the image's aspect
+ * ratio (width divided by height).
+ *
+ * @return the width of the image in user coordinates.
+ */
+ float getWidth();
+
+ /**
+ * Gets the height in user coordinate space. By convention, the
+ * usual height of a RenderedImage is equal to 1.0F.
+ *
+ * @return the height of the image in user coordinates.
+ */
+ float getHeight();
+
+ /**
+ * Gets the minimum X coordinate of the rendering-independent image data.
+ * @return the minimum X coordinate of the rendering-independent image
+ * data.
+ */
+ float getMinX();
+
+ /**
+ * Gets the minimum Y coordinate of the rendering-independent image data.
+ * @return the minimum Y coordinate of the rendering-independent image
+ * data.
+ */
+ float getMinY();
+
+ /**
+ * Creates a RenderedImage instance of this image with width w, and
+ * height h in pixels. The RenderContext is built automatically
+ * with an appropriate usr2dev transform and an area of interest
+ * of the full image. All the rendering hints come from hints
+ * passed in.
+ *
+ * <p> If w == 0, it will be taken to equal
+ * Math.round(h*(getWidth()/getHeight())).
+ * Similarly, if h == 0, it will be taken to equal
+ * Math.round(w*(getHeight()/getWidth())). One of
+ * w or h must be non-zero or else an IllegalArgumentException
+ * will be thrown.
+ *
+ * <p> The created RenderedImage may have a property identified
+ * by the String HINTS_OBSERVED to indicate which RenderingHints
+ * were used to create the image. In addition any RenderedImages
+ * that are obtained via the getSources() method on the created
+ * RenderedImage may have such a property.
+ *
+ * @param w the width of rendered image in pixels, or 0.
+ * @param h the height of rendered image in pixels, or 0.
+ * @param hints a RenderingHints object containg hints.
+ * @return a RenderedImage containing the rendered data.
+ */
+ RenderedImage createScaledRendering(int w, int h, RenderingHints hints);
+
+ /**
+ * Returnd a RenderedImage instance of this image with a default
+ * width and height in pixels. The RenderContext is built
+ * automatically with an appropriate usr2dev transform and an area
+ * of interest of the full image. The rendering hints are
+ * empty. createDefaultRendering may make use of a stored
+ * rendering for speed.
+ *
+ * @return a RenderedImage containing the rendered data.
+ */
+ RenderedImage createDefaultRendering();
+
+ /**
+ * Creates a RenderedImage that represented a rendering of this image
+ * using a given RenderContext. This is the most general way to obtain a
+ * rendering of a RenderableImage.
+ *
+ * <p> The created RenderedImage may have a property identified
+ * by the String HINTS_OBSERVED to indicate which RenderingHints
+ * (from the RenderContext) were used to create the image.
+ * In addition any RenderedImages
+ * that are obtained via the getSources() method on the created
+ * RenderedImage may have such a property.
+ *
+ * @param renderContext the RenderContext to use to produce the rendering.
+ * @return a RenderedImage containing the rendered data.
+ */
+ RenderedImage createRendering(RenderContext renderContext);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/renderable/RenderableImageOp.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,350 @@
+/*
+ * Portions Copyright 1998-2000 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.image.renderable;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.RenderedImage;
+import java.awt.RenderingHints;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * This class handles the renderable aspects of an operation with help
+ * from its associated instance of a ContextualRenderedImageFactory.
+ */
+public class RenderableImageOp implements RenderableImage {
+
+ /** A ParameterBlock containing source and parameters. */
+ ParameterBlock paramBlock;
+
+ /** The associated ContextualRenderedImageFactory. */
+ ContextualRenderedImageFactory myCRIF;
+
+ /** The bounding box of the results of this RenderableImageOp. */
+ Rectangle2D boundingBox;
+
+
+ /**
+ * Constructs a RenderedImageOp given a
+ * ContextualRenderedImageFactory object, and
+ * a ParameterBlock containing RenderableImage sources and other
+ * parameters. Any RenderedImage sources referenced by the
+ * ParameterBlock will be ignored.
+ *
+ * @param CRIF a ContextualRenderedImageFactory object
+ * @param paramBlock a ParameterBlock containing this operation's source
+ * images and other parameters necessary for the operation
+ * to run.
+ */
+ public RenderableImageOp(ContextualRenderedImageFactory CRIF,
+ ParameterBlock paramBlock) {
+ this.myCRIF = CRIF;
+ this.paramBlock = (ParameterBlock) paramBlock.clone();
+ }
+
+ /**
+ * Returns a vector of RenderableImages that are the sources of
+ * image data for this RenderableImage. Note that this method may
+ * return an empty vector, to indicate that the image has no sources,
+ * or null, to indicate that no information is available.
+ *
+ * @return a (possibly empty) Vector of RenderableImages, or null.
+ */
+ public Vector<RenderableImage> getSources() {
+ return getRenderableSources();
+ }
+
+ private Vector getRenderableSources() {
+ Vector sources = null;
+
+ if (paramBlock.getNumSources() > 0) {
+ sources = new Vector();
+ int i = 0;
+ while (i < paramBlock.getNumSources()) {
+ Object o = paramBlock.getSource(i);
+ if (o instanceof RenderableImage) {
+ sources.add((RenderableImage)o);
+ i++;
+ } else {
+ break;
+ }
+ }
+ }
+ return sources;
+ }
+
+ /**
+ * Gets a property from the property set of this image.
+ * If the property name is not recognized, java.awt.Image.UndefinedProperty
+ * will be returned.
+ *
+ * @param name the name of the property to get, as a String.
+ * @return a reference to the property Object, or the value
+ * java.awt.Image.UndefinedProperty.
+ */
+ public Object getProperty(String name) {
+ return myCRIF.getProperty(paramBlock, name);
+ }
+
+ /**
+ * Return a list of names recognized by getProperty.
+ * @return a list of property names.
+ */
+ public String[] getPropertyNames() {
+ return myCRIF.getPropertyNames();
+ }
+
+ /**
+ * Returns true if successive renderings (that is, calls to
+ * createRendering() or createScaledRendering()) with the same arguments
+ * may produce different results. This method may be used to
+ * determine whether an existing rendering may be cached and
+ * reused. The CRIF's isDynamic method will be called.
+ * @return <code>true</code> if successive renderings with the
+ * same arguments might produce different results;
+ * <code>false</code> otherwise.
+ */
+ public boolean isDynamic() {
+ return myCRIF.isDynamic();
+ }
+
+ /**
+ * Gets the width in user coordinate space. By convention, the
+ * usual width of a RenderableImage is equal to the image's aspect
+ * ratio (width divided by height).
+ *
+ * @return the width of the image in user coordinates.
+ */
+ public float getWidth() {
+ if (boundingBox == null) {
+ boundingBox = myCRIF.getBounds2D(paramBlock);
+ }
+ return (float)boundingBox.getWidth();
+ }
+
+ /**
+ * Gets the height in user coordinate space. By convention, the
+ * usual height of a RenderedImage is equal to 1.0F.
+ *
+ * @return the height of the image in user coordinates.
+ */
+ public float getHeight() {
+ if (boundingBox == null) {
+ boundingBox = myCRIF.getBounds2D(paramBlock);
+ }
+ return (float)boundingBox.getHeight();
+ }
+
+ /**
+ * Gets the minimum X coordinate of the rendering-independent image data.
+ */
+ public float getMinX() {
+ if (boundingBox == null) {
+ boundingBox = myCRIF.getBounds2D(paramBlock);
+ }
+ return (float)boundingBox.getMinX();
+ }
+
+ /**
+ * Gets the minimum Y coordinate of the rendering-independent image data.
+ */
+ public float getMinY() {
+ if (boundingBox == null) {
+ boundingBox = myCRIF.getBounds2D(paramBlock);
+ }
+ return (float)boundingBox.getMinY();
+ }
+
+ /**
+ * Change the current ParameterBlock of the operation, allowing
+ * editing of image rendering chains. The effects of such a
+ * change will be visible when a new rendering is created from
+ * this RenderableImageOp or any dependent RenderableImageOp.
+ *
+ * @param paramBlock the new ParameterBlock.
+ * @return the old ParameterBlock.
+ * @see #getParameterBlock
+ */
+ public ParameterBlock setParameterBlock(ParameterBlock paramBlock) {
+ ParameterBlock oldParamBlock = this.paramBlock;
+ this.paramBlock = (ParameterBlock)paramBlock.clone();
+ return oldParamBlock;
+ }
+
+ /**
+ * Returns a reference to the current parameter block.
+ * @return the <code>ParameterBlock</code> of this
+ * <code>RenderableImageOp</code>.
+ * @see #setParameterBlock(ParameterBlock)
+ */
+ public ParameterBlock getParameterBlock() {
+ return paramBlock;
+ }
+
+ /**
+ * Creates a RenderedImage instance of this image with width w, and
+ * height h in pixels. The RenderContext is built automatically
+ * with an appropriate usr2dev transform and an area of interest
+ * of the full image. All the rendering hints come from hints
+ * passed in.
+ *
+ * <p> If w == 0, it will be taken to equal
+ * Math.round(h*(getWidth()/getHeight())).
+ * Similarly, if h == 0, it will be taken to equal
+ * Math.round(w*(getHeight()/getWidth())). One of
+ * w or h must be non-zero or else an IllegalArgumentException
+ * will be thrown.
+ *
+ * <p> The created RenderedImage may have a property identified
+ * by the String HINTS_OBSERVED to indicate which RenderingHints
+ * were used to create the image. In addition any RenderedImages
+ * that are obtained via the getSources() method on the created
+ * RenderedImage may have such a property.
+ *
+ * @param w the width of rendered image in pixels, or 0.
+ * @param h the height of rendered image in pixels, or 0.
+ * @param hints a RenderingHints object containg hints.
+ * @return a RenderedImage containing the rendered data.
+ */
+ public RenderedImage createScaledRendering(int w, int h,
+ RenderingHints hints) {
+ // DSR -- code to try to get a unit scale
+ double sx = (double)w/getWidth();
+ double sy = (double)h/getHeight();
+ if (Math.abs(sx/sy - 1.0) < 0.01) {
+ sx = sy;
+ }
+ AffineTransform usr2dev = AffineTransform.getScaleInstance(sx, sy);
+ RenderContext newRC = new RenderContext(usr2dev, hints);
+ return createRendering(newRC);
+ }
+
+ /**
+ * Gets a RenderedImage instance of this image with a default
+ * width and height in pixels. The RenderContext is built
+ * automatically with an appropriate usr2dev transform and an area
+ * of interest of the full image. All the rendering hints come
+ * from hints passed in. Implementors of this interface must be
+ * sure that there is a defined default width and height.
+ *
+ * @return a RenderedImage containing the rendered data.
+ */
+ public RenderedImage createDefaultRendering() {
+ AffineTransform usr2dev = new AffineTransform(); // Identity
+ RenderContext newRC = new RenderContext(usr2dev);
+ return createRendering(newRC);
+ }
+
+ /**
+ * Creates a RenderedImage which represents this
+ * RenderableImageOp (including its Renderable sources) rendered
+ * according to the given RenderContext.
+ *
+ * <p> This method supports chaining of either Renderable or
+ * RenderedImage operations. If sources in
+ * the ParameterBlock used to construct the RenderableImageOp are
+ * RenderableImages, then a three step process is followed:
+ *
+ * <ol>
+ * <li> mapRenderContext() is called on the associated CRIF for
+ * each RenderableImage source;
+ * <li> createRendering() is called on each of the RenderableImage sources
+ * using the backwards-mapped RenderContexts obtained in step 1,
+ * resulting in a rendering of each source;
+ * <li> ContextualRenderedImageFactory.create() is called
+ * with a new ParameterBlock containing the parameters of
+ * the RenderableImageOp and the RenderedImages that were created by the
+ * createRendering() calls.
+ * </ol>
+ *
+ * <p> If the elements of the source Vector of
+ * the ParameterBlock used to construct the RenderableImageOp are
+ * instances of RenderedImage, then the CRIF.create() method is
+ * called immediately using the original ParameterBlock.
+ * This provides a basis case for the recursion.
+ *
+ * <p> The created RenderedImage may have a property identified
+ * by the String HINTS_OBSERVED to indicate which RenderingHints
+ * (from the RenderContext) were used to create the image.
+ * In addition any RenderedImages
+ * that are obtained via the getSources() method on the created
+ * RenderedImage may have such a property.
+ *
+ * @param renderContext The RenderContext to use to perform the rendering.
+ * @return a RenderedImage containing the desired output image.
+ */
+ public RenderedImage createRendering(RenderContext renderContext) {
+ RenderedImage image = null;
+ RenderContext rcOut = null;
+
+ // Clone the original ParameterBlock; if the ParameterBlock
+ // contains RenderableImage sources, they will be replaced by
+ // RenderedImages.
+ ParameterBlock renderedParamBlock = (ParameterBlock)paramBlock.clone();
+ Vector sources = getRenderableSources();
+
+ try {
+ // This assumes that if there is no renderable source, that there
+ // is a rendered source in paramBlock
+
+ if (sources != null) {
+ Vector renderedSources = new Vector();
+ for (int i = 0; i < sources.size(); i++) {
+ rcOut = myCRIF.mapRenderContext(i, renderContext,
+ paramBlock, this);
+ RenderedImage rdrdImage =
+ ((RenderableImage)sources.elementAt(i)).createRendering(rcOut);
+ if (rdrdImage == null) {
+ return null;
+ }
+
+ // Add this rendered image to the ParameterBlock's
+ // list of RenderedImages.
+ renderedSources.addElement(rdrdImage);
+ }
+
+ if (renderedSources.size() > 0) {
+ renderedParamBlock.setSources(renderedSources);
+ }
+ }
+
+ return myCRIF.create(renderContext, renderedParamBlock);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // This should never happen
+ return null;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/renderable/RenderableImageProducer.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,219 @@
+/*
+ * Portions Copyright 1998 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.image.renderable;
+import java.awt.color.ColorSpace;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DirectColorModel;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ImageProducer;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * An adapter class that implements ImageProducer to allow the
+ * asynchronous production of a RenderableImage. The size of the
+ * ImageConsumer is determined by the scale factor of the usr2dev
+ * transform in the RenderContext. If the RenderContext is null, the
+ * default rendering of the RenderableImage is used. This class
+ * implements an asynchronous production that produces the image in
+ * one thread at one resolution. This class may be subclassed to
+ * implement versions that will render the image using several
+ * threads. These threads could render either the same image at
+ * progressively better quality, or different sections of the image at
+ * a single resolution.
+ */
+public class RenderableImageProducer implements ImageProducer, Runnable {
+
+ /** The RenderableImage source for the producer. */
+ RenderableImage rdblImage;
+
+ /** The RenderContext to use for producing the image. */
+ RenderContext rc;
+
+ /** A Vector of image consumers. */
+ Vector ics = new Vector();
+
+ /**
+ * Constructs a new RenderableImageProducer from a RenderableImage
+ * and a RenderContext.
+ *
+ * @param rdblImage the RenderableImage to be rendered.
+ * @param rc the RenderContext to use for producing the pixels.
+ */
+ public RenderableImageProducer(RenderableImage rdblImage,
+ RenderContext rc) {
+ this.rdblImage = rdblImage;
+ this.rc = rc;
+ }
+
+ /**
+ * Sets a new RenderContext to use for the next startProduction() call.
+ *
+ * @param rc the new RenderContext.
+ */
+ public synchronized void setRenderContext(RenderContext rc) {
+ this.rc = rc;
+ }
+
+ /**
+ * Adds an ImageConsumer to the list of consumers interested in
+ * data for this image.
+ *
+ * @param ic an ImageConsumer to be added to the interest list.
+ */
+ public synchronized void addConsumer(ImageConsumer ic) {
+ if (!ics.contains(ic)) {
+ ics.addElement(ic);
+ }
+ }
+
+ /**
+ * Determine if an ImageConsumer is on the list of consumers
+ * currently interested in data for this image.
+ *
+ * @param ic the ImageConsumer to be checked.
+ * @return true if the ImageConsumer is on the list; false otherwise.
+ */
+ public synchronized boolean isConsumer(ImageConsumer ic) {
+ return ics.contains(ic);
+ }
+
+ /**
+ * Remove an ImageConsumer from the list of consumers interested in
+ * data for this image.
+ *
+ * @param ic the ImageConsumer to be removed.
+ */
+ public synchronized void removeConsumer(ImageConsumer ic) {
+ ics.removeElement(ic);
+ }
+
+ /**
+ * Adds an ImageConsumer to the list of consumers interested in
+ * data for this image, and immediately starts delivery of the
+ * image data through the ImageConsumer interface.
+ *
+ * @param ic the ImageConsumer to be added to the list of consumers.
+ */
+ public synchronized void startProduction(ImageConsumer ic) {
+ addConsumer(ic);
+ // Need to build a runnable object for the Thread.
+ Thread thread = new Thread(this, "RenderableImageProducer Thread");
+ thread.start();
+ }
+
+ /**
+ * Requests that a given ImageConsumer have the image data delivered
+ * one more time in top-down, left-right order.
+ *
+ * @param ic the ImageConsumer requesting the resend.
+ */
+ public void requestTopDownLeftRightResend(ImageConsumer ic) {
+ // So far, all pixels are already sent in TDLR order
+ }
+
+ /**
+ * The runnable method for this class. This will produce an image using
+ * the current RenderableImage and RenderContext and send it to all the
+ * ImageConsumer currently registered with this class.
+ */
+ public void run() {
+ // First get the rendered image
+ RenderedImage rdrdImage;
+ if (rc != null) {
+ rdrdImage = rdblImage.createRendering(rc);
+ } else {
+ rdrdImage = rdblImage.createDefaultRendering();
+ }
+
+ // And its ColorModel
+ ColorModel colorModel = rdrdImage.getColorModel();
+ Raster raster = rdrdImage.getData();
+ SampleModel sampleModel = raster.getSampleModel();
+ DataBuffer dataBuffer = raster.getDataBuffer();
+
+ if (colorModel == null) {
+ colorModel = ColorModel.getRGBdefault();
+ }
+ int minX = raster.getMinX();
+ int minY = raster.getMinY();
+ int width = raster.getWidth();
+ int height = raster.getHeight();
+
+ Enumeration icList;
+ ImageConsumer ic;
+ // Set up the ImageConsumers
+ icList = ics.elements();
+ while (icList.hasMoreElements()) {
+ ic = (ImageConsumer)icList.nextElement();
+ ic.setDimensions(width,height);
+ ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT |
+ ImageConsumer.COMPLETESCANLINES |
+ ImageConsumer.SINGLEPASS |
+ ImageConsumer.SINGLEFRAME);
+ }
+
+ // Get RGB pixels from the raster scanline by scanline and
+ // send to consumers.
+ int pix[] = new int[width];
+ int i,j;
+ int numBands = sampleModel.getNumBands();
+ int tmpPixel[] = new int[numBands];
+ for (j = 0; j < height; j++) {
+ for(i = 0; i < width; i++) {
+ sampleModel.getPixel(i, j, tmpPixel, dataBuffer);
+ pix[i] = colorModel.getDataElement(tmpPixel, 0);
+ }
+ // Now send the scanline to the Consumers
+ icList = ics.elements();
+ while (icList.hasMoreElements()) {
+ ic = (ImageConsumer)icList.nextElement();
+ ic.setPixels(0, j, width, 1, colorModel, pix, 0, width);
+ }
+ }
+
+ // Now tell the consumers we're done.
+ icList = ics.elements();
+ while (icList.hasMoreElements()) {
+ ic = (ImageConsumer)icList.nextElement();
+ ic.imageComplete(ImageConsumer.STATICIMAGEDONE);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/awt/image/renderable/RenderedImageFactory.java Thu Apr 10 16:28:45 2008 -0700
@@ -0,0 +1,78 @@
+/*
+ * Portions Copyright 1998 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* ********************************************************************
+ **********************************************************************
+ **********************************************************************
+ *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
+ *** As an unpublished work pursuant to Title 17 of the United ***
+ *** States Code. All rights reserved. ***
+ **********************************************************************
+ **********************************************************************
+ **********************************************************************/
+
+package java.awt.image.renderable;
+import java.awt.image.RenderedImage;
+import java.awt.RenderingHints;
+
+/**
+ * The RenderedImageFactory interface (often abbreviated RIF) is
+ * intended to be implemented by classes that wish to act as factories
+ * to produce different renderings, for example by executing a series
+ * of BufferedImageOps on a set of sources, depending on a specific
+ * set of parameters, properties, and rendering hints.
+ */
+public interface RenderedImageFactory {
+
+ /**
+ * Creates a RenderedImage representing the results of an imaging
+ * operation (or chain of operations) for a given ParameterBlock and
+ * RenderingHints. The RIF may also query any source images
+ * referenced by the ParameterBlock for their dimensions,
+ * SampleModels, properties, etc., as necessary.
+ *
+ * <p> The create() method can return null if the
+ * RenderedImageFactory is not capable of producing output for the
+ * given set of source images and parameters. For example, if a
+ * RenderedImageFactory is only capable of performing a 3x3
+ * convolution on single-banded image data, and the source image has
+ * multiple bands or the convolution Kernel is 5x5, null should be
+ * returned.
+ *
+ * <p> Hints should be taken into account, but can be ignored.
+ * The created RenderedImage may have a property identified
+ * by the String HINTS_OBSERVED to indicate which RenderingHints
+ * were used to create the image. In addition any RenderedImages
+ * that are obtained via the getSources() method on the created
+ * RenderedImage may have such a property.
+ *
+ * @param paramBlock a ParameterBlock containing sources and parameters
+ * for the RenderedImage to be created.
+ * @param hints a RenderingHints object containing hints.
+ * @return A RenderedImage containing the desired output.
+ */
+ RenderedImage create(ParameterBlock paramBlock,
+ RenderingHints hints);
+}