| /* |
| * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package java.awt.image; |
| |
| import java.awt.Transparency; |
| import java.awt.color.ColorSpace; |
| import java.awt.color.ICC_ColorSpace; |
| import sun.java2d.cmm.CMSManager; |
| import sun.java2d.cmm.ColorTransform; |
| import sun.java2d.cmm.PCMM; |
| import java.util.Collections; |
| import java.util.Map; |
| import java.util.WeakHashMap; |
| import java.util.Arrays; |
| |
| /** |
| * The {@code ColorModel} abstract class encapsulates the |
| * methods for translating a pixel value to color components |
| * (for example, red, green, and blue) and an alpha component. |
| * In order to render an image to the screen, a printer, or another |
| * image, pixel values must be converted to color and alpha components. |
| * As arguments to or return values from methods of this class, |
| * pixels are represented as 32-bit ints or as arrays of primitive types. |
| * The number, order, and interpretation of color components for a |
| * {@code ColorModel} is specified by its {@code ColorSpace}. |
| * A {@code ColorModel} used with pixel data that does not include |
| * alpha information treats all pixels as opaque, which is an alpha |
| * value of 1.0. |
| * <p> |
| * This {@code ColorModel} class supports two representations of |
| * pixel values. A pixel value can be a single 32-bit int or an |
| * array of primitive types. The Java(tm) Platform 1.0 and 1.1 APIs |
| * represented pixels as single {@code byte} or single |
| * {@code int} values. For purposes of the {@code ColorModel} |
| * class, pixel value arguments were passed as ints. The Java(tm) 2 |
| * Platform API introduced additional classes for representing images. |
| * With {@link BufferedImage} or {@link RenderedImage} |
| * objects, based on {@link Raster} and {@link SampleModel} classes, pixel |
| * values might not be conveniently representable as a single int. |
| * Consequently, {@code ColorModel} now has methods that accept |
| * pixel values represented as arrays of primitive types. The primitive |
| * type used by a particular {@code ColorModel} object is called its |
| * transfer type. |
| * <p> |
| * {@code ColorModel} objects used with images for which pixel values |
| * are not conveniently representable as a single int throw an |
| * {@link IllegalArgumentException} when methods taking a single int pixel |
| * argument are called. Subclasses of {@code ColorModel} must |
| * specify the conditions under which this occurs. This does not |
| * occur with {@link DirectColorModel} or {@link IndexColorModel} objects. |
| * <p> |
| * Currently, the transfer types supported by the Java 2D(tm) API are |
| * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, |
| * DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, and DataBuffer.TYPE_DOUBLE. |
| * Most rendering operations will perform much faster when using ColorModels |
| * and images based on the first three of these types. In addition, some |
| * image filtering operations are not supported for ColorModels and |
| * images based on the latter three types. |
| * The transfer type for a particular {@code ColorModel} object is |
| * specified when the object is created, either explicitly or by default. |
| * All subclasses of {@code ColorModel} must specify what the |
| * possible transfer types are and how the number of elements in the |
| * primitive arrays representing pixels is determined. |
| * <p> |
| * For {@code BufferedImages}, the transfer type of its |
| * {@code Raster} and of the {@code Raster} object's |
| * {@code SampleModel} (available from the |
| * {@code getTransferType} methods of these classes) must match that |
| * of the {@code ColorModel}. The number of elements in an array |
| * representing a pixel for the {@code Raster} and |
| * {@code SampleModel} (available from the |
| * {@code getNumDataElements} methods of these classes) must match |
| * that of the {@code ColorModel}. |
| * <p> |
| * The algorithm used to convert from pixel values to color and alpha |
| * components varies by subclass. For example, there is not necessarily |
| * a one-to-one correspondence between samples obtained from the |
| * {@code SampleModel} of a {@code BufferedImage} object's |
| * {@code Raster} and color/alpha components. Even when |
| * there is such a correspondence, the number of bits in a sample is not |
| * necessarily the same as the number of bits in the corresponding color/alpha |
| * component. Each subclass must specify how the translation from |
| * pixel values to color/alpha components is done. |
| * <p> |
| * Methods in the {@code ColorModel} class use two different |
| * representations of color and alpha components - a normalized form |
| * and an unnormalized form. In the normalized form, each component is a |
| * {@code float} value between some minimum and maximum values. For |
| * the alpha component, the minimum is 0.0 and the maximum is 1.0. For |
| * color components the minimum and maximum values for each component can |
| * be obtained from the {@code ColorSpace} object. These values |
| * will often be 0.0 and 1.0 (e.g. normalized component values for the |
| * default sRGB color space range from 0.0 to 1.0), but some color spaces |
| * have component values with different upper and lower limits. These |
| * limits can be obtained using the {@code getMinValue} and |
| * {@code getMaxValue} methods of the {@code ColorSpace} |
| * class. Normalized color component values are not premultiplied. |
| * All {@code ColorModels} must support the normalized form. |
| * <p> |
| * In the unnormalized |
| * form, each component is an unsigned integral value between 0 and |
| * 2<sup>n</sup> - 1, where n is the number of significant bits for a |
| * particular component. If pixel values for a particular |
| * {@code ColorModel} represent color samples premultiplied by |
| * the alpha sample, unnormalized color component values are |
| * also premultiplied. The unnormalized form is used only with instances |
| * of {@code ColorModel} whose {@code ColorSpace} has minimum |
| * component values of 0.0 for all components and maximum values of |
| * 1.0 for all components. |
| * The unnormalized form for color and alpha components can be a convenient |
| * representation for {@code ColorModels} whose normalized component |
| * values all lie |
| * between 0.0 and 1.0. In such cases the integral value 0 maps to 0.0 and |
| * the value 2<sup>n</sup> - 1 maps to 1.0. In other cases, such as |
| * when the normalized component values can be either negative or positive, |
| * the unnormalized form is not convenient. Such {@code ColorModel} |
| * objects throw an {@link IllegalArgumentException} when methods involving |
| * an unnormalized argument are called. Subclasses of {@code ColorModel} |
| * must specify the conditions under which this occurs. |
| * |
| * @see IndexColorModel |
| * @see ComponentColorModel |
| * @see PackedColorModel |
| * @see DirectColorModel |
| * @see java.awt.Image |
| * @see BufferedImage |
| * @see RenderedImage |
| * @see java.awt.color.ColorSpace |
| * @see SampleModel |
| * @see Raster |
| * @see DataBuffer |
| */ |
| public abstract class ColorModel implements Transparency{ |
| private long pData; // Placeholder for data for native functions |
| |
| /** |
| * The total number of bits in the pixel. |
| */ |
| protected int pixel_bits; |
| int[] nBits; |
| int transparency = Transparency.TRANSLUCENT; |
| boolean supportsAlpha = true; |
| boolean isAlphaPremultiplied = false; |
| int numComponents = -1; |
| int numColorComponents = -1; |
| ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB); |
| int colorSpaceType = ColorSpace.TYPE_RGB; |
| int maxBits; |
| boolean is_sRGB = true; |
| |
| /** |
| * Data type of the array used to represent pixel values. |
| */ |
| protected int transferType; |
| |
| /** |
| * This is copied from java.awt.Toolkit since we need the library |
| * loaded in java.awt.image also: |
| * |
| * WARNING: This is a temporary workaround for a problem in the |
| * way the AWT loads native libraries. A number of classes in the |
| * AWT package have a native method, initIDs(), which initializes |
| * the JNI field and method ids used in the native portion of |
| * their implementation. |
| * |
| * Since the use and storage of these ids is done by the |
| * implementation libraries, the implementation of these method is |
| * provided by the particular AWT implementations (for example, |
| * "Toolkit"s/Peer), such as Motif, Microsoft Windows, or Tiny. The |
| * problem is that this means that the native libraries must be |
| * loaded by the java.* classes, which do not necessarily know the |
| * names of the libraries to load. A better way of doing this |
| * would be to provide a separate library which defines java.awt.* |
| * initIDs, and exports the relevant symbols out to the |
| * implementation libraries. |
| * |
| * For now, we know it's done by the implementation, and we assume |
| * that the name of the library is "awt". -br. |
| */ |
| private static boolean loaded = false; |
| @SuppressWarnings("removal") |
| static void loadLibraries() { |
| if (!loaded) { |
| java.security.AccessController.doPrivileged( |
| new java.security.PrivilegedAction<Void>() { |
| public Void run() { |
| System.loadLibrary("awt"); |
| return null; |
| } |
| }); |
| loaded = true; |
| } |
| } |
| private static native void initIDs(); |
| static { |
| /* ensure that the proper libraries are loaded */ |
| loadLibraries(); |
| initIDs(); |
| } |
| private static ColorModel RGBdefault; |
| |
| /** |
| * Returns a {@code DirectColorModel} that describes the default |
| * format for integer RGB values used in many of the methods in the |
| * AWT image interfaces for the convenience of the programmer. |
| * The color space is the default {@link ColorSpace}, sRGB. |
| * The format for the RGB values is an integer with 8 bits |
| * each of alpha, red, green, and blue color components ordered |
| * correspondingly from the most significant byte to the least |
| * significant byte, as in: 0xAARRGGBB. Color components are |
| * not premultiplied by the alpha component. This format does not |
| * necessarily represent the native or the most efficient |
| * {@code ColorModel} for a particular device or for all images. |
| * It is merely used as a common color model format. |
| * @return a {@code DirectColorModel} object describing default |
| * RGB values. |
| */ |
| public static ColorModel getRGBdefault() { |
| if (RGBdefault == null) { |
| RGBdefault = new DirectColorModel(32, |
| 0x00ff0000, // Red |
| 0x0000ff00, // Green |
| 0x000000ff, // Blue |
| 0xff000000 // Alpha |
| ); |
| } |
| return RGBdefault; |
| } |
| |
| /** |
| * Constructs a {@code ColorModel} that translates pixels of the |
| * specified number of bits to color/alpha components. The color |
| * space is the default RGB {@code ColorSpace}, which is sRGB. |
| * Pixel values are assumed to include alpha information. If color |
| * and alpha information are represented in the pixel value as |
| * separate spatial bands, the color bands are assumed not to be |
| * premultiplied with the alpha value. The transparency type is |
| * java.awt.Transparency.TRANSLUCENT. The transfer type will be the |
| * smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, |
| * or DataBuffer.TYPE_INT that can hold a single pixel |
| * (or DataBuffer.TYPE_UNDEFINED if bits is greater |
| * than 32). Since this constructor has no information about the |
| * number of bits per color and alpha component, any subclass calling |
| * this constructor should override any method that requires this |
| * information. |
| * @param bits the number of bits of a pixel |
| * @throws IllegalArgumentException if the number |
| * of bits in {@code bits} is less than 1 |
| */ |
| public ColorModel(int bits) { |
| pixel_bits = bits; |
| if (bits < 1) { |
| throw new IllegalArgumentException("Number of bits must be > 0"); |
| } |
| numComponents = 4; |
| numColorComponents = 3; |
| maxBits = bits; |
| // REMIND: make sure transferType is set correctly |
| transferType = ColorModel.getDefaultTransferType(bits); |
| } |
| |
| /** |
| * Constructs a {@code ColorModel} that translates pixel values |
| * to color/alpha components. Color components will be in the |
| * specified {@code ColorSpace}. {@code pixel_bits} is the |
| * number of bits in the pixel values. The bits array |
| * specifies the number of significant bits per color and alpha component. |
| * Its length should be the number of components in the |
| * {@code ColorSpace} if there is no alpha information in the |
| * pixel values, or one more than this number if there is alpha |
| * information. {@code hasAlpha} indicates whether or not alpha |
| * information is present. The {@code boolean} |
| * {@code isAlphaPremultiplied} specifies how to interpret pixel |
| * values in which color and alpha information are represented as |
| * separate spatial bands. If the {@code boolean} |
| * is {@code true}, color samples are assumed to have been |
| * multiplied by the alpha sample. The {@code transparency} |
| * specifies what alpha values can be represented by this color model. |
| * The transfer type is the type of primitive array used to represent |
| * pixel values. Note that the bits array contains the number of |
| * significant bits per color/alpha component after the translation |
| * from pixel values. For example, for an |
| * {@code IndexColorModel} with {@code pixel_bits} equal to |
| * 16, the bits array might have four elements with each element set |
| * to 8. |
| * @param pixel_bits the number of bits in the pixel values |
| * @param bits array that specifies the number of significant bits |
| * per color and alpha component |
| * @param cspace the specified {@code ColorSpace} |
| * @param hasAlpha {@code true} if alpha information is present; |
| * {@code false} otherwise |
| * @param isAlphaPremultiplied {@code true} if color samples are |
| * assumed to be premultiplied by the alpha samples; |
| * {@code false} otherwise |
| * @param transparency what alpha values can be represented by this |
| * color model |
| * @param transferType the type of the array used to represent pixel |
| * values |
| * @throws IllegalArgumentException if the length of |
| * the bit array is less than the number of color or alpha |
| * components in this {@code ColorModel}, or if the |
| * transparency is not a valid value. |
| * @throws IllegalArgumentException if the sum of the number |
| * of bits in {@code bits} is less than 1 or if |
| * any of the elements in {@code bits} is less than 0. |
| * @see java.awt.Transparency |
| */ |
| protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace, |
| boolean hasAlpha, |
| boolean isAlphaPremultiplied, |
| int transparency, |
| int transferType) { |
| colorSpace = cspace; |
| colorSpaceType = cspace.getType(); |
| numColorComponents = cspace.getNumComponents(); |
| numComponents = numColorComponents + (hasAlpha ? 1 : 0); |
| supportsAlpha = hasAlpha; |
| if (bits.length < numComponents) { |
| throw new IllegalArgumentException("Number of color/alpha "+ |
| "components should be "+ |
| numComponents+ |
| " but length of bits array is "+ |
| bits.length); |
| } |
| |
| // 4186669 |
| if (transparency < Transparency.OPAQUE || |
| transparency > Transparency.TRANSLUCENT) |
| { |
| throw new IllegalArgumentException("Unknown transparency: "+ |
| transparency); |
| } |
| |
| if (supportsAlpha == false) { |
| this.isAlphaPremultiplied = false; |
| this.transparency = Transparency.OPAQUE; |
| } |
| else { |
| this.isAlphaPremultiplied = isAlphaPremultiplied; |
| this.transparency = transparency; |
| } |
| |
| /* |
| * We need significant bits value only for the length |
| * of number of components, so we truncate remaining part. |
| * It also helps in hashCode calculation since bits[] can contain |
| * different values after the length of number of components between |
| * two ColorModels. |
| */ |
| nBits = Arrays.copyOf(bits, numComponents); |
| this.pixel_bits = pixel_bits; |
| if (pixel_bits <= 0) { |
| throw new IllegalArgumentException("Number of pixel bits must "+ |
| "be > 0"); |
| } |
| // Check for bits < 0 |
| maxBits = 0; |
| for (int i=0; i < bits.length; i++) { |
| // bug 4304697 |
| if (bits[i] < 0) { |
| throw new |
| IllegalArgumentException("Number of bits must be >= 0"); |
| } |
| if (maxBits < bits[i]) { |
| maxBits = bits[i]; |
| } |
| } |
| |
| // Make sure that we don't have all 0-bit components |
| if (maxBits == 0) { |
| throw new IllegalArgumentException("There must be at least "+ |
| "one component with > 0 "+ |
| "pixel bits."); |
| } |
| |
| // Save this since we always need to check if it is the default CS |
| if (cspace != ColorSpace.getInstance(ColorSpace.CS_sRGB)) { |
| is_sRGB = false; |
| } |
| |
| // Save the transfer type |
| this.transferType = transferType; |
| } |
| |
| /** |
| * Returns whether or not alpha is supported in this |
| * {@code ColorModel}. |
| * @return {@code true} if alpha is supported in this |
| * {@code ColorModel}; {@code false} otherwise. |
| */ |
| public final boolean hasAlpha() { |
| return supportsAlpha; |
| } |
| |
| /** |
| * Returns whether or not the alpha has been premultiplied in the |
| * pixel values to be translated by this {@code ColorModel}. |
| * If the boolean is {@code true}, this {@code ColorModel} |
| * is to be used to interpret pixel values in which color and alpha |
| * information are represented as separate spatial bands, and color |
| * samples are assumed to have been multiplied by the |
| * alpha sample. |
| * @return {@code true} if the alpha values are premultiplied |
| * in the pixel values to be translated by this |
| * {@code ColorModel}; {@code false} otherwise. |
| */ |
| public final boolean isAlphaPremultiplied() { |
| return isAlphaPremultiplied; |
| } |
| |
| /** |
| * Returns the transfer type of this {@code ColorModel}. |
| * The transfer type is the type of primitive array used to represent |
| * pixel values as arrays. |
| * @return the transfer type. |
| * @since 1.3 |
| */ |
| public final int getTransferType() { |
| return transferType; |
| } |
| |
| /** |
| * Returns the number of bits per pixel described by this |
| * {@code ColorModel}. |
| * @return the number of bits per pixel. |
| */ |
| public int getPixelSize() { |
| return pixel_bits; |
| } |
| |
| /** |
| * Returns the number of bits for the specified color/alpha component. |
| * Color components are indexed in the order specified by the |
| * {@code ColorSpace}. Typically, this order reflects the name |
| * of the color space type. For example, for TYPE_RGB, index 0 |
| * corresponds to red, index 1 to green, and index 2 |
| * to blue. If this {@code ColorModel} supports alpha, the alpha |
| * component corresponds to the index following the last color |
| * component. |
| * @param componentIdx the index of the color/alpha component |
| * @return the number of bits for the color/alpha component at the |
| * specified index. |
| * @throws ArrayIndexOutOfBoundsException if {@code componentIdx} |
| * is greater than the number of components or |
| * less than zero |
| * @throws NullPointerException if the number of bits array is |
| * {@code null} |
| */ |
| public int getComponentSize(int componentIdx) { |
| // REMIND: |
| if (nBits == null) { |
| throw new NullPointerException("Number of bits array is null."); |
| } |
| |
| return nBits[componentIdx]; |
| } |
| |
| /** |
| * Returns an array of the number of bits per color/alpha component. |
| * The array contains the color components in the order specified by the |
| * {@code ColorSpace}, followed by the alpha component, if |
| * present. |
| * @return an array of the number of bits per color/alpha component |
| */ |
| public int[] getComponentSize() { |
| if (nBits != null) { |
| return nBits.clone(); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns the transparency. Returns either OPAQUE, BITMASK, |
| * or TRANSLUCENT. |
| * @return the transparency of this {@code ColorModel}. |
| * @see Transparency#OPAQUE |
| * @see Transparency#BITMASK |
| * @see Transparency#TRANSLUCENT |
| */ |
| public int getTransparency() { |
| return transparency; |
| } |
| |
| /** |
| * Returns the number of components, including alpha, in this |
| * {@code ColorModel}. This is equal to the number of color |
| * components, optionally plus one, if there is an alpha component. |
| * @return the number of components in this {@code ColorModel} |
| */ |
| public int getNumComponents() { |
| return numComponents; |
| } |
| |
| /** |
| * Returns the number of color components in this |
| * {@code ColorModel}. |
| * This is the number of components returned by |
| * {@link ColorSpace#getNumComponents}. |
| * @return the number of color components in this |
| * {@code ColorModel}. |
| * @see ColorSpace#getNumComponents |
| */ |
| public int getNumColorComponents() { |
| return numColorComponents; |
| } |
| |
| /** |
| * Returns the red color component for the specified pixel, scaled |
| * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion |
| * is done if necessary. The pixel value is specified as an int. |
| * An {@code IllegalArgumentException} is thrown if pixel |
| * values for this {@code ColorModel} are not conveniently |
| * representable as a single int. The returned value is not a |
| * pre-multiplied value. For example, if the |
| * alpha is premultiplied, this method divides it out before returning |
| * the value. If the alpha value is 0, the red value is 0. |
| * @param pixel a specified pixel |
| * @return the value of the red component of the specified pixel. |
| */ |
| public abstract int getRed(int pixel); |
| |
| /** |
| * Returns the green color component for the specified pixel, scaled |
| * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion |
| * is done if necessary. The pixel value is specified as an int. |
| * An {@code IllegalArgumentException} is thrown if pixel |
| * values for this {@code ColorModel} are not conveniently |
| * representable as a single int. The returned value is a non |
| * pre-multiplied value. For example, if the alpha is premultiplied, |
| * this method divides it out before returning |
| * the value. If the alpha value is 0, the green value is 0. |
| * @param pixel the specified pixel |
| * @return the value of the green component of the specified pixel. |
| */ |
| public abstract int getGreen(int pixel); |
| |
| /** |
| * Returns the blue color component for the specified pixel, scaled |
| * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion |
| * is done if necessary. The pixel value is specified as an int. |
| * An {@code IllegalArgumentException} is thrown if pixel values |
| * for this {@code ColorModel} are not conveniently representable |
| * as a single int. The returned value is a non pre-multiplied |
| * value, for example, if the alpha is premultiplied, this method |
| * divides it out before returning the value. If the alpha value is |
| * 0, the blue value is 0. |
| * @param pixel the specified pixel |
| * @return the value of the blue component of the specified pixel. |
| */ |
| public abstract int getBlue(int pixel); |
| |
| /** |
| * Returns the alpha component for the specified pixel, scaled |
| * from 0 to 255. The pixel value is specified as an int. |
| * An {@code IllegalArgumentException} is thrown if pixel |
| * values for this {@code ColorModel} are not conveniently |
| * representable as a single int. |
| * @param pixel the specified pixel |
| * @return the value of alpha component of the specified pixel. |
| */ |
| public abstract int getAlpha(int pixel); |
| |
| /** |
| * Returns the color/alpha components of the pixel in the default |
| * RGB color model format. A color conversion is done if necessary. |
| * The pixel value is specified as an int. |
| * An {@code IllegalArgumentException} thrown if pixel values |
| * for this {@code ColorModel} are not conveniently representable |
| * as a single int. The returned value is in a non |
| * pre-multiplied format. For example, if the alpha is premultiplied, |
| * this method divides it out of the color components. If the alpha |
| * value is 0, the color values are 0. |
| * @param pixel the specified pixel |
| * @return the RGB value of the color/alpha components of the |
| * specified pixel. |
| * @see ColorModel#getRGBdefault |
| */ |
| public int getRGB(int pixel) { |
| return (getAlpha(pixel) << 24) |
| | (getRed(pixel) << 16) |
| | (getGreen(pixel) << 8) |
| | (getBlue(pixel) << 0); |
| } |
| |
| /** |
| * Returns the red color component for the specified pixel, scaled |
| * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A |
| * color conversion is done if necessary. The pixel value is |
| * specified by an array of data elements of type transferType passed |
| * in as an object reference. The returned value is a non |
| * pre-multiplied value. For example, if alpha is premultiplied, |
| * this method divides it out before returning |
| * the value. If the alpha value is 0, the red value is 0. |
| * If {@code inData} is not a primitive array of type |
| * transferType, a {@code ClassCastException} is thrown. An |
| * {@code ArrayIndexOutOfBoundsException} is thrown if |
| * {@code inData} is not large enough to hold a pixel value for |
| * this {@code ColorModel}. |
| * If this {@code transferType} is not supported, a |
| * {@code UnsupportedOperationException} will be |
| * thrown. Since |
| * {@code ColorModel} is an abstract class, any instance |
| * must be an instance of a subclass. Subclasses inherit the |
| * implementation of this method and if they don't override it, this |
| * method throws an exception if the subclass uses a |
| * {@code transferType} other than |
| * {@code DataBuffer.TYPE_BYTE}, |
| * {@code DataBuffer.TYPE_USHORT}, or |
| * {@code DataBuffer.TYPE_INT}. |
| * @param inData an array of pixel values |
| * @return the value of the red component of the specified pixel. |
| * @throws ClassCastException if {@code inData} |
| * is not a primitive array of type {@code transferType} |
| * @throws ArrayIndexOutOfBoundsException if |
| * {@code inData} is not large enough to hold a pixel value |
| * for this {@code ColorModel} |
| * @throws UnsupportedOperationException if this |
| * {@code transferType} is not supported by this |
| * {@code ColorModel} |
| */ |
| public int getRed(Object inData) { |
| int pixel=0,length=0; |
| switch (transferType) { |
| case DataBuffer.TYPE_BYTE: |
| byte[] bdata = (byte[])inData; |
| pixel = bdata[0] & 0xff; |
| length = bdata.length; |
| break; |
| case DataBuffer.TYPE_USHORT: |
| short[] sdata = (short[])inData; |
| pixel = sdata[0] & 0xffff; |
| length = sdata.length; |
| break; |
| case DataBuffer.TYPE_INT: |
| int[] idata = (int[])inData; |
| pixel = idata[0]; |
| length = idata.length; |
| break; |
| default: |
| throw new UnsupportedOperationException("This method has not been "+ |
| "implemented for transferType " + transferType); |
| } |
| if (length == 1) { |
| return getRed(pixel); |
| } |
| else { |
| throw new UnsupportedOperationException |
| ("This method is not supported by this color model"); |
| } |
| } |
| |
| /** |
| * Returns the green color component for the specified pixel, scaled |
| * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A |
| * color conversion is done if necessary. The pixel value is |
| * specified by an array of data elements of type transferType passed |
| * in as an object reference. The returned value will be a non |
| * pre-multiplied value. For example, if the alpha is premultiplied, |
| * this method divides it out before returning the value. If the |
| * alpha value is 0, the green value is 0. If {@code inData} is |
| * not a primitive array of type transferType, a |
| * {@code ClassCastException} is thrown. An |
| * {@code ArrayIndexOutOfBoundsException} is thrown if |
| * {@code inData} is not large enough to hold a pixel value for |
| * this {@code ColorModel}. |
| * If this {@code transferType} is not supported, a |
| * {@code UnsupportedOperationException} will be |
| * thrown. Since |
| * {@code ColorModel} is an abstract class, any instance |
| * must be an instance of a subclass. Subclasses inherit the |
| * implementation of this method and if they don't override it, this |
| * method throws an exception if the subclass uses a |
| * {@code transferType} other than |
| * {@code DataBuffer.TYPE_BYTE}, |
| * {@code DataBuffer.TYPE_USHORT}, or |
| * {@code DataBuffer.TYPE_INT}. |
| * @param inData an array of pixel values |
| * @return the value of the green component of the specified pixel. |
| * @throws ClassCastException if {@code inData} |
| * is not a primitive array of type {@code transferType} |
| * @throws ArrayIndexOutOfBoundsException if |
| * {@code inData} is not large enough to hold a pixel value |
| * for this {@code ColorModel} |
| * @throws UnsupportedOperationException if this |
| * {@code transferType} is not supported by this |
| * {@code ColorModel} |
| */ |
| public int getGreen(Object inData) { |
| int pixel=0,length=0; |
| switch (transferType) { |
| case DataBuffer.TYPE_BYTE: |
| byte[] bdata = (byte[])inData; |
| pixel = bdata[0] & 0xff; |
| length = bdata.length; |
| break; |
| case DataBuffer.TYPE_USHORT: |
| short[] sdata = (short[])inData; |
| pixel = sdata[0] & 0xffff; |
| length = sdata.length; |
| break; |
| case DataBuffer.TYPE_INT: |
| int[] idata = (int[])inData; |
| pixel = idata[0]; |
| length = idata.length; |
| break; |
| default: |
| throw new UnsupportedOperationException("This method has not been "+ |
| "implemented for transferType " + transferType); |
| } |
| if (length == 1) { |
| return getGreen(pixel); |
| } |
| else { |
| throw new UnsupportedOperationException |
| ("This method is not supported by this color model"); |
| } |
| } |
| |
| /** |
| * Returns the blue color component for the specified pixel, scaled |
| * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. A |
| * color conversion is done if necessary. The pixel value is |
| * specified by an array of data elements of type transferType passed |
| * in as an object reference. The returned value is a non |
| * pre-multiplied value. For example, if the alpha is premultiplied, |
| * this method divides it out before returning the value. If the |
| * alpha value is 0, the blue value will be 0. If |
| * {@code inData} is not a primitive array of type transferType, |
| * a {@code ClassCastException} is thrown. An |
| * {@code ArrayIndexOutOfBoundsException} is |
| * thrown if {@code inData} is not large enough to hold a pixel |
| * value for this {@code ColorModel}. |
| * If this {@code transferType} is not supported, a |
| * {@code UnsupportedOperationException} will be |
| * thrown. Since |
| * {@code ColorModel} is an abstract class, any instance |
| * must be an instance of a subclass. Subclasses inherit the |
| * implementation of this method and if they don't override it, this |
| * method throws an exception if the subclass uses a |
| * {@code transferType} other than |
| * {@code DataBuffer.TYPE_BYTE}, |
| * {@code DataBuffer.TYPE_USHORT}, or |
| * {@code DataBuffer.TYPE_INT}. |
| * @param inData an array of pixel values |
| * @return the value of the blue component of the specified pixel. |
| * @throws ClassCastException if {@code inData} |
| * is not a primitive array of type {@code transferType} |
| * @throws ArrayIndexOutOfBoundsException if |
| * {@code inData} is not large enough to hold a pixel value |
| * for this {@code ColorModel} |
| * @throws UnsupportedOperationException if this |
| * {@code transferType} is not supported by this |
| * {@code ColorModel} |
| */ |
| public int getBlue(Object inData) { |
| int pixel=0,length=0; |
| switch (transferType) { |
| case DataBuffer.TYPE_BYTE: |
| byte[] bdata = (byte[])inData; |
| pixel = bdata[0] & 0xff; |
| length = bdata.length; |
| break; |
| case DataBuffer.TYPE_USHORT: |
| short[] sdata = (short[])inData; |
| pixel = sdata[0] & 0xffff; |
| length = sdata.length; |
| break; |
| case DataBuffer.TYPE_INT: |
| int[] idata = (int[])inData; |
| pixel = idata[0]; |
| length = idata.length; |
| break; |
| default: |
| throw new UnsupportedOperationException("This method has not been "+ |
| "implemented for transferType " + transferType); |
| } |
| if (length == 1) { |
| return getBlue(pixel); |
| } |
| else { |
| throw new UnsupportedOperationException |
| ("This method is not supported by this color model"); |
| } |
| } |
| |
| /** |
| * Returns the alpha component for the specified pixel, scaled |
| * from 0 to 255. The pixel value is specified by an array of data |
| * elements of type transferType passed in as an object reference. |
| * If inData is not a primitive array of type transferType, a |
| * {@code ClassCastException} is thrown. An |
| * {@code ArrayIndexOutOfBoundsException} is thrown if |
| * {@code inData} is not large enough to hold a pixel value for |
| * this {@code ColorModel}. |
| * If this {@code transferType} is not supported, a |
| * {@code UnsupportedOperationException} will be |
| * thrown. Since |
| * {@code ColorModel} is an abstract class, any instance |
| * must be an instance of a subclass. Subclasses inherit the |
| * implementation of this method and if they don't override it, this |
| * method throws an exception if the subclass uses a |
| * {@code transferType} other than |
| * {@code DataBuffer.TYPE_BYTE}, |
| * {@code DataBuffer.TYPE_USHORT}, or |
| * {@code DataBuffer.TYPE_INT}. |
| * @param inData the specified pixel |
| * @return the alpha component of the specified pixel, scaled from |
| * 0 to 255. |
| * @throws ClassCastException if {@code inData} |
| * is not a primitive array of type {@code transferType} |
| * @throws ArrayIndexOutOfBoundsException if |
| * {@code inData} is not large enough to hold a pixel value |
| * for this {@code ColorModel} |
| * @throws UnsupportedOperationException if this |
| * {@code tranferType} is not supported by this |
| * {@code ColorModel} |
| */ |
| public int getAlpha(Object inData) { |
| int pixel=0,length=0; |
| switch (transferType) { |
| case DataBuffer.TYPE_BYTE: |
| byte[] bdata = (byte[])inData; |
| pixel = bdata[0] & 0xff; |
| length = bdata.length; |
| break; |
| case DataBuffer.TYPE_USHORT: |
| short[] sdata = (short[])inData; |
| pixel = sdata[0] & 0xffff; |
| length = sdata.length; |
| break; |
| case DataBuffer.TYPE_INT: |
| int[] idata = (int[])inData; |
| pixel = idata[0]; |
| length = idata.length; |
| break; |
| default: |
| throw new UnsupportedOperationException("This method has not been "+ |
| "implemented for transferType " + transferType); |
| } |
| if (length == 1) { |
| return getAlpha(pixel); |
| } |
| else { |
| throw new UnsupportedOperationException |
| ("This method is not supported by this color model"); |
| } |
| } |
| |
| /** |
| * Returns the color/alpha components for the specified pixel in the |
| * default RGB color model format. A color conversion is done if |
| * necessary. The pixel value is specified by an array of data |
| * elements of type transferType passed in as an object reference. |
| * If inData is not a primitive array of type transferType, a |
| * {@code ClassCastException} is thrown. An |
| * {@code ArrayIndexOutOfBoundsException} is |
| * thrown if {@code inData} is not large enough to hold a pixel |
| * value for this {@code ColorModel}. |
| * The returned value will be in a non pre-multiplied format, i.e. if |
| * the alpha is premultiplied, this method will divide it out of the |
| * color components (if the alpha value is 0, the color values will be 0). |
| * @param inData the specified pixel |
| * @return the color and alpha components of the specified pixel. |
| * @see ColorModel#getRGBdefault |
| */ |
| public int getRGB(Object inData) { |
| return (getAlpha(inData) << 24) |
| | (getRed(inData) << 16) |
| | (getGreen(inData) << 8) |
| | (getBlue(inData) << 0); |
| } |
| |
| /** |
| * Returns a data element array representation of a pixel in this |
| * {@code ColorModel}, given an integer pixel representation in |
| * the default RGB color model. |
| * This array can then be passed to the |
| * {@link WritableRaster#setDataElements} method of |
| * a {@link WritableRaster} object. If the pixel variable is |
| * {@code null}, a new array will be allocated. If |
| * {@code pixel} is not |
| * {@code null}, it must be a primitive array of type |
| * {@code transferType}; otherwise, a |
| * {@code ClassCastException} is thrown. An |
| * {@code ArrayIndexOutOfBoundsException} is thrown if |
| * {@code pixel} is |
| * not large enough to hold a pixel value for this |
| * {@code ColorModel}. The pixel array is returned. |
| * If this {@code transferType} is not supported, a |
| * {@code UnsupportedOperationException} will be |
| * thrown. Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. Subclasses must |
| * override this method since the implementation in this abstract |
| * class throws an {@code UnsupportedOperationException}. |
| * @param rgb the integer pixel representation in the default RGB |
| * color model |
| * @param pixel the specified pixel |
| * @return an array representation of the specified pixel in this |
| * {@code ColorModel}. |
| * @throws ClassCastException if {@code pixel} |
| * is not a primitive array of type {@code transferType} |
| * @throws ArrayIndexOutOfBoundsException if |
| * {@code pixel} is not large enough to hold a pixel value |
| * for this {@code ColorModel} |
| * @throws UnsupportedOperationException if this |
| * method is not supported by this {@code ColorModel} |
| * @see WritableRaster#setDataElements |
| * @see SampleModel#setDataElements |
| */ |
| public Object getDataElements(int rgb, Object pixel) { |
| throw new UnsupportedOperationException |
| ("This method is not supported by this color model."); |
| } |
| |
| /** |
| * Returns an array of unnormalized color/alpha components given a pixel |
| * in this {@code ColorModel}. The pixel value is specified as |
| * an {@code int}. An {@code IllegalArgumentException} |
| * will be thrown if pixel values for this {@code ColorModel} are |
| * not conveniently representable as a single {@code int} or if |
| * color component values for this {@code ColorModel} are not |
| * conveniently representable in the unnormalized form. |
| * For example, this method can be used to retrieve the |
| * components for a specific pixel value in a |
| * {@code DirectColorModel}. If the components array is |
| * {@code null}, a new array will be allocated. The |
| * components array will be returned. Color/alpha components are |
| * stored in the components array starting at {@code offset} |
| * (even if the array is allocated by this method). An |
| * {@code ArrayIndexOutOfBoundsException} is thrown if the |
| * components array is not {@code null} and is not large |
| * enough to hold all the color and alpha components (starting at offset). |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. Subclasses must |
| * override this method since the implementation in this abstract |
| * class throws an {@code UnsupportedOperationException}. |
| * @param pixel the specified pixel |
| * @param components the array to receive the color and alpha |
| * components of the specified pixel |
| * @param offset the offset into the {@code components} array at |
| * which to start storing the color and alpha components |
| * @return an array containing the color and alpha components of the |
| * specified pixel starting at the specified offset. |
| * @throws UnsupportedOperationException if this |
| * method is not supported by this {@code ColorModel} |
| */ |
| public int[] getComponents(int pixel, int[] components, int offset) { |
| throw new UnsupportedOperationException |
| ("This method is not supported by this color model."); |
| } |
| |
| /** |
| * Returns an array of unnormalized color/alpha components given a pixel |
| * in this {@code ColorModel}. The pixel value is specified by |
| * an array of data elements of type transferType passed in as an |
| * object reference. If {@code pixel} is not a primitive array |
| * of type transferType, a {@code ClassCastException} is thrown. |
| * An {@code IllegalArgumentException} will be thrown if color |
| * component values for this {@code ColorModel} are not |
| * conveniently representable in the unnormalized form. |
| * An {@code ArrayIndexOutOfBoundsException} is |
| * thrown if {@code pixel} is not large enough to hold a pixel |
| * value for this {@code ColorModel}. |
| * This method can be used to retrieve the components for a specific |
| * pixel value in any {@code ColorModel}. If the components |
| * array is {@code null}, a new array will be allocated. The |
| * components array will be returned. Color/alpha components are |
| * stored in the {@code components} array starting at |
| * {@code offset} (even if the array is allocated by this |
| * method). An {@code ArrayIndexOutOfBoundsException} |
| * is thrown if the components array is not {@code null} and is |
| * not large enough to hold all the color and alpha components |
| * (starting at {@code offset}). |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. Subclasses must |
| * override this method since the implementation in this abstract |
| * class throws an {@code UnsupportedOperationException}. |
| * @param pixel the specified pixel |
| * @param components an array that receives the color and alpha |
| * components of the specified pixel |
| * @param offset the index into the {@code components} array at |
| * which to begin storing the color and alpha components of the |
| * specified pixel |
| * @return an array containing the color and alpha components of the |
| * specified pixel starting at the specified offset. |
| * @throws UnsupportedOperationException if this |
| * method is not supported by this {@code ColorModel} |
| */ |
| public int[] getComponents(Object pixel, int[] components, int offset) { |
| throw new UnsupportedOperationException |
| ("This method is not supported by this color model."); |
| } |
| |
| /** |
| * Returns an array of all of the color/alpha components in unnormalized |
| * form, given a normalized component array. Unnormalized components |
| * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where |
| * n is the number of bits for a particular component. Normalized |
| * components are float values between a per component minimum and |
| * maximum specified by the {@code ColorSpace} object for this |
| * {@code ColorModel}. An {@code IllegalArgumentException} |
| * will be thrown if color component values for this |
| * {@code ColorModel} are not conveniently representable in the |
| * unnormalized form. If the |
| * {@code components} array is {@code null}, a new array |
| * will be allocated. The {@code components} array will |
| * be returned. Color/alpha components are stored in the |
| * {@code components} array starting at {@code offset} (even |
| * if the array is allocated by this method). An |
| * {@code ArrayIndexOutOfBoundsException} is thrown if the |
| * {@code components} array is not {@code null} and is not |
| * large enough to hold all the color and alpha |
| * components (starting at {@code offset}). An |
| * {@code IllegalArgumentException} is thrown if the |
| * {@code normComponents} array is not large enough to hold |
| * all the color and alpha components starting at |
| * {@code normOffset}. |
| * @param normComponents an array containing normalized components |
| * @param normOffset the offset into the {@code normComponents} |
| * array at which to start retrieving normalized components |
| * @param components an array that receives the components from |
| * {@code normComponents} |
| * @param offset the index into {@code components} at which to |
| * begin storing normalized components from |
| * {@code normComponents} |
| * @return an array containing unnormalized color and alpha |
| * components. |
| * @throws IllegalArgumentException If the component values for this |
| * {@code ColorModel} are not conveniently representable in the |
| * unnormalized form. |
| * @throws IllegalArgumentException if the length of |
| * {@code normComponents} minus {@code normOffset} |
| * is less than {@code numComponents} |
| * @throws UnsupportedOperationException if the |
| * constructor of this {@code ColorModel} called the |
| * {@code super(bits)} constructor, but did not |
| * override this method. See the constructor, |
| * {@link #ColorModel(int)}. |
| */ |
| public int[] getUnnormalizedComponents(float[] normComponents, |
| int normOffset, |
| int[] components, int offset) { |
| // Make sure that someone isn't using a custom color model |
| // that called the super(bits) constructor. |
| if (colorSpace == null) { |
| throw new UnsupportedOperationException("This method is not supported "+ |
| "by this color model."); |
| } |
| |
| if (nBits == null) { |
| throw new UnsupportedOperationException ("This method is not supported. "+ |
| "Unable to determine #bits per "+ |
| "component."); |
| } |
| if ((normComponents.length - normOffset) < numComponents) { |
| throw new |
| IllegalArgumentException( |
| "Incorrect number of components. Expecting "+ |
| numComponents); |
| } |
| |
| if (components == null) { |
| components = new int[offset+numComponents]; |
| } |
| |
| if (supportsAlpha && isAlphaPremultiplied) { |
| float normAlpha = normComponents[normOffset+numColorComponents]; |
| for (int i=0; i < numColorComponents; i++) { |
| components[offset+i] = (int) (normComponents[normOffset+i] |
| * ((1<<nBits[i]) - 1) |
| * normAlpha + 0.5f); |
| } |
| components[offset+numColorComponents] = (int) |
| (normAlpha * ((1<<nBits[numColorComponents]) - 1) + 0.5f); |
| } |
| else { |
| for (int i=0; i < numComponents; i++) { |
| components[offset+i] = (int) (normComponents[normOffset+i] |
| * ((1<<nBits[i]) - 1) + 0.5f); |
| } |
| } |
| |
| return components; |
| } |
| |
| /** |
| * Returns an array of all of the color/alpha components in normalized |
| * form, given an unnormalized component array. Unnormalized components |
| * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where |
| * n is the number of bits for a particular component. Normalized |
| * components are float values between a per component minimum and |
| * maximum specified by the {@code ColorSpace} object for this |
| * {@code ColorModel}. An {@code IllegalArgumentException} |
| * will be thrown if color component values for this |
| * {@code ColorModel} are not conveniently representable in the |
| * unnormalized form. If the |
| * {@code normComponents} array is {@code null}, a new array |
| * will be allocated. The {@code normComponents} array |
| * will be returned. Color/alpha components are stored in the |
| * {@code normComponents} array starting at |
| * {@code normOffset} (even if the array is allocated by this |
| * method). An {@code ArrayIndexOutOfBoundsException} is thrown |
| * if the {@code normComponents} array is not {@code null} |
| * and is not large enough to hold all the color and alpha components |
| * (starting at {@code normOffset}). An |
| * {@code IllegalArgumentException} is thrown if the |
| * {@code components} array is not large enough to hold all the |
| * color and alpha components starting at {@code offset}. |
| * <p> |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. The default implementation |
| * of this method in this abstract class assumes that component values |
| * for this class are conveniently representable in the unnormalized |
| * form. Therefore, subclasses which may |
| * have instances which do not support the unnormalized form must |
| * override this method. |
| * @param components an array containing unnormalized components |
| * @param offset the offset into the {@code components} array at |
| * which to start retrieving unnormalized components |
| * @param normComponents an array that receives the normalized components |
| * @param normOffset the index into {@code normComponents} at |
| * which to begin storing normalized components |
| * @return an array containing normalized color and alpha |
| * components. |
| * @throws IllegalArgumentException If the component values for this |
| * {@code ColorModel} are not conveniently representable in the |
| * unnormalized form. |
| * @throws UnsupportedOperationException if the |
| * constructor of this {@code ColorModel} called the |
| * {@code super(bits)} constructor, but did not |
| * override this method. See the constructor, |
| * {@link #ColorModel(int)}. |
| * @throws UnsupportedOperationException if this method is unable |
| * to determine the number of bits per component |
| */ |
| public float[] getNormalizedComponents(int[] components, int offset, |
| float[] normComponents, |
| int normOffset) { |
| // Make sure that someone isn't using a custom color model |
| // that called the super(bits) constructor. |
| if (colorSpace == null) { |
| throw new UnsupportedOperationException("This method is not supported by "+ |
| "this color model."); |
| } |
| if (nBits == null) { |
| throw new UnsupportedOperationException ("This method is not supported. "+ |
| "Unable to determine #bits per "+ |
| "component."); |
| } |
| |
| if ((components.length - offset) < numComponents) { |
| throw new |
| IllegalArgumentException( |
| "Incorrect number of components. Expecting "+ |
| numComponents); |
| } |
| |
| if (normComponents == null) { |
| normComponents = new float[numComponents+normOffset]; |
| } |
| |
| if (supportsAlpha && isAlphaPremultiplied) { |
| // Normalized coordinates are non premultiplied |
| float normAlpha = (float)components[offset+numColorComponents]; |
| normAlpha /= (float) ((1<<nBits[numColorComponents]) - 1); |
| if (normAlpha != 0.0f) { |
| for (int i=0; i < numColorComponents; i++) { |
| normComponents[normOffset+i] = |
| ((float) components[offset+i]) / |
| (normAlpha * ((float) ((1<<nBits[i]) - 1))); |
| } |
| } else { |
| for (int i=0; i < numColorComponents; i++) { |
| normComponents[normOffset+i] = 0.0f; |
| } |
| } |
| normComponents[normOffset+numColorComponents] = normAlpha; |
| } |
| else { |
| for (int i=0; i < numComponents; i++) { |
| normComponents[normOffset+i] = ((float) components[offset+i]) / |
| ((float) ((1<<nBits[i]) - 1)); |
| } |
| } |
| |
| return normComponents; |
| } |
| |
| /** |
| * Returns a pixel value represented as an {@code int} in this |
| * {@code ColorModel}, given an array of unnormalized color/alpha |
| * components. This method will throw an |
| * {@code IllegalArgumentException} if component values for this |
| * {@code ColorModel} are not conveniently representable as a |
| * single {@code int} or if color component values for this |
| * {@code ColorModel} are not conveniently representable in the |
| * unnormalized form. An |
| * {@code ArrayIndexOutOfBoundsException} is thrown if the |
| * {@code components} array is not large enough to hold all the |
| * color and alpha components (starting at {@code offset}). |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. Subclasses must |
| * override this method since the implementation in this abstract |
| * class throws an {@code UnsupportedOperationException}. |
| * @param components an array of unnormalized color and alpha |
| * components |
| * @param offset the index into {@code components} at which to |
| * begin retrieving the color and alpha components |
| * @return an {@code int} pixel value in this |
| * {@code ColorModel} corresponding to the specified components. |
| * @throws IllegalArgumentException if |
| * pixel values for this {@code ColorModel} are not |
| * conveniently representable as a single {@code int} |
| * @throws IllegalArgumentException if |
| * component values for this {@code ColorModel} are not |
| * conveniently representable in the unnormalized form |
| * @throws ArrayIndexOutOfBoundsException if |
| * the {@code components} array is not large enough to |
| * hold all of the color and alpha components starting at |
| * {@code offset} |
| * @throws UnsupportedOperationException if this |
| * method is not supported by this {@code ColorModel} |
| */ |
| public int getDataElement(int[] components, int offset) { |
| throw new UnsupportedOperationException("This method is not supported "+ |
| "by this color model."); |
| } |
| |
| /** |
| * Returns a data element array representation of a pixel in this |
| * {@code ColorModel}, given an array of unnormalized color/alpha |
| * components. This array can then be passed to the |
| * {@code setDataElements} method of a {@code WritableRaster} |
| * object. This method will throw an {@code IllegalArgumentException} |
| * if color component values for this {@code ColorModel} are not |
| * conveniently representable in the unnormalized form. |
| * An {@code ArrayIndexOutOfBoundsException} is thrown |
| * if the {@code components} array is not large enough to hold |
| * all the color and alpha components (starting at |
| * {@code offset}). If the {@code obj} variable is |
| * {@code null}, a new array will be allocated. If |
| * {@code obj} is not {@code null}, it must be a primitive |
| * array of type transferType; otherwise, a |
| * {@code ClassCastException} is thrown. An |
| * {@code ArrayIndexOutOfBoundsException} is thrown if |
| * {@code obj} is not large enough to hold a pixel value for this |
| * {@code ColorModel}. |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. Subclasses must |
| * override this method since the implementation in this abstract |
| * class throws an {@code UnsupportedOperationException}. |
| * @param components an array of unnormalized color and alpha |
| * components |
| * @param offset the index into {@code components} at which to |
| * begin retrieving color and alpha components |
| * @param obj the {@code Object} representing an array of color |
| * and alpha components |
| * @return an {@code Object} representing an array of color and |
| * alpha components. |
| * @throws ClassCastException if {@code obj} |
| * is not a primitive array of type {@code transferType} |
| * @throws ArrayIndexOutOfBoundsException if |
| * {@code obj} is not large enough to hold a pixel value |
| * for this {@code ColorModel} or the {@code components} |
| * array is not large enough to hold all of the color and alpha |
| * components starting at {@code offset} |
| * @throws IllegalArgumentException if |
| * component values for this {@code ColorModel} are not |
| * conveniently representable in the unnormalized form |
| * @throws UnsupportedOperationException if this |
| * method is not supported by this {@code ColorModel} |
| * @see WritableRaster#setDataElements |
| * @see SampleModel#setDataElements |
| */ |
| public Object getDataElements(int[] components, int offset, Object obj) { |
| throw new UnsupportedOperationException("This method has not been implemented "+ |
| "for this color model."); |
| } |
| |
| /** |
| * Returns a pixel value represented as an {@code int} in this |
| * {@code ColorModel}, given an array of normalized color/alpha |
| * components. This method will throw an |
| * {@code IllegalArgumentException} if pixel values for this |
| * {@code ColorModel} are not conveniently representable as a |
| * single {@code int}. An |
| * {@code ArrayIndexOutOfBoundsException} is thrown if the |
| * {@code normComponents} array is not large enough to hold all the |
| * color and alpha components (starting at {@code normOffset}). |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. The default implementation |
| * of this method in this abstract class first converts from the |
| * normalized form to the unnormalized form and then calls |
| * {@code getDataElement(int[], int)}. Subclasses which may |
| * have instances which do not support the unnormalized form must |
| * override this method. |
| * @param normComponents an array of normalized color and alpha |
| * components |
| * @param normOffset the index into {@code normComponents} at which to |
| * begin retrieving the color and alpha components |
| * @return an {@code int} pixel value in this |
| * {@code ColorModel} corresponding to the specified components. |
| * @throws IllegalArgumentException if |
| * pixel values for this {@code ColorModel} are not |
| * conveniently representable as a single {@code int} |
| * @throws ArrayIndexOutOfBoundsException if |
| * the {@code normComponents} array is not large enough to |
| * hold all of the color and alpha components starting at |
| * {@code normOffset} |
| * @since 1.4 |
| */ |
| public int getDataElement(float[] normComponents, int normOffset) { |
| int[] components = getUnnormalizedComponents(normComponents, |
| normOffset, null, 0); |
| return getDataElement(components, 0); |
| } |
| |
| /** |
| * Returns a data element array representation of a pixel in this |
| * {@code ColorModel}, given an array of normalized color/alpha |
| * components. This array can then be passed to the |
| * {@code setDataElements} method of a {@code WritableRaster} |
| * object. An {@code ArrayIndexOutOfBoundsException} is thrown |
| * if the {@code normComponents} array is not large enough to hold |
| * all the color and alpha components (starting at |
| * {@code normOffset}). If the {@code obj} variable is |
| * {@code null}, a new array will be allocated. If |
| * {@code obj} is not {@code null}, it must be a primitive |
| * array of type transferType; otherwise, a |
| * {@code ClassCastException} is thrown. An |
| * {@code ArrayIndexOutOfBoundsException} is thrown if |
| * {@code obj} is not large enough to hold a pixel value for this |
| * {@code ColorModel}. |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. The default implementation |
| * of this method in this abstract class first converts from the |
| * normalized form to the unnormalized form and then calls |
| * {@code getDataElement(int[], int, Object)}. Subclasses which may |
| * have instances which do not support the unnormalized form must |
| * override this method. |
| * @param normComponents an array of normalized color and alpha |
| * components |
| * @param normOffset the index into {@code normComponents} at which to |
| * begin retrieving color and alpha components |
| * @param obj a primitive data array to hold the returned pixel |
| * @return an {@code Object} which is a primitive data array |
| * representation of a pixel |
| * @throws ClassCastException if {@code obj} |
| * is not a primitive array of type {@code transferType} |
| * @throws ArrayIndexOutOfBoundsException if |
| * {@code obj} is not large enough to hold a pixel value |
| * for this {@code ColorModel} or the {@code normComponents} |
| * array is not large enough to hold all of the color and alpha |
| * components starting at {@code normOffset} |
| * @see WritableRaster#setDataElements |
| * @see SampleModel#setDataElements |
| * @since 1.4 |
| */ |
| public Object getDataElements(float[] normComponents, int normOffset, |
| Object obj) { |
| int[] components = getUnnormalizedComponents(normComponents, |
| normOffset, null, 0); |
| return getDataElements(components, 0, obj); |
| } |
| |
| /** |
| * Returns an array of all of the color/alpha components in normalized |
| * form, given a pixel in this {@code ColorModel}. The pixel |
| * value is specified by an array of data elements of type transferType |
| * passed in as an object reference. If pixel is not a primitive array |
| * of type transferType, a {@code ClassCastException} is thrown. |
| * An {@code ArrayIndexOutOfBoundsException} is thrown if |
| * {@code pixel} is not large enough to hold a pixel value for this |
| * {@code ColorModel}. |
| * Normalized components are float values between a per component minimum |
| * and maximum specified by the {@code ColorSpace} object for this |
| * {@code ColorModel}. If the |
| * {@code normComponents} array is {@code null}, a new array |
| * will be allocated. The {@code normComponents} array |
| * will be returned. Color/alpha components are stored in the |
| * {@code normComponents} array starting at |
| * {@code normOffset} (even if the array is allocated by this |
| * method). An {@code ArrayIndexOutOfBoundsException} is thrown |
| * if the {@code normComponents} array is not {@code null} |
| * and is not large enough to hold all the color and alpha components |
| * (starting at {@code normOffset}). |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. The default implementation |
| * of this method in this abstract class first retrieves color and alpha |
| * components in the unnormalized form using |
| * {@code getComponents(Object, int[], int)} and then calls |
| * {@code getNormalizedComponents(int[], int, float[], int)}. |
| * Subclasses which may |
| * have instances which do not support the unnormalized form must |
| * override this method. |
| * @param pixel the specified pixel |
| * @param normComponents an array to receive the normalized components |
| * @param normOffset the offset into the {@code normComponents} |
| * array at which to start storing normalized components |
| * @return an array containing normalized color and alpha |
| * components. |
| * @throws ClassCastException if {@code pixel} is not a primitive |
| * array of type transferType |
| * @throws ArrayIndexOutOfBoundsException if |
| * {@code normComponents} is not large enough to hold all |
| * color and alpha components starting at {@code normOffset} |
| * @throws ArrayIndexOutOfBoundsException if |
| * {@code pixel} is not large enough to hold a pixel |
| * value for this {@code ColorModel}. |
| * @throws UnsupportedOperationException if the |
| * constructor of this {@code ColorModel} called the |
| * {@code super(bits)} constructor, but did not |
| * override this method. See the constructor, |
| * {@link #ColorModel(int)}. |
| * @throws UnsupportedOperationException if this method is unable |
| * to determine the number of bits per component |
| * @since 1.4 |
| */ |
| public float[] getNormalizedComponents(Object pixel, |
| float[] normComponents, |
| int normOffset) { |
| int[] components = getComponents(pixel, null, 0); |
| return getNormalizedComponents(components, 0, |
| normComponents, normOffset); |
| } |
| |
| /** |
| * This method simply delegates to the default implementation in {@code Object} |
| * which is identical to an {@code ==} test since this class cannot enforce the |
| * issues of a proper equality test among multiple independent subclass |
| * branches. |
| * Subclasses are encouraged to override this method and provide equality |
| * testing for their own properties in addition to equality tests for the |
| * following common base properties of {@code ColorModel}: |
| * <ul> |
| * <li>Support for alpha component.</li> |
| * <li>Is alpha premultiplied.</li> |
| * <li>Number of bits per pixel.</li> |
| * <li>Type of transparency like Opaque, Bitmask or Translucent.</li> |
| * <li>Number of components in a pixel.</li> |
| * <li>{@code ColorSpace} type.</li> |
| * <li>Type of the array used to represent pixel values.</li> |
| * <li>Number of significant bits per color and alpha component.</li> |
| * </ul> |
| * @param obj the reference object with which to compare. |
| * @return {@code true} if this object is the same as the obj |
| * argument; {@code false} otherwise. |
| */ |
| @Override |
| public boolean equals(Object obj) { |
| return super.equals(obj); |
| } |
| |
| /** |
| * This method simply delegates to the default implementation in {@code Object} |
| * which returns the system ID for the class. |
| * Subclasses are encouraged to override this method and provide a hash |
| * for their own properties in addition to hashing the values of the |
| * following common base properties of {@code ColorModel}: |
| * <ul> |
| * <li>Support for alpha component.</li> |
| * <li>Is alpha premultiplied.</li> |
| * <li>Number of bits per pixel.</li> |
| * <li>Type of transparency like Opaque, Bitmask or Translucent.</li> |
| * <li>Number of components in a pixel.</li> |
| * <li>{@code ColorSpace} type.</li> |
| * <li>Type of the array used to represent pixel values.</li> |
| * <li>Number of significant bits per color and alpha component.</li> |
| * </ul> |
| * @return a hash code value for this object. |
| */ |
| @Override |
| public int hashCode() { |
| return super.hashCode(); |
| } |
| |
| /** |
| * Returns the {@code ColorSpace} associated with this |
| * {@code ColorModel}. |
| * @return the {@code ColorSpace} of this |
| * {@code ColorModel}. |
| */ |
| public final ColorSpace getColorSpace() { |
| return colorSpace; |
| } |
| |
| /** |
| * Forces the raster data to match the state specified in the |
| * {@code isAlphaPremultiplied} variable, assuming the data is |
| * currently correctly described by this {@code ColorModel}. It |
| * may multiply or divide the color raster data by alpha, or do |
| * nothing if the data is in the correct state. If the data needs to |
| * be coerced, this method will also return an instance of this |
| * {@code ColorModel} with the {@code isAlphaPremultiplied} |
| * flag set appropriately. This method will throw a |
| * {@code UnsupportedOperationException} if it is not supported |
| * by this {@code ColorModel}. |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. Subclasses must |
| * override this method since the implementation in this abstract |
| * class throws an {@code UnsupportedOperationException}. |
| * @param raster the {@code WritableRaster} data |
| * @param isAlphaPremultiplied {@code true} if the alpha is |
| * premultiplied; {@code false} otherwise |
| * @return a {@code ColorModel} object that represents the |
| * coerced data. |
| */ |
| public ColorModel coerceData (WritableRaster raster, |
| boolean isAlphaPremultiplied) { |
| throw new UnsupportedOperationException |
| ("This method is not supported by this color model"); |
| } |
| |
| /** |
| * Returns {@code true} if {@code raster} is compatible |
| * with this {@code ColorModel} and {@code false} if it is |
| * not. |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. Subclasses must |
| * override this method since the implementation in this abstract |
| * class throws an {@code UnsupportedOperationException}. |
| * @param raster the {@link Raster} object to test for compatibility |
| * @return {@code true} if {@code raster} is compatible |
| * with this {@code ColorModel}. |
| * @throws UnsupportedOperationException if this |
| * method has not been implemented for this |
| * {@code ColorModel} |
| */ |
| public boolean isCompatibleRaster(Raster raster) { |
| throw new UnsupportedOperationException( |
| "This method has not been implemented for this ColorModel."); |
| } |
| |
| /** |
| * Creates a {@code WritableRaster} with the specified width and |
| * height that has a data layout ({@code SampleModel}) compatible |
| * with this {@code ColorModel}. |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. Subclasses must |
| * override this method since the implementation in this abstract |
| * class throws an {@code UnsupportedOperationException}. |
| * @param w the width to apply to the new {@code WritableRaster} |
| * @param h the height to apply to the new {@code WritableRaster} |
| * @return a {@code WritableRaster} object with the specified |
| * width and height. |
| * @throws UnsupportedOperationException if this |
| * method is not supported by this {@code ColorModel} |
| * @see WritableRaster |
| * @see SampleModel |
| */ |
| public WritableRaster createCompatibleWritableRaster(int w, int h) { |
| throw new UnsupportedOperationException |
| ("This method is not supported by this color model"); |
| } |
| |
| /** |
| * Creates a {@code SampleModel} with the specified width and |
| * height that has a data layout compatible with this |
| * {@code ColorModel}. |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. Subclasses must |
| * override this method since the implementation in this abstract |
| * class throws an {@code UnsupportedOperationException}. |
| * @param w the width to apply to the new {@code SampleModel} |
| * @param h the height to apply to the new {@code SampleModel} |
| * @return a {@code SampleModel} object with the specified |
| * width and height. |
| * @throws UnsupportedOperationException if this |
| * method is not supported by this {@code ColorModel} |
| * @see SampleModel |
| */ |
| public SampleModel createCompatibleSampleModel(int w, int h) { |
| throw new UnsupportedOperationException |
| ("This method is not supported by this color model"); |
| } |
| |
| /** Checks if the {@code SampleModel} is compatible with this |
| * {@code ColorModel}. |
| * Since {@code ColorModel} is an abstract class, |
| * any instance is an instance of a subclass. Subclasses must |
| * override this method since the implementation in this abstract |
| * class throws an {@code UnsupportedOperationException}. |
| * @param sm the specified {@code SampleModel} |
| * @return {@code true} if the specified {@code SampleModel} |
| * is compatible with this {@code ColorModel}; {@code false} |
| * otherwise. |
| * @throws UnsupportedOperationException if this |
| * method is not supported by this {@code ColorModel} |
| * @see SampleModel |
| */ |
| public boolean isCompatibleSampleModel(SampleModel sm) { |
| throw new UnsupportedOperationException |
| ("This method is not supported by this color model"); |
| } |
| |
| /** |
| * Disposes of system resources associated with this |
| * {@code ColorModel} once this {@code ColorModel} is no |
| * longer referenced. |
| * |
| * @deprecated The {@code finalize} method has been deprecated. |
| * Subclasses that override {@code finalize} in order to perform cleanup |
| * should be modified to use alternative cleanup mechanisms and |
| * to remove the overriding {@code finalize} method. |
| * When overriding the {@code finalize} method, its implementation must explicitly |
| * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}. |
| * See the specification for {@link Object#finalize()} for further |
| * information about migration options. |
| */ |
| @Deprecated(since = "9", forRemoval = true) |
| @SuppressWarnings("removal") |
| public void finalize() { |
| } |
| |
| |
| /** |
| * Returns a {@code Raster} representing the alpha channel of an |
| * image, extracted from the input {@code Raster}, provided that |
| * pixel values of this {@code ColorModel} represent color and |
| * alpha information as separate spatial bands (e.g. |
| * {@link ComponentColorModel} and {@code DirectColorModel}). |
| * This method assumes that {@code Raster} objects associated |
| * with such a {@code ColorModel} store the alpha band, if |
| * present, as the last band of image data. Returns {@code null} |
| * if there is no separate spatial alpha channel associated with this |
| * {@code ColorModel}. If this is an |
| * {@code IndexColorModel} which has alpha in the lookup table, |
| * this method will return {@code null} since |
| * there is no spatially discrete alpha channel. |
| * This method will create a new {@code Raster} (but will share |
| * the data array). |
| * Since {@code ColorModel} is an abstract class, any instance |
| * is an instance of a subclass. Subclasses must override this |
| * method to get any behavior other than returning {@code null} |
| * because the implementation in this abstract class returns |
| * {@code null}. |
| * @param raster the specified {@code Raster} |
| * @return a {@code Raster} representing the alpha channel of |
| * an image, obtained from the specified {@code Raster}. |
| */ |
| public WritableRaster getAlphaRaster(WritableRaster raster) { |
| return null; |
| } |
| |
| /** |
| * Returns the {@code String} representation of the contents of |
| * this {@code ColorModel} object. |
| * @return a {@code String} representing the contents of this |
| * {@code ColorModel} object. |
| */ |
| public String toString() { |
| return new String("ColorModel: #pixelBits = "+pixel_bits |
| + " numComponents = "+numComponents |
| + " color space = "+colorSpace |
| + " transparency = "+transparency |
| + " has alpha = "+supportsAlpha |
| + " isAlphaPre = "+isAlphaPremultiplied |
| ); |
| } |
| |
| static int getDefaultTransferType(int pixel_bits) { |
| if (pixel_bits <= 8) { |
| return DataBuffer.TYPE_BYTE; |
| } else if (pixel_bits <= 16) { |
| return DataBuffer.TYPE_USHORT; |
| } else if (pixel_bits <= 32) { |
| return DataBuffer.TYPE_INT; |
| } else { |
| return DataBuffer.TYPE_UNDEFINED; |
| } |
| } |
| |
| static byte[] l8Tos8 = null; // 8-bit linear to 8-bit non-linear sRGB LUT |
| static byte[] s8Tol8 = null; // 8-bit non-linear sRGB to 8-bit linear LUT |
| static byte[] l16Tos8 = null; // 16-bit linear to 8-bit non-linear sRGB LUT |
| static short[] s8Tol16 = null; // 8-bit non-linear sRGB to 16-bit linear LUT |
| |
| // Maps to hold LUTs for grayscale conversions |
| static Map<ICC_ColorSpace, byte[]> g8Tos8Map = null; // 8-bit gray values to 8-bit sRGB values |
| static Map<ICC_ColorSpace, byte[]> lg16Toog8Map = null; // 16-bit linear to 8-bit "other" gray |
| static Map<ICC_ColorSpace, byte[]> g16Tos8Map = null; // 16-bit gray values to 8-bit sRGB values |
| static Map<ICC_ColorSpace, short[]> lg16Toog16Map = null; // 16-bit linear to 16-bit "other" gray |
| |
| static boolean isLinearRGBspace(ColorSpace cs) { |
| return cs == ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); |
| } |
| |
| static boolean isLinearGRAYspace(ColorSpace cs) { |
| return cs == ColorSpace.getInstance(ColorSpace.CS_GRAY); |
| } |
| |
| static byte[] getLinearRGB8TosRGB8LUT() { |
| if (l8Tos8 == null) { |
| l8Tos8 = new byte[256]; |
| float input, output; |
| // algorithm for linear RGB to nonlinear sRGB conversion |
| // is from the IEC 61966-2-1 International Standard, |
| // Colour Management - Default RGB colour space - sRGB, |
| // First Edition, 1999-10, |
| // available for order at http://www.iec.ch |
| for (int i = 0; i <= 255; i++) { |
| input = ((float) i) / 255.0f; |
| if (input <= 0.0031308f) { |
| output = input * 12.92f; |
| } else { |
| output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4))) |
| - 0.055f; |
| } |
| l8Tos8[i] = (byte) Math.round(output * 255.0f); |
| } |
| } |
| return l8Tos8; |
| } |
| |
| static byte[] getsRGB8ToLinearRGB8LUT() { |
| if (s8Tol8 == null) { |
| s8Tol8 = new byte[256]; |
| float input, output; |
| // algorithm from IEC 61966-2-1 International Standard |
| for (int i = 0; i <= 255; i++) { |
| input = ((float) i) / 255.0f; |
| if (input <= 0.04045f) { |
| output = input / 12.92f; |
| } else { |
| output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4); |
| } |
| s8Tol8[i] = (byte) Math.round(output * 255.0f); |
| } |
| } |
| return s8Tol8; |
| } |
| |
| static byte[] getLinearRGB16TosRGB8LUT() { |
| if (l16Tos8 == null) { |
| l16Tos8 = new byte[65536]; |
| float input, output; |
| // algorithm from IEC 61966-2-1 International Standard |
| for (int i = 0; i <= 65535; i++) { |
| input = ((float) i) / 65535.0f; |
| if (input <= 0.0031308f) { |
| output = input * 12.92f; |
| } else { |
| output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4))) |
| - 0.055f; |
| } |
| l16Tos8[i] = (byte) Math.round(output * 255.0f); |
| } |
| } |
| return l16Tos8; |
| } |
| |
| static short[] getsRGB8ToLinearRGB16LUT() { |
| if (s8Tol16 == null) { |
| s8Tol16 = new short[256]; |
| float input, output; |
| // algorithm from IEC 61966-2-1 International Standard |
| for (int i = 0; i <= 255; i++) { |
| input = ((float) i) / 255.0f; |
| if (input <= 0.04045f) { |
| output = input / 12.92f; |
| } else { |
| output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4); |
| } |
| s8Tol16[i] = (short) Math.round(output * 65535.0f); |
| } |
| } |
| return s8Tol16; |
| } |
| |
| /* |
| * Return a byte LUT that converts 8-bit gray values in the grayCS |
| * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut |
| * is the byte array returned by this method and sval = lut[gval], |
| * then the sRGB triple (sval,sval,sval) is the best match to gval. |
| * Cache references to any computed LUT in a Map. |
| */ |
| static byte[] getGray8TosRGB8LUT(ICC_ColorSpace grayCS) { |
| if (isLinearGRAYspace(grayCS)) { |
| return getLinearRGB8TosRGB8LUT(); |
| } |
| if (g8Tos8Map != null) { |
| byte[] g8Tos8LUT = g8Tos8Map.get(grayCS); |
| if (g8Tos8LUT != null) { |
| return g8Tos8LUT; |
| } |
| } |
| byte[] g8Tos8LUT = new byte[256]; |
| for (int i = 0; i <= 255; i++) { |
| g8Tos8LUT[i] = (byte) i; |
| } |
| ColorTransform[] transformList = new ColorTransform[2]; |
| PCMM mdl = CMSManager.getModule(); |
| ICC_ColorSpace srgbCS = |
| (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB); |
| transformList[0] = mdl.createTransform( |
| grayCS.getProfile(), ColorTransform.Any, ColorTransform.In); |
| transformList[1] = mdl.createTransform( |
| srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out); |
| ColorTransform t = mdl.createTransform(transformList); |
| byte[] tmp = t.colorConvert(g8Tos8LUT, null); |
| for (int i = 0, j= 2; i <= 255; i++, j += 3) { |
| // All three components of tmp should be equal, since |
| // the input color space to colorConvert is a gray scale |
| // space. However, there are slight anomalies in the results. |
| // Copy tmp starting at index 2, since colorConvert seems |
| // to be slightly more accurate for the third component! |
| g8Tos8LUT[i] = tmp[j]; |
| } |
| if (g8Tos8Map == null) { |
| g8Tos8Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, byte[]>(2)); |
| } |
| g8Tos8Map.put(grayCS, g8Tos8LUT); |
| return g8Tos8LUT; |
| } |
| |
| /* |
| * Return a byte LUT that converts 16-bit gray values in the CS_GRAY |
| * linear gray ColorSpace to the appropriate 8-bit value in the |
| * grayCS ColorSpace. Cache references to any computed LUT in a Map. |
| */ |
| static byte[] getLinearGray16ToOtherGray8LUT(ICC_ColorSpace grayCS) { |
| if (lg16Toog8Map != null) { |
| byte[] lg16Toog8LUT = lg16Toog8Map.get(grayCS); |
| if (lg16Toog8LUT != null) { |
| return lg16Toog8LUT; |
| } |
| } |
| short[] tmp = new short[65536]; |
| for (int i = 0; i <= 65535; i++) { |
| tmp[i] = (short) i; |
| } |
| ColorTransform[] transformList = new ColorTransform[2]; |
| PCMM mdl = CMSManager.getModule(); |
| ICC_ColorSpace lgCS = |
| (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY); |
| transformList[0] = mdl.createTransform ( |
| lgCS.getProfile(), ColorTransform.Any, ColorTransform.In); |
| transformList[1] = mdl.createTransform ( |
| grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out); |
| ColorTransform t = mdl.createTransform(transformList); |
| tmp = t.colorConvert(tmp, null); |
| byte[] lg16Toog8LUT = new byte[65536]; |
| for (int i = 0; i <= 65535; i++) { |
| // scale unsigned short (0 - 65535) to unsigned byte (0 - 255) |
| lg16Toog8LUT[i] = |
| (byte) (((float) (tmp[i] & 0xffff)) * (1.0f /257.0f) + 0.5f); |
| } |
| if (lg16Toog8Map == null) { |
| lg16Toog8Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, byte[]>(2)); |
| } |
| lg16Toog8Map.put(grayCS, lg16Toog8LUT); |
| return lg16Toog8LUT; |
| } |
| |
| /* |
| * Return a byte LUT that converts 16-bit gray values in the grayCS |
| * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut |
| * is the byte array returned by this method and sval = lut[gval], |
| * then the sRGB triple (sval,sval,sval) is the best match to gval. |
| * Cache references to any computed LUT in a Map. |
| */ |
| static byte[] getGray16TosRGB8LUT(ICC_ColorSpace grayCS) { |
| if (isLinearGRAYspace(grayCS)) { |
| return getLinearRGB16TosRGB8LUT(); |
| } |
| if (g16Tos8Map != null) { |
| byte[] g16Tos8LUT = g16Tos8Map.get(grayCS); |
| if (g16Tos8LUT != null) { |
| return g16Tos8LUT; |
| } |
| } |
| short[] tmp = new short[65536]; |
| for (int i = 0; i <= 65535; i++) { |
| tmp[i] = (short) i; |
| } |
| ColorTransform[] transformList = new ColorTransform[2]; |
| PCMM mdl = CMSManager.getModule(); |
| ICC_ColorSpace srgbCS = |
| (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB); |
| transformList[0] = mdl.createTransform ( |
| grayCS.getProfile(), ColorTransform.Any, ColorTransform.In); |
| transformList[1] = mdl.createTransform ( |
| srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out); |
| ColorTransform t = mdl.createTransform(transformList); |
| tmp = t.colorConvert(tmp, null); |
| byte[] g16Tos8LUT = new byte[65536]; |
| for (int i = 0, j= 2; i <= 65535; i++, j += 3) { |
| // All three components of tmp should be equal, since |
| // the input color space to colorConvert is a gray scale |
| // space. However, there are slight anomalies in the results. |
| // Copy tmp starting at index 2, since colorConvert seems |
| // to be slightly more accurate for the third component! |
| |
| // scale unsigned short (0 - 65535) to unsigned byte (0 - 255) |
| g16Tos8LUT[i] = |
| (byte) (((float) (tmp[j] & 0xffff)) * (1.0f /257.0f) + 0.5f); |
| } |
| if (g16Tos8Map == null) { |
| g16Tos8Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, byte[]>(2)); |
| } |
| g16Tos8Map.put(grayCS, g16Tos8LUT); |
| return g16Tos8LUT; |
| } |
| |
| /* |
| * Return a short LUT that converts 16-bit gray values in the CS_GRAY |
| * linear gray ColorSpace to the appropriate 16-bit value in the |
| * grayCS ColorSpace. Cache references to any computed LUT in a Map. |
| */ |
| static short[] getLinearGray16ToOtherGray16LUT(ICC_ColorSpace grayCS) { |
| if (lg16Toog16Map != null) { |
| short[] lg16Toog16LUT = lg16Toog16Map.get(grayCS); |
| if (lg16Toog16LUT != null) { |
| return lg16Toog16LUT; |
| } |
| } |
| short[] tmp = new short[65536]; |
| for (int i = 0; i <= 65535; i++) { |
| tmp[i] = (short) i; |
| } |
| ColorTransform[] transformList = new ColorTransform[2]; |
| PCMM mdl = CMSManager.getModule(); |
| ICC_ColorSpace lgCS = |
| (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY); |
| transformList[0] = mdl.createTransform ( |
| lgCS.getProfile(), ColorTransform.Any, ColorTransform.In); |
| transformList[1] = mdl.createTransform( |
| grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out); |
| ColorTransform t = mdl.createTransform( |
| transformList); |
| short[] lg16Toog16LUT = t.colorConvert(tmp, null); |
| if (lg16Toog16Map == null) { |
| lg16Toog16Map = Collections.synchronizedMap(new WeakHashMap<ICC_ColorSpace, short[]>(2)); |
| } |
| lg16Toog16Map.put(grayCS, lg16Toog16LUT); |
| return lg16Toog16LUT; |
| } |
| |
| } |