12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt.image; 27 28 import java.awt.color.ColorSpace; 29 import java.awt.color.ICC_ColorSpace; 30 31 /** 32 * A <CODE>ColorModel</CODE> class that works with pixel values that 33 * represent color and alpha information as separate samples and that 34 * store each sample in a separate data element. This class can be 35 * used with an arbitrary <CODE>ColorSpace</CODE>. The number of 36 * color samples in the pixel values must be same as the number of 37 * color components in the <CODE>ColorSpace</CODE>. There may be a 38 * single alpha sample. 39 * <p> 40 * For those methods that use 41 * a primitive array pixel representation of type <CODE>transferType</CODE>, 42 * the array length is the same as the number of color and alpha samples. 43 * Color samples are stored first in the array followed by the alpha 44 * sample, if present. The order of the color samples is specified 45 * by the <CODE>ColorSpace</CODE>. Typically, this order reflects the 46 * name of the color space type. For example, for <CODE>TYPE_RGB</CODE>, 47 * index 0 corresponds to red, index 1 to green, and index 2 to blue. 48 * <p> 49 * The translation from pixel sample values to color/alpha components for 50 * display or processing purposes is based on a one-to-one correspondence of 51 * samples to components. 52 * Depending on the transfer type used to create an instance of 53 * <code>ComponentColorModel</code>, the pixel sample values 54 * represented by that instance may be signed or unsigned and may 55 * be of integral type or float or double (see below for details). 56 * The translation from sample values to normalized color/alpha components 57 * must follow certain rules. For float and double samples, the translation 58 * is an identity, i.e. normalized component values are equal to the 59 * corresponding sample values. For integral samples, the translation 60 * should be only a simple scale and offset, where the scale and offset 61 * constants may be different for each component. The result of 62 * applying the scale and offset constants is a set of color/alpha 63 * component values, which are guaranteed to fall within a certain 64 * range. Typically, the range for a color component will be the range 65 * defined by the <code>getMinValue</code> and <code>getMaxValue</code> 66 * methods of the <code>ColorSpace</code> class. The range for an 67 * alpha component should be 0.0 to 1.0. 68 * <p> 69 * Instances of <code>ComponentColorModel</code> created with transfer types 70 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 71 * and <CODE>DataBuffer.TYPE_INT</CODE> have pixel sample values which 72 * are treated as unsigned integral values. 73 * The number of bits in a color or alpha sample of a pixel value might not 74 * be the same as the number of bits for the corresponding color or alpha 75 * sample passed to the 76 * <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code> 77 * constructor. In 78 * that case, this class assumes that the least significant n bits of a sample 79 * value hold the component value, where n is the number of significant bits 80 * for the component passed to the constructor. It also assumes that 81 * any higher-order bits in a sample value are zero. Thus, sample values 82 * range from 0 to 2<sup>n</sup> - 1. This class maps these sample values 83 * to normalized color component values such that 0 maps to the value 84 * obtained from the <code>ColorSpace's</code> <code>getMinValue</code> 85 * method for each component and 2<sup>n</sup> - 1 maps to the value 86 * obtained from <code>getMaxValue</code>. To create a 87 * <code>ComponentColorModel</code> with a different color sample mapping 88 * requires subclassing this class and overriding the 89 * <code>getNormalizedComponents(Object, float[], int)</code> method. 90 * The mapping for an alpha sample always maps 0 to 0.0 and 91 * 2<sup>n</sup> - 1 to 1.0. 92 * <p> 93 * For instances with unsigned sample values, 94 * the unnormalized color/alpha component representation is only 95 * supported if two conditions hold. First, sample value 0 must 96 * map to normalized component value 0.0 and sample value 2<sup>n</sup> - 1 97 * to 1.0. Second the min/max range of all color components of the 98 * <code>ColorSpace</code> must be 0.0 to 1.0. In this case, the 99 * component representation is the n least 100 * significant bits of the corresponding sample. Thus each component is 101 * an unsigned integral value between 0 and 2<sup>n</sup> - 1, where 102 * n is the number of significant bits for a particular component. 103 * If these conditions are not met, any method taking an unnormalized 104 * component argument will throw an <code>IllegalArgumentException</code>. 105 * <p> 106 * Instances of <code>ComponentColorModel</code> created with transfer types 107 * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and 108 * <CODE>DataBuffer.TYPE_DOUBLE</CODE> have pixel sample values which 109 * are treated as signed short, float, or double values. 110 * Such instances do not support the unnormalized color/alpha component 111 * representation, so any methods taking such a representation as an argument 112 * will throw an <code>IllegalArgumentException</code> when called on one 113 * of these instances. The normalized component values of instances 114 * of this class have a range which depends on the transfer 115 * type as follows: for float samples, the full range of the float data 116 * type; for double samples, the full range of the float data type 117 * (resulting from casting double to float); for short samples, 118 * from approximately -maxVal to +maxVal, where maxVal is the per 119 * component maximum value for the <code>ColorSpace</code> 120 * (-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps 121 * to +maxVal). A subclass may override the scaling for short sample 122 * values to normalized component values by overriding the 123 * <code>getNormalizedComponents(Object, float[], int)</code> method. 124 * For float and double samples, the normalized component values are 125 * taken to be equal to the corresponding sample values, and subclasses 126 * should not attempt to add any non-identity scaling for these transfer 127 * types. 128 * <p> 129 * Instances of <code>ComponentColorModel</code> created with transfer types 130 * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, and 131 * <CODE>DataBuffer.TYPE_DOUBLE</CODE> 132 * use all the bits of all sample values. Thus all color/alpha components 133 * have 16 bits when using <CODE>DataBuffer.TYPE_SHORT</CODE>, 32 bits when 134 * using <CODE>DataBuffer.TYPE_FLOAT</CODE>, and 64 bits when using 135 * <CODE>DataBuffer.TYPE_DOUBLE</CODE>. When the 136 * <code>ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)</code> 137 * form of constructor is used with one of these transfer types, the 138 * bits array argument is ignored. 139 * <p> 140 * It is possible to have color/alpha sample values 141 * which cannot be reasonably interpreted as component values for rendering. 142 * This can happen when <code>ComponentColorModel</code> is subclassed to 143 * override the mapping of unsigned sample values to normalized color 144 * component values or when signed sample values outside a certain range 145 * are used. (As an example, specifying an alpha component as a signed 146 * short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can 147 * lead to unexpected results.) It is the 148 * responsibility of applications to appropriately scale pixel data before 149 * rendering such that color components fall within the normalized range 150 * of the <code>ColorSpace</code> (obtained using the <code>getMinValue</code> 151 * and <code>getMaxValue</code> methods of the <code>ColorSpace</code> class) 152 * and the alpha component is between 0.0 and 1.0. If color or alpha 153 * component values fall outside these ranges, rendering results are 154 * indeterminate. 155 * <p> 156 * Methods that use a single int pixel representation throw 157 * an <CODE>IllegalArgumentException</CODE>, unless the number of components 158 * for the <CODE>ComponentColorModel</CODE> is one and the component 159 * value is unsigned -- in other words, a single color component using 160 * a transfer type of <CODE>DataBuffer.TYPE_BYTE</CODE>, 161 * <CODE>DataBuffer.TYPE_USHORT</CODE>, or <CODE>DataBuffer.TYPE_INT</CODE> 162 * and no alpha. 163 * <p> 164 * A <CODE>ComponentColorModel</CODE> can be used in conjunction with a 165 * <CODE>ComponentSampleModel</CODE>, a <CODE>BandedSampleModel</CODE>, 166 * or a <CODE>PixelInterleavedSampleModel</CODE> to construct a 167 * <CODE>BufferedImage</CODE>. 168 * 169 * @see ColorModel 170 * @see ColorSpace 171 * @see ComponentSampleModel 172 * @see BandedSampleModel 173 * @see PixelInterleavedSampleModel 174 * @see BufferedImage 175 * 176 */ 177 public class ComponentColorModel extends ColorModel { 178 179 /** 180 * <code>signed</code> is <code>true</code> for <code>short</code>, 181 * <code>float</code>, and <code>double</code> transfer types; it 182 * is <code>false</code> for <code>byte</code>, <code>ushort</code>, 183 * and <code>int</code> transfer types. 184 */ 185 private boolean signed; // true for transfer types short, float, double 186 // false for byte, ushort, int 187 private boolean is_sRGB_stdScale; 188 private boolean is_LinearRGB_stdScale; 189 private boolean is_LinearGray_stdScale; 190 private boolean is_ICCGray_stdScale; 191 private byte[] tosRGB8LUT; 192 private byte[] fromsRGB8LUT8; 193 private short[] fromsRGB8LUT16; 194 private byte[] fromLinearGray16ToOtherGray8LUT; 195 private short[] fromLinearGray16ToOtherGray16LUT; 196 private boolean needScaleInit; 197 private boolean noUnnorm; 198 private boolean nonStdScale; 199 private float[] min; 200 private float[] diffMinMax; 201 private float[] compOffset; 202 private float[] compScale; 203 204 /** 205 * Constructs a <CODE>ComponentColorModel</CODE> from the specified 206 * parameters. Color components will be in the specified 207 * <CODE>ColorSpace</CODE>. The supported transfer types are 208 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 209 * <CODE>DataBuffer.TYPE_INT</CODE>, 210 * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, 211 * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>. 212 * If not null, the <CODE>bits</CODE> array specifies the 213 * number of significant bits per color and alpha component and its 214 * length should be at least the number of components in the 215 * <CODE>ColorSpace</CODE> if there is no alpha 216 * information in the pixel values, or one more than this number if 217 * there is alpha information. When the <CODE>transferType</CODE> is 218 * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, 219 * or <CODE>DataBuffer.TYPE_DOUBLE</CODE> the <CODE>bits</CODE> array 220 * argument is ignored. <CODE>hasAlpha</CODE> indicates whether alpha 221 * information is present. If <CODE>hasAlpha</CODE> is true, then 222 * the boolean <CODE>isAlphaPremultiplied</CODE> 223 * specifies how to interpret color and alpha samples in pixel values. 224 * If the boolean is true, color samples are assumed to have been 225 * multiplied by the alpha sample. The <CODE>transparency</CODE> 226 * specifies what alpha values can be represented by this color model. 227 * The acceptable <code>transparency</code> values are 228 * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>. 229 * The <CODE>transferType</CODE> is the type of primitive array used 230 * to represent pixel values. 231 * 232 * @param colorSpace The <CODE>ColorSpace</CODE> associated 233 * with this color model. 234 * @param bits The number of significant bits per component. 235 * May be null, in which case all bits of all 236 * component samples will be significant. 237 * Ignored if transferType is one of 238 * <CODE>DataBuffer.TYPE_SHORT</CODE>, 239 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or 240 * <CODE>DataBuffer.TYPE_DOUBLE</CODE>, 241 * in which case all bits of all component 242 * samples will be significant. 243 * @param hasAlpha If true, this color model supports alpha. 244 * @param isAlphaPremultiplied If true, alpha is premultiplied. 245 * @param transparency Specifies what alpha values can be represented 246 * by this color model. 247 * @param transferType Specifies the type of primitive array used to 248 * represent pixel values. 249 * 250 * @throws IllegalArgumentException If the <CODE>bits</CODE> array 251 * argument is not null, its length is less than the number of 252 * color and alpha components, and transferType is one of 253 * <CODE>DataBuffer.TYPE_BYTE</CODE>, 254 * <CODE>DataBuffer.TYPE_USHORT</CODE>, or 255 * <CODE>DataBuffer.TYPE_INT</CODE>. 256 * @throws IllegalArgumentException If transferType is not one of 257 * <CODE>DataBuffer.TYPE_BYTE</CODE>, 258 * <CODE>DataBuffer.TYPE_USHORT</CODE>, 259 * <CODE>DataBuffer.TYPE_INT</CODE>, 260 * <CODE>DataBuffer.TYPE_SHORT</CODE>, 261 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or 262 * <CODE>DataBuffer.TYPE_DOUBLE</CODE>. 263 * 264 * @see ColorSpace 265 * @see java.awt.Transparency 266 */ 267 public ComponentColorModel (ColorSpace colorSpace, 268 int[] bits, 269 boolean hasAlpha, 270 boolean isAlphaPremultiplied, 271 int transparency, 272 int transferType) { 273 super (bitsHelper(transferType, colorSpace, hasAlpha), 274 bitsArrayHelper(bits, transferType, colorSpace, hasAlpha), 275 colorSpace, hasAlpha, isAlphaPremultiplied, transparency, 276 transferType); 277 switch(transferType) { 278 case DataBuffer.TYPE_BYTE: 279 case DataBuffer.TYPE_USHORT: 280 case DataBuffer.TYPE_INT: 281 signed = false; 282 needScaleInit = true; 283 break; 284 case DataBuffer.TYPE_SHORT: 285 signed = true; 286 needScaleInit = true; 287 break; 288 case DataBuffer.TYPE_FLOAT: 289 case DataBuffer.TYPE_DOUBLE: 290 signed = true; 291 needScaleInit = false; 292 noUnnorm = true; 293 nonStdScale = false; 294 break; 295 default: 296 throw new IllegalArgumentException("This constructor is not "+ 297 "compatible with transferType " + transferType); 298 } 299 setupLUTs(); 300 } 301 302 /** 303 * Constructs a <CODE>ComponentColorModel</CODE> from the specified 304 * parameters. Color components will be in the specified 305 * <CODE>ColorSpace</CODE>. The supported transfer types are 306 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 307 * <CODE>DataBuffer.TYPE_INT</CODE>, 308 * <CODE>DataBuffer.TYPE_SHORT</CODE>, <CODE>DataBuffer.TYPE_FLOAT</CODE>, 309 * and <CODE>DataBuffer.TYPE_DOUBLE</CODE>. The number of significant 310 * bits per color and alpha component will be 8, 16, 32, 16, 32, or 64, 311 * respectively. The number of color components will be the 312 * number of components in the <CODE>ColorSpace</CODE>. There will be 313 * an alpha component if <CODE>hasAlpha</CODE> is <CODE>true</CODE>. 314 * If <CODE>hasAlpha</CODE> is true, then 315 * the boolean <CODE>isAlphaPremultiplied</CODE> 316 * specifies how to interpret color and alpha samples in pixel values. 317 * If the boolean is true, color samples are assumed to have been 318 * multiplied by the alpha sample. The <CODE>transparency</CODE> 319 * specifies what alpha values can be represented by this color model. 320 * The acceptable <code>transparency</code> values are 321 * <CODE>OPAQUE</CODE>, <CODE>BITMASK</CODE> or <CODE>TRANSLUCENT</CODE>. 322 * The <CODE>transferType</CODE> is the type of primitive array used 323 * to represent pixel values. 324 * 325 * @param colorSpace The <CODE>ColorSpace</CODE> associated 326 * with this color model. 327 * @param hasAlpha If true, this color model supports alpha. 328 * @param isAlphaPremultiplied If true, alpha is premultiplied. 329 * @param transparency Specifies what alpha values can be represented 330 * by this color model. 331 * @param transferType Specifies the type of primitive array used to 332 * represent pixel values. 333 * 334 * @throws IllegalArgumentException If transferType is not one of 335 * <CODE>DataBuffer.TYPE_BYTE</CODE>, 336 * <CODE>DataBuffer.TYPE_USHORT</CODE>, 337 * <CODE>DataBuffer.TYPE_INT</CODE>, 338 * <CODE>DataBuffer.TYPE_SHORT</CODE>, 339 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or 340 * <CODE>DataBuffer.TYPE_DOUBLE</CODE>. 341 * 342 * @see ColorSpace 343 * @see java.awt.Transparency 344 * @since 1.4 345 */ 346 public ComponentColorModel (ColorSpace colorSpace, 347 boolean hasAlpha, 348 boolean isAlphaPremultiplied, 349 int transparency, 350 int transferType) { 351 this(colorSpace, null, hasAlpha, isAlphaPremultiplied, 352 transparency, transferType); 353 } 354 355 private static int bitsHelper(int transferType, 356 ColorSpace colorSpace, 357 boolean hasAlpha) { 358 int numBits = DataBuffer.getDataTypeSize(transferType); 359 int numComponents = colorSpace.getNumComponents(); 360 if (hasAlpha) { 645 float[] norm = getNormalizedComponents(opixel, null, 0); 646 float[] rgb = colorSpace.toRGB(norm); 647 648 return (int) (rgb[idx] * 255.0f + 0.5f); 649 } 650 651 /** 652 * Returns the red color component for the specified pixel, scaled 653 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 654 * is done if necessary. The pixel value is specified as an int. 655 * The returned value will be a non pre-multiplied value. 656 * If the alpha is premultiplied, this method divides 657 * it out before returning the value (if the alpha value is 0, 658 * the red value will be 0). 659 * 660 * @param pixel The pixel from which you want to get the red color component. 661 * 662 * @return The red color component for the specified pixel, as an int. 663 * 664 * @throws IllegalArgumentException If there is more than 665 * one component in this <CODE>ColorModel</CODE>. 666 * @throws IllegalArgumentException If the component value for this 667 * <CODE>ColorModel</CODE> is signed 668 */ 669 public int getRed(int pixel) { 670 return getRGBComponent(pixel, 0); 671 } 672 673 /** 674 * Returns the green color component for the specified pixel, scaled 675 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 676 * is done if necessary. The pixel value is specified as an int. 677 * The returned value will be a non 678 * pre-multiplied value. If the alpha is premultiplied, this method 679 * divides it out before returning the value (if the alpha value is 0, 680 * the green value will be 0). 681 * 682 * @param pixel The pixel from which you want to get the green color component. 683 * 684 * @return The green color component for the specified pixel, as an int. 685 * 686 * @throws IllegalArgumentException If there is more than 687 * one component in this <CODE>ColorModel</CODE>. 688 * @throws IllegalArgumentException If the component value for this 689 * <CODE>ColorModel</CODE> is signed 690 */ 691 public int getGreen(int pixel) { 692 return getRGBComponent(pixel, 1); 693 } 694 695 /** 696 * Returns the blue color component for the specified pixel, scaled 697 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 698 * is done if necessary. The pixel value is specified as an int. 699 * The returned value will be a non 700 * pre-multiplied value. If the alpha is premultiplied, this method 701 * divides it out before returning the value (if the alpha value is 0, 702 * the blue value will be 0). 703 * 704 * @param pixel The pixel from which you want to get the blue color component. 705 * 706 * @return The blue color component for the specified pixel, as an int. 707 * 708 * @throws IllegalArgumentException If there is more than 709 * one component in this <CODE>ColorModel</CODE>. 710 * @throws IllegalArgumentException If the component value for this 711 * <CODE>ColorModel</CODE> is signed 712 */ 713 public int getBlue(int pixel) { 714 return getRGBComponent(pixel, 2); 715 } 716 717 /** 718 * Returns the alpha component for the specified pixel, scaled 719 * from 0 to 255. The pixel value is specified as an int. 720 * 721 * @param pixel The pixel from which you want to get the alpha component. 722 * 723 * @return The alpha component for the specified pixel, as an int. 724 * 725 * @throws IllegalArgumentException If there is more than 726 * one component in this <CODE>ColorModel</CODE>. 727 * @throws IllegalArgumentException If the component value for this 728 * <CODE>ColorModel</CODE> is signed 729 */ 730 public int getAlpha(int pixel) { 731 if (supportsAlpha == false) { 732 return 255; 733 } 734 if (numComponents > 1) { 735 throw new 736 IllegalArgumentException("More than one component per pixel"); 737 } 738 if (signed) { 739 throw new 740 IllegalArgumentException("Component value is signed"); 741 } 742 743 return (int) ((((float) pixel) / ((1<<nBits[0])-1)) * 255.0f + 0.5f); 744 } 745 746 /** 747 * Returns the color/alpha components of the pixel in the default 748 * RGB color model format. A color conversion is done if necessary. 749 * The returned value will be in a non pre-multiplied format. If 750 * the alpha is premultiplied, this method divides it out of the 751 * color components (if the alpha value is 0, the color values will be 0). 752 * 753 * @param pixel The pixel from which you want to get the color/alpha components. 754 * 755 * @return The color/alpha components for the specified pixel, as an int. 756 * 757 * @throws IllegalArgumentException If there is more than 758 * one component in this <CODE>ColorModel</CODE>. 759 * @throws IllegalArgumentException If the component value for this 760 * <CODE>ColorModel</CODE> is signed 761 */ 762 public int getRGB(int pixel) { 763 if (numComponents > 1) { 764 throw new 765 IllegalArgumentException("More than one component per pixel"); 766 } 767 if (signed) { 768 throw new 769 IllegalArgumentException("Component value is signed"); 770 } 771 772 return (getAlpha(pixel) << 24) 773 | (getRed(pixel) << 16) 774 | (getGreen(pixel) << 8) 775 | (getBlue(pixel) << 0); 776 } 777 778 private int extractComponent(Object inData, int idx, int precision) { 779 // Extract component idx from inData. The precision argument 780 // should be either 8 or 16. If it's 8, this method will return 896 if (is_sRGB_stdScale) { 897 return extractComponent(inData, idx, 8); 898 } else if (is_LinearRGB_stdScale) { 899 int lutidx = extractComponent(inData, idx, 16); 900 return tosRGB8LUT[lutidx] & 0xff; 901 } else if (is_ICCGray_stdScale) { 902 int lutidx = extractComponent(inData, 0, 16); 903 return tosRGB8LUT[lutidx] & 0xff; 904 } 905 906 // Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace 907 float[] norm = getNormalizedComponents(inData, null, 0); 908 // Note that getNormalizedComponents returns non-premultiplied values 909 float[] rgb = colorSpace.toRGB(norm); 910 return (int) (rgb[idx] * 255.0f + 0.5f); 911 } 912 913 /** 914 * Returns the red color component for the specified pixel, scaled 915 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 916 * is done if necessary. The <CODE>pixel</CODE> value is specified by an array 917 * of data elements of type <CODE>transferType</CODE> passed in as an object 918 * reference. The returned value will be a non pre-multiplied value. If the 919 * alpha is premultiplied, this method divides it out before returning 920 * the value (if the alpha value is 0, the red value will be 0). Since 921 * <code>ComponentColorModel</code> can be subclassed, subclasses 922 * inherit the implementation of this method and if they don't override 923 * it then they throw an exception if they use an unsupported 924 * <code>transferType</code>. 925 * 926 * @param inData The pixel from which you want to get the red color component, 927 * specified by an array of data elements of type <CODE>transferType</CODE>. 928 * 929 * @return The red color component for the specified pixel, as an int. 930 * 931 * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array 932 * of type <CODE>transferType</CODE>. 933 * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not 934 * large enough to hold a pixel value for this 935 * <CODE>ColorModel</CODE>. 936 * @throws UnsupportedOperationException If the transfer type of 937 * this <CODE>ComponentColorModel</CODE> 938 * is not one of the supported transfer types: 939 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 940 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, 941 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. 942 */ 943 public int getRed(Object inData) { 944 return getRGBComponent(inData, 0); 945 } 946 947 948 /** 949 * Returns the green color component for the specified pixel, scaled 950 * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB. 951 * A color conversion is done if necessary. The <CODE>pixel</CODE> value 952 * is specified by an array of data elements of type <CODE>transferType</CODE> 953 * passed in as an object reference. The returned value is a non pre-multiplied 954 * value. If the alpha is premultiplied, this method divides it out before 955 * returning the value (if the alpha value is 0, the green value will be 0). 956 * Since <code>ComponentColorModel</code> can be subclassed, 957 * subclasses inherit the implementation of this method and if they 958 * don't override it then they throw an exception if they use an 959 * unsupported <code>transferType</code>. 960 * 961 * @param inData The pixel from which you want to get the green color component, 962 * specified by an array of data elements of type <CODE>transferType</CODE>. 963 * 964 * @return The green color component for the specified pixel, as an int. 965 * 966 * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array 967 * of type <CODE>transferType</CODE>. 968 * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not 969 * large enough to hold a pixel value for this 970 * <CODE>ColorModel</CODE>. 971 * @throws UnsupportedOperationException If the transfer type of 972 * this <CODE>ComponentColorModel</CODE> 973 * is not one of the supported transfer types: 974 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 975 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, 976 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. 977 */ 978 public int getGreen(Object inData) { 979 return getRGBComponent(inData, 1); 980 } 981 982 983 /** 984 * Returns the blue color component for the specified pixel, scaled 985 * from 0 to 255 in the default RGB <CODE>ColorSpace</CODE>, sRGB. 986 * A color conversion is done if necessary. The <CODE>pixel</CODE> value is 987 * specified by an array of data elements of type <CODE>transferType</CODE> 988 * passed in as an object reference. The returned value is a non pre-multiplied 989 * value. If the alpha is premultiplied, this method divides it out before 990 * returning the value (if the alpha value is 0, the blue value will be 0). 991 * Since <code>ComponentColorModel</code> can be subclassed, 992 * subclasses inherit the implementation of this method and if they 993 * don't override it then they throw an exception if they use an 994 * unsupported <code>transferType</code>. 995 * 996 * @param inData The pixel from which you want to get the blue color component, 997 * specified by an array of data elements of type <CODE>transferType</CODE>. 998 * 999 * @return The blue color component for the specified pixel, as an int. 1000 * 1001 * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array 1002 * of type <CODE>transferType</CODE>. 1003 * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not 1004 * large enough to hold a pixel value for this 1005 * <CODE>ColorModel</CODE>. 1006 * @throws UnsupportedOperationException If the transfer type of 1007 * this <CODE>ComponentColorModel</CODE> 1008 * is not one of the supported transfer types: 1009 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 1010 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, 1011 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. 1012 */ 1013 public int getBlue(Object inData) { 1014 return getRGBComponent(inData, 2); 1015 } 1016 1017 /** 1018 * Returns the alpha component for the specified pixel, scaled from 1019 * 0 to 255. The pixel value is specified by an array of data 1020 * elements of type <CODE>transferType</CODE> passed in as an 1021 * object reference. Since <code>ComponentColorModel</code> can be 1022 * subclassed, subclasses inherit the 1023 * implementation of this method and if they don't override it then 1024 * they throw an exception if they use an unsupported 1025 * <code>transferType</code>. 1026 * 1027 * @param inData The pixel from which you want to get the alpha component, 1028 * specified by an array of data elements of type <CODE>transferType</CODE>. 1029 * 1030 * @return The alpha component for the specified pixel, as an int. 1031 * 1032 * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array 1033 * of type <CODE>transferType</CODE>. 1034 * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not 1035 * large enough to hold a pixel value for this 1036 * <CODE>ColorModel</CODE>. 1037 * @throws UnsupportedOperationException If the transfer type of 1038 * this <CODE>ComponentColorModel</CODE> 1039 * is not one of the supported transfer types: 1040 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 1041 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, 1042 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. 1043 */ 1044 public int getAlpha(Object inData) { 1045 if (supportsAlpha == false) { 1046 return 255; 1047 } 1048 1049 int alpha = 0; 1050 int aIdx = numColorComponents; 1051 int mask = (1 << nBits[aIdx]) - 1; 1052 1053 switch (transferType) { 1054 case DataBuffer.TYPE_SHORT: 1055 short sdata[] = (short[])inData; 1056 alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f); 1057 return alpha; 1058 case DataBuffer.TYPE_FLOAT: 1059 float fdata[] = (float[])inData; 1060 alpha = (int) (fdata[aIdx] * 255.0f + 0.5f); 1061 return alpha; 1062 case DataBuffer.TYPE_DOUBLE: 1077 break; 1078 default: 1079 throw new 1080 UnsupportedOperationException("This method has not "+ 1081 "been implemented for transferType " + transferType); 1082 } 1083 1084 if (nBits[aIdx] == 8) { 1085 return alpha; 1086 } else { 1087 return (int) 1088 ((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) * 1089 255.0f + 0.5f); 1090 } 1091 } 1092 1093 /** 1094 * Returns the color/alpha components for the specified pixel in the 1095 * default RGB color model format. A color conversion is done if 1096 * necessary. The pixel value is specified by an 1097 * array of data elements of type <CODE>transferType</CODE> passed 1098 * in as an object reference. 1099 * The returned value is in a non pre-multiplied format. If 1100 * the alpha is premultiplied, this method divides it out of the 1101 * color components (if the alpha value is 0, the color values will be 0). 1102 * Since <code>ComponentColorModel</code> can be subclassed, 1103 * subclasses inherit the implementation of this method and if they 1104 * don't override it then they throw an exception if they use an 1105 * unsupported <code>transferType</code>. 1106 * 1107 * @param inData The pixel from which you want to get the color/alpha components, 1108 * specified by an array of data elements of type <CODE>transferType</CODE>. 1109 * 1110 * @return The color/alpha components for the specified pixel, as an int. 1111 * 1112 * @throws ClassCastException If <CODE>inData</CODE> is not a primitive array 1113 * of type <CODE>transferType</CODE>. 1114 * @throws ArrayIndexOutOfBoundsException if <CODE>inData</CODE> is not 1115 * large enough to hold a pixel value for this 1116 * <CODE>ColorModel</CODE>. 1117 * @throws UnsupportedOperationException If the transfer type of 1118 * this <CODE>ComponentColorModel</CODE> 1119 * is not one of the supported transfer types: 1120 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 1121 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, 1122 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. 1123 * @see ColorModel#getRGBdefault 1124 */ 1125 public int getRGB(Object inData) { 1126 if (needScaleInit) { 1127 initScale(); 1128 } 1129 if (is_sRGB_stdScale || is_LinearRGB_stdScale) { 1130 return (getAlpha(inData) << 24) 1131 | (getRed(inData) << 16) 1132 | (getGreen(inData) << 8) 1133 | (getBlue(inData)); 1134 } else if (colorSpaceType == ColorSpace.TYPE_GRAY) { 1135 int gray = getRed(inData); // Red sRGB component should equal 1136 // green and blue components 1137 return (getAlpha(inData) << 24) 1138 | (gray << 16) 1139 | (gray << 8) 1140 | gray; 1141 } 1142 float[] norm = getNormalizedComponents(inData, null, 0); 1143 // Note that getNormalizedComponents returns non-premult values 1144 float[] rgb = colorSpace.toRGB(norm); 1145 return (getAlpha(inData) << 24) 1146 | (((int) (rgb[0] * 255.0f + 0.5f)) << 16) 1147 | (((int) (rgb[1] * 255.0f + 0.5f)) << 8) 1148 | (((int) (rgb[2] * 255.0f + 0.5f)) << 0); 1149 } 1150 1151 /** 1152 * Returns a data element array representation of a pixel in this 1153 * <CODE>ColorModel</CODE>, given an integer pixel representation 1154 * in the default RGB color model. 1155 * This array can then be passed to the <CODE>setDataElements</CODE> 1156 * method of a <CODE>WritableRaster</CODE> object. If the 1157 * <CODE>pixel</CODE> 1158 * parameter is null, a new array is allocated. Since 1159 * <code>ComponentColorModel</code> can be subclassed, subclasses 1160 * inherit the implementation of this method and if they don't 1161 * override it then 1162 * they throw an exception if they use an unsupported 1163 * <code>transferType</code>. 1164 * 1165 * @param rgb the integer representation of the pixel in the RGB 1166 * color model 1167 * @param pixel the specified pixel 1168 * @return The data element array representation of a pixel 1169 * in this <CODE>ColorModel</CODE>. 1170 * @throws ClassCastException If <CODE>pixel</CODE> is not null and 1171 * is not a primitive array of type <CODE>transferType</CODE>. 1172 * @throws ArrayIndexOutOfBoundsException If <CODE>pixel</CODE> is 1173 * not large enough to hold a pixel value for this 1174 * <CODE>ColorModel</CODE>. 1175 * @throws UnsupportedOperationException If the transfer type of 1176 * this <CODE>ComponentColorModel</CODE> 1177 * is not one of the supported transfer types: 1178 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 1179 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, 1180 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. 1181 * 1182 * @see WritableRaster#setDataElements 1183 * @see SampleModel#setDataElements 1184 */ 1185 public Object getDataElements(int rgb, Object pixel) { 1186 // REMIND: Use rendering hints? 1187 1188 int red, grn, blu, alp; 1189 red = (rgb>>16) & 0xff; 1190 grn = (rgb>>8) & 0xff; 1191 blu = rgb & 0xff; 1192 1193 if (needScaleInit) { 1194 initScale(); 1195 } 1196 if (signed) { 1197 // Handle SHORT, FLOAT, & DOUBLE here 1198 1199 switch(transferType) { 1200 case DataBuffer.TYPE_SHORT: 1638 } 1639 case DataBuffer.TYPE_INT: 1640 if (maxBits > 23) { 1641 // fix 4412670 - for components of 24 or more bits 1642 // some calculations done above with float precision 1643 // may lose enough precision that the integer result 1644 // overflows nBits, so we need to clamp. 1645 for (int i = 0; i < numComponents; i++) { 1646 if (intpixel[i] > ((1<<nBits[i]) - 1)) { 1647 intpixel[i] = (1<<nBits[i]) - 1; 1648 } 1649 } 1650 } 1651 return intpixel; 1652 } 1653 throw new IllegalArgumentException("This method has not been "+ 1654 "implemented for transferType " + transferType); 1655 } 1656 1657 /** Returns an array of unnormalized color/alpha components given a pixel 1658 * in this <CODE>ColorModel</CODE>. 1659 * An IllegalArgumentException is thrown if the component value for this 1660 * <CODE>ColorModel</CODE> is not conveniently representable in the 1661 * unnormalized form. Color/alpha components are stored 1662 * in the <CODE>components</CODE> array starting at <CODE>offset</CODE> 1663 * (even if the array is allocated by this method). 1664 * 1665 * @param pixel The pixel value specified as an integer. 1666 * @param components An integer array in which to store the unnormalized 1667 * color/alpha components. If the <CODE>components</CODE> array is null, 1668 * a new array is allocated. 1669 * @param offset An offset into the <CODE>components</CODE> array. 1670 * 1671 * @return The components array. 1672 * 1673 * @throws IllegalArgumentException If there is more than one 1674 * component in this <CODE>ColorModel</CODE>. 1675 * @throws IllegalArgumentException If this 1676 * <CODE>ColorModel</CODE> does not support the unnormalized form 1677 * @throws ArrayIndexOutOfBoundsException If the <CODE>components</CODE> 1678 * array is not null and is not large enough to hold all the color and 1679 * alpha components (starting at offset). 1680 */ 1681 public int[] getComponents(int pixel, int[] components, int offset) { 1682 if (numComponents > 1) { 1683 throw new 1684 IllegalArgumentException("More than one component per pixel"); 1685 } 1686 if (needScaleInit) { 1687 initScale(); 1688 } 1689 if (noUnnorm) { 1690 throw new 1691 IllegalArgumentException( 1692 "This ColorModel does not support the unnormalized form"); 1693 } 1694 if (components == null) { 1695 components = new int[offset+1]; 1696 } 1697 1698 components[offset+0] = (pixel & ((1<<nBits[0]) - 1)); 1699 return components; 1700 } 1701 1702 /** 1703 * Returns an array of unnormalized color/alpha components given a pixel 1704 * in this <CODE>ColorModel</CODE>. The pixel value is specified by an 1705 * array of data elements of type <CODE>transferType</CODE> passed in as 1706 * an object reference. 1707 * An IllegalArgumentException is thrown if the component values for this 1708 * <CODE>ColorModel</CODE> are not conveniently representable in the 1709 * unnormalized form. 1710 * Color/alpha components are stored in the <CODE>components</CODE> array 1711 * starting at <CODE>offset</CODE> (even if the array is allocated by 1712 * this method). Since <code>ComponentColorModel</code> can be 1713 * subclassed, subclasses inherit the 1714 * implementation of this method and if they don't override it then 1715 * this method might throw an exception if they use an unsupported 1716 * <code>transferType</code>. 1717 * 1718 * @param pixel A pixel value specified by an array of data elements of 1719 * type <CODE>transferType</CODE>. 1720 * @param components An integer array in which to store the unnormalized 1721 * color/alpha components. If the <CODE>components</CODE> array is null, 1722 * a new array is allocated. 1723 * @param offset An offset into the <CODE>components</CODE> array. 1724 * 1725 * @return The <CODE>components</CODE> array. 1726 * 1727 * @throws IllegalArgumentException If this 1728 * <CODE>ComponentColorModel</CODE> does not support the unnormalized form 1729 * @throws UnsupportedOperationException in some cases iff the 1730 * transfer type of this <CODE>ComponentColorModel</CODE> 1731 * is not one of the following transfer types: 1732 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 1733 * or <CODE>DataBuffer.TYPE_INT</CODE>. 1734 * @throws ClassCastException If <CODE>pixel</CODE> is not a primitive 1735 * array of type <CODE>transferType</CODE>. 1736 * @throws IllegalArgumentException If the <CODE>components</CODE> array is 1737 * not null and is not large enough to hold all the color and alpha 1738 * components (starting at offset), or if <CODE>pixel</CODE> is not large 1739 * enough to hold a pixel value for this ColorModel. 1740 */ 1741 public int[] getComponents(Object pixel, int[] components, int offset) { 1742 int intpixel[]; 1743 if (needScaleInit) { 1744 initScale(); 1745 } 1746 if (noUnnorm) { 1747 throw new 1748 IllegalArgumentException( 1749 "This ColorModel does not support the unnormalized form"); 1750 } 1751 if (pixel instanceof int[]) { 1752 intpixel = (int[])pixel; 1753 } else { 1754 intpixel = DataBuffer.toIntArray(pixel); 1755 if (intpixel == null) { 1756 throw new UnsupportedOperationException("This method has not been "+ 1757 "implemented for transferType " + transferType); 1758 } 1762 ("Length of pixel array < number of components in model"); 1763 } 1764 if (components == null) { 1765 components = new int[offset+numComponents]; 1766 } 1767 else if ((components.length-offset) < numComponents) { 1768 throw new IllegalArgumentException 1769 ("Length of components array < number of components in model"); 1770 } 1771 System.arraycopy(intpixel, 0, components, offset, numComponents); 1772 1773 return components; 1774 } 1775 1776 /** 1777 * Returns an array of all of the color/alpha components in unnormalized 1778 * form, given a normalized component array. Unnormalized components 1779 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where 1780 * n is the number of bits for a particular component. Normalized 1781 * components are float values between a per component minimum and 1782 * maximum specified by the <code>ColorSpace</code> object for this 1783 * <code>ColorModel</code>. An <code>IllegalArgumentException</code> 1784 * will be thrown if color component values for this 1785 * <code>ColorModel</code> are not conveniently representable in the 1786 * unnormalized form. If the 1787 * <code>components</code> array is <code>null</code>, a new array 1788 * will be allocated. The <code>components</code> array will 1789 * be returned. Color/alpha components are stored in the 1790 * <code>components</code> array starting at <code>offset</code> (even 1791 * if the array is allocated by this method). An 1792 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the 1793 * <code>components</code> array is not <code>null</code> and is not 1794 * large enough to hold all the color and alpha 1795 * components (starting at <code>offset</code>). An 1796 * <code>IllegalArgumentException</code> is thrown if the 1797 * <code>normComponents</code> array is not large enough to hold 1798 * all the color and alpha components starting at 1799 * <code>normOffset</code>. 1800 * @param normComponents an array containing normalized components 1801 * @param normOffset the offset into the <code>normComponents</code> 1802 * array at which to start retrieving normalized components 1803 * @param components an array that receives the components from 1804 * <code>normComponents</code> 1805 * @param offset the index into <code>components</code> at which to 1806 * begin storing normalized components from 1807 * <code>normComponents</code> 1808 * @return an array containing unnormalized color and alpha 1809 * components. 1810 * @throws IllegalArgumentException If this 1811 * <CODE>ComponentColorModel</CODE> does not support the unnormalized form 1812 * @throws IllegalArgumentException if the length of 1813 * <code>normComponents</code> minus <code>normOffset</code> 1814 * is less than <code>numComponents</code> 1815 */ 1816 public int[] getUnnormalizedComponents(float[] normComponents, 1817 int normOffset, 1818 int[] components, int offset) { 1819 if (needScaleInit) { 1820 initScale(); 1821 } 1822 if (noUnnorm) { 1823 throw new 1824 IllegalArgumentException( 1825 "This ColorModel does not support the unnormalized form"); 1826 } 1827 return super.getUnnormalizedComponents(normComponents, normOffset, 1828 components, offset); 1829 } 1830 1831 /** 1832 * Returns an array of all of the color/alpha components in normalized 1833 * form, given an unnormalized component array. Unnormalized components 1834 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where 1835 * n is the number of bits for a particular component. Normalized 1836 * components are float values between a per component minimum and 1837 * maximum specified by the <code>ColorSpace</code> object for this 1838 * <code>ColorModel</code>. An <code>IllegalArgumentException</code> 1839 * will be thrown if color component values for this 1840 * <code>ColorModel</code> are not conveniently representable in the 1841 * unnormalized form. If the 1842 * <code>normComponents</code> array is <code>null</code>, a new array 1843 * will be allocated. The <code>normComponents</code> array 1844 * will be returned. Color/alpha components are stored in the 1845 * <code>normComponents</code> array starting at 1846 * <code>normOffset</code> (even if the array is allocated by this 1847 * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown 1848 * if the <code>normComponents</code> array is not <code>null</code> 1849 * and is not large enough to hold all the color and alpha components 1850 * (starting at <code>normOffset</code>). An 1851 * <code>IllegalArgumentException</code> is thrown if the 1852 * <code>components</code> array is not large enough to hold all the 1853 * color and alpha components starting at <code>offset</code>. 1854 * @param components an array containing unnormalized components 1855 * @param offset the offset into the <code>components</code> array at 1856 * which to start retrieving unnormalized components 1857 * @param normComponents an array that receives the normalized components 1858 * @param normOffset the index into <code>normComponents</code> at 1859 * which to begin storing normalized components 1860 * @return an array containing normalized color and alpha 1861 * components. 1862 * @throws IllegalArgumentException If this 1863 * <CODE>ComponentColorModel</CODE> does not support the unnormalized form 1864 */ 1865 public float[] getNormalizedComponents(int[] components, int offset, 1866 float[] normComponents, 1867 int normOffset) { 1868 if (needScaleInit) { 1869 initScale(); 1870 } 1871 if (noUnnorm) { 1872 throw new 1873 IllegalArgumentException( 1874 "This ColorModel does not support the unnormalized form"); 1875 } 1876 return super.getNormalizedComponents(components, offset, 1877 normComponents, normOffset); 1878 } 1879 1880 /** 1881 * Returns a pixel value represented as an int in this <CODE>ColorModel</CODE>, 1882 * given an array of unnormalized color/alpha components. 1883 * 1884 * @param components An array of unnormalized color/alpha components. 1885 * @param offset An offset into the <CODE>components</CODE> array. 1886 * 1887 * @return A pixel value represented as an int. 1888 * 1889 * @throws IllegalArgumentException If there is more than one component 1890 * in this <CODE>ColorModel</CODE>. 1891 * @throws IllegalArgumentException If this 1892 * <CODE>ComponentColorModel</CODE> does not support the unnormalized form 1893 */ 1894 public int getDataElement(int[] components, int offset) { 1895 if (needScaleInit) { 1896 initScale(); 1897 } 1898 if (numComponents == 1) { 1899 if (noUnnorm) { 1900 throw new 1901 IllegalArgumentException( 1902 "This ColorModel does not support the unnormalized form"); 1903 } 1904 return components[offset+0]; 1905 } 1906 throw new IllegalArgumentException("This model returns "+ 1907 numComponents+ 1908 " elements in the pixel array."); 1909 } 1910 1911 /** 1912 * Returns a data element array representation of a pixel in this 1913 * <CODE>ColorModel</CODE>, given an array of unnormalized color/alpha 1914 * components. This array can then be passed to the <CODE>setDataElements</CODE> 1915 * method of a <CODE>WritableRaster</CODE> object. 1916 * 1917 * @param components An array of unnormalized color/alpha components. 1918 * @param offset The integer offset into the <CODE>components</CODE> array. 1919 * @param obj The object in which to store the data element array 1920 * representation of the pixel. If <CODE>obj</CODE> variable is null, 1921 * a new array is allocated. If <CODE>obj</CODE> is not null, it must 1922 * be a primitive array of type <CODE>transferType</CODE>. An 1923 * <CODE>ArrayIndexOutOfBoundsException</CODE> is thrown if 1924 * <CODE>obj</CODE> is not large enough to hold a pixel value 1925 * for this <CODE>ColorModel</CODE>. Since 1926 * <code>ComponentColorModel</code> can be subclassed, subclasses 1927 * inherit the implementation of this method and if they don't 1928 * override it then they throw an exception if they use an 1929 * unsupported <code>transferType</code>. 1930 * 1931 * @return The data element array representation of a pixel 1932 * in this <CODE>ColorModel</CODE>. 1933 * 1934 * @throws IllegalArgumentException If the components array 1935 * is not large enough to hold all the color and alpha components 1936 * (starting at offset). 1937 * @throws ClassCastException If <CODE>obj</CODE> is not null and is not a 1938 * primitive array of type <CODE>transferType</CODE>. 1939 * @throws ArrayIndexOutOfBoundsException If <CODE>obj</CODE> is not large 1940 * enough to hold a pixel value for this <CODE>ColorModel</CODE>. 1941 * @throws IllegalArgumentException If this 1942 * <CODE>ComponentColorModel</CODE> does not support the unnormalized form 1943 * @throws UnsupportedOperationException If the transfer type of 1944 * this <CODE>ComponentColorModel</CODE> 1945 * is not one of the following transfer types: 1946 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 1947 * or <CODE>DataBuffer.TYPE_INT</CODE>. 1948 * 1949 * @see WritableRaster#setDataElements 1950 * @see SampleModel#setDataElements 1951 */ 1952 public Object getDataElements(int[] components, int offset, Object obj) { 1953 if (needScaleInit) { 1954 initScale(); 1955 } 1956 if (noUnnorm) { 1957 throw new 1958 IllegalArgumentException( 1959 "This ColorModel does not support the unnormalized form"); 1960 } 1961 if ((components.length-offset) < numComponents) { 1962 throw new IllegalArgumentException("Component array too small"+ 1963 " (should be "+numComponents); 1964 } 1965 switch(transferType) { 1966 case DataBuffer.TYPE_INT: 1967 { 1998 if (obj == null) { 1999 pixel = new short[numComponents]; 2000 } 2001 else { 2002 pixel = (short[]) obj; 2003 } 2004 for (int i=0; i < numComponents; i++) { 2005 pixel[i] = (short) (components[offset+i]&0xffff); 2006 } 2007 return pixel; 2008 } 2009 2010 default: 2011 throw new UnsupportedOperationException("This method has not been "+ 2012 "implemented for transferType " + 2013 transferType); 2014 } 2015 } 2016 2017 /** 2018 * Returns a pixel value represented as an <code>int</code> in this 2019 * <code>ColorModel</code>, given an array of normalized color/alpha 2020 * components. This method will throw an 2021 * <code>IllegalArgumentException</code> if pixel values for this 2022 * <code>ColorModel</code> are not conveniently representable as a 2023 * single <code>int</code>. An 2024 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the 2025 * <code>normComponents</code> array is not large enough to hold all the 2026 * color and alpha components (starting at <code>normOffset</code>). 2027 * @param normComponents an array of normalized color and alpha 2028 * components 2029 * @param normOffset the index into <code>normComponents</code> at which to 2030 * begin retrieving the color and alpha components 2031 * @return an <code>int</code> pixel value in this 2032 * <code>ColorModel</code> corresponding to the specified components. 2033 * @throws IllegalArgumentException if 2034 * pixel values for this <code>ColorModel</code> are not 2035 * conveniently representable as a single <code>int</code> 2036 * @throws ArrayIndexOutOfBoundsException if 2037 * the <code>normComponents</code> array is not large enough to 2038 * hold all of the color and alpha components starting at 2039 * <code>normOffset</code> 2040 * @since 1.4 2041 */ 2042 public int getDataElement(float[] normComponents, int normOffset) { 2043 if (numComponents > 1) { 2044 throw new 2045 IllegalArgumentException("More than one component per pixel"); 2046 } 2047 if (signed) { 2048 throw new 2049 IllegalArgumentException("Component value is signed"); 2050 } 2051 if (needScaleInit) { 2052 initScale(); 2053 } 2054 Object pixel = getDataElements(normComponents, normOffset, null); 2055 switch (transferType) { 2056 case DataBuffer.TYPE_BYTE: 2057 { 2058 byte bpixel[] = (byte[]) pixel; 2059 return bpixel[0] & 0xff; 2060 } 2061 case DataBuffer.TYPE_USHORT: 2062 { 2063 short[] uspixel = (short[]) pixel; 2064 return uspixel[0] & 0xffff; 2065 } 2066 case DataBuffer.TYPE_INT: 2067 { 2068 int[] ipixel = (int[]) pixel; 2069 return ipixel[0]; 2070 } 2071 default: 2072 throw new UnsupportedOperationException("This method has not been " 2073 + "implemented for transferType " + transferType); 2074 } 2075 } 2076 2077 /** 2078 * Returns a data element array representation of a pixel in this 2079 * <code>ColorModel</code>, given an array of normalized color/alpha 2080 * components. This array can then be passed to the 2081 * <code>setDataElements</code> method of a <code>WritableRaster</code> 2082 * object. An <code>ArrayIndexOutOfBoundsException</code> is thrown 2083 * if the <code>normComponents</code> array is not large enough to hold 2084 * all the color and alpha components (starting at 2085 * <code>normOffset</code>). If the <code>obj</code> variable is 2086 * <code>null</code>, a new array will be allocated. If 2087 * <code>obj</code> is not <code>null</code>, it must be a primitive 2088 * array of type transferType; otherwise, a 2089 * <code>ClassCastException</code> is thrown. An 2090 * <code>ArrayIndexOutOfBoundsException</code> is thrown if 2091 * <code>obj</code> is not large enough to hold a pixel value for this 2092 * <code>ColorModel</code>. 2093 * @param normComponents an array of normalized color and alpha 2094 * components 2095 * @param normOffset the index into <code>normComponents</code> at which to 2096 * begin retrieving color and alpha components 2097 * @param obj a primitive data array to hold the returned pixel 2098 * @return an <code>Object</code> which is a primitive data array 2099 * representation of a pixel 2100 * @throws ClassCastException if <code>obj</code> 2101 * is not a primitive array of type <code>transferType</code> 2102 * @throws ArrayIndexOutOfBoundsException if 2103 * <code>obj</code> is not large enough to hold a pixel value 2104 * for this <code>ColorModel</code> or the <code>normComponents</code> 2105 * array is not large enough to hold all of the color and alpha 2106 * components starting at <code>normOffset</code> 2107 * @see WritableRaster#setDataElements 2108 * @see SampleModel#setDataElements 2109 * @since 1.4 2110 */ 2111 public Object getDataElements(float[] normComponents, int normOffset, 2112 Object obj) { 2113 boolean needAlpha = supportsAlpha && isAlphaPremultiplied; 2114 float[] stdNormComponents; 2115 if (needScaleInit) { 2116 initScale(); 2117 } 2118 if (nonStdScale) { 2119 stdNormComponents = new float[numComponents]; 2120 for (int c = 0, nc = normOffset; c < numColorComponents; 2121 c++, nc++) { 2122 stdNormComponents[c] = (normComponents[nc] - compOffset[c]) * 2123 compScale[c]; 2124 // REMIND: need to analyze whether this 2125 // clamping is necessary 2126 if (stdNormComponents[c] < 0.0f) { 2281 c++, nc++) { 2282 dpixel[c] = normComponents[nc] * alpha; 2283 } 2284 dpixel[numColorComponents] = alpha; 2285 } else { 2286 for (int c = 0, nc = normOffset; c < numComponents; 2287 c++, nc++) { 2288 dpixel[c] = (double) normComponents[nc]; 2289 } 2290 } 2291 return dpixel; 2292 default: 2293 throw new UnsupportedOperationException("This method has not been "+ 2294 "implemented for transferType " + 2295 transferType); 2296 } 2297 } 2298 2299 /** 2300 * Returns an array of all of the color/alpha components in normalized 2301 * form, given a pixel in this <code>ColorModel</code>. The pixel 2302 * value is specified by an array of data elements of type transferType 2303 * passed in as an object reference. If pixel is not a primitive array 2304 * of type transferType, a <code>ClassCastException</code> is thrown. 2305 * An <code>ArrayIndexOutOfBoundsException</code> is thrown if 2306 * <code>pixel</code> is not large enough to hold a pixel value for this 2307 * <code>ColorModel</code>. 2308 * Normalized components are float values between a per component minimum 2309 * and maximum specified by the <code>ColorSpace</code> object for this 2310 * <code>ColorModel</code>. If the 2311 * <code>normComponents</code> array is <code>null</code>, a new array 2312 * will be allocated. The <code>normComponents</code> array 2313 * will be returned. Color/alpha components are stored in the 2314 * <code>normComponents</code> array starting at 2315 * <code>normOffset</code> (even if the array is allocated by this 2316 * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown 2317 * if the <code>normComponents</code> array is not <code>null</code> 2318 * and is not large enough to hold all the color and alpha components 2319 * (starting at <code>normOffset</code>). 2320 * <p> 2321 * This method must be overridden by a subclass if that subclass 2322 * is designed to translate pixel sample values to color component values 2323 * in a non-default way. The default translations implemented by this 2324 * class is described in the class comments. Any subclass implementing 2325 * a non-default translation must follow the constraints on allowable 2326 * translations defined there. 2327 * @param pixel the specified pixel 2328 * @param normComponents an array to receive the normalized components 2329 * @param normOffset the offset into the <code>normComponents</code> 2330 * array at which to start storing normalized components 2331 * @return an array containing normalized color and alpha 2332 * components. 2333 * @throws ClassCastException if <code>pixel</code> is not a primitive 2334 * array of type transferType 2335 * @throws ArrayIndexOutOfBoundsException if 2336 * <code>normComponents</code> is not large enough to hold all 2337 * color and alpha components starting at <code>normOffset</code> 2338 * @throws ArrayIndexOutOfBoundsException if 2339 * <code>pixel</code> is not large enough to hold a pixel 2340 * value for this <code>ColorModel</code>. 2341 * @since 1.4 2342 */ 2343 public float[] getNormalizedComponents(Object pixel, 2344 float[] normComponents, 2345 int normOffset) { 2346 if (normComponents == null) { 2347 normComponents = new float[numComponents+normOffset]; 2348 } 2349 switch (transferType) { 2350 case DataBuffer.TYPE_BYTE: 2351 byte[] bpixel = (byte[]) pixel; 2352 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { 2353 normComponents[nc] = ((float) (bpixel[c] & 0xff)) / 2354 ((float) ((1 << nBits[c]) - 1)); 2355 } 2356 break; 2357 case DataBuffer.TYPE_USHORT: 2358 short[] uspixel = (short[]) pixel; 2359 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { 2360 normComponents[nc] = ((float) (uspixel[c] & 0xffff)) / 2409 // possible case, in which this method is overridden, nonStdScale 2410 // is set true by initScale(), the subclass method for some 2411 // reason calls this superclass method, but the min and 2412 // diffMinMax arrays were never initialized by setupLUTs(). In 2413 // that case, the right thing to do is follow the intended 2414 // semantics of this method, and rescale the color components 2415 // only if the ColorSpace min/max were detected to be other 2416 // than 0.0/1.0 by setupLUTs(). Note that this implies the 2417 // transferType is byte, ushort, int, or short - i.e. components 2418 // derived from float and double pixel data are never rescaled. 2419 for (int c = 0; c < numColorComponents; c++) { 2420 normComponents[c + normOffset] = min[c] + 2421 diffMinMax[c] * normComponents[c + normOffset]; 2422 } 2423 } 2424 return normComponents; 2425 } 2426 2427 /** 2428 * Forces the raster data to match the state specified in the 2429 * <CODE>isAlphaPremultiplied</CODE> variable, assuming the data 2430 * is currently correctly described by this <CODE>ColorModel</CODE>. 2431 * It may multiply or divide the color raster data by alpha, or 2432 * do nothing if the data is in the correct state. If the data needs 2433 * to be coerced, this method also returns an instance of 2434 * this <CODE>ColorModel</CODE> with 2435 * the <CODE>isAlphaPremultiplied</CODE> flag set appropriately. 2436 * Since <code>ColorModel</code> can be subclassed, subclasses inherit 2437 * the implementation of this method and if they don't override it 2438 * then they throw an exception if they use an unsupported 2439 * <code>transferType</code>. 2440 * 2441 * @throws NullPointerException if <code>raster</code> is 2442 * <code>null</code> and data coercion is required. 2443 * @throws UnsupportedOperationException if the transfer type of 2444 * this <CODE>ComponentColorModel</CODE> 2445 * is not one of the supported transfer types: 2446 * <CODE>DataBuffer.TYPE_BYTE</CODE>, <CODE>DataBuffer.TYPE_USHORT</CODE>, 2447 * <CODE>DataBuffer.TYPE_INT</CODE>, <CODE>DataBuffer.TYPE_SHORT</CODE>, 2448 * <CODE>DataBuffer.TYPE_FLOAT</CODE>, or <CODE>DataBuffer.TYPE_DOUBLE</CODE>. 2449 */ 2450 public ColorModel coerceData (WritableRaster raster, 2451 boolean isAlphaPremultiplied) { 2452 if ((supportsAlpha == false) || 2453 (this.isAlphaPremultiplied == isAlphaPremultiplied)) 2454 { 2455 // Nothing to do 2456 return this; 2457 } 2458 2459 int w = raster.getWidth(); 2460 int h = raster.getHeight(); 2461 int aIdx = raster.getNumBands() - 1; 2462 float normAlpha; 2463 int rminX = raster.getMinX(); 2464 int rY = raster.getMinY(); 2465 int rX; 2466 if (isAlphaPremultiplied) { 2467 switch (transferType) { 2468 case DataBuffer.TYPE_BYTE: { 2757 default: 2758 throw new UnsupportedOperationException("This method has not been "+ 2759 "implemented for transferType " + transferType); 2760 } 2761 } 2762 2763 // Return a new color model 2764 if (!signed) { 2765 return new ComponentColorModel(colorSpace, nBits, supportsAlpha, 2766 isAlphaPremultiplied, transparency, 2767 transferType); 2768 } else { 2769 return new ComponentColorModel(colorSpace, supportsAlpha, 2770 isAlphaPremultiplied, transparency, 2771 transferType); 2772 } 2773 2774 } 2775 2776 /** 2777 * Returns true if <CODE>raster</CODE> is compatible with this 2778 * <CODE>ColorModel</CODE>; false if it is not. 2779 * 2780 * @param raster The <CODE>Raster</CODE> object to test for compatibility. 2781 * 2782 * @return <CODE>true</CODE> if <CODE>raster</CODE> is compatible with this 2783 * <CODE>ColorModel</CODE>, <CODE>false</CODE> if it is not. 2784 */ 2785 public boolean isCompatibleRaster(Raster raster) { 2786 2787 SampleModel sm = raster.getSampleModel(); 2788 2789 if (sm instanceof ComponentSampleModel) { 2790 if (sm.getNumBands() != getNumComponents()) { 2791 return false; 2792 } 2793 for (int i=0; i<nBits.length; i++) { 2794 if (sm.getSampleSize(i) < nBits[i]) { 2795 return false; 2796 } 2797 } 2798 return (raster.getTransferType() == transferType); 2799 } 2800 else { 2801 return false; 2802 } 2803 } 2804 2805 /** 2806 * Creates a <CODE>WritableRaster</CODE> with the specified width and height, 2807 * that has a data layout (<CODE>SampleModel</CODE>) compatible with 2808 * this <CODE>ColorModel</CODE>. 2809 * 2810 * @param w The width of the <CODE>WritableRaster</CODE> you want to create. 2811 * @param h The height of the <CODE>WritableRaster</CODE> you want to create. 2812 * 2813 * @return A <CODE>WritableRaster</CODE> that is compatible with 2814 * this <CODE>ColorModel</CODE>. 2815 * @see WritableRaster 2816 * @see SampleModel 2817 */ 2818 public WritableRaster createCompatibleWritableRaster (int w, int h) { 2819 int dataSize = w*h*numComponents; 2820 WritableRaster raster = null; 2821 2822 switch (transferType) { 2823 case DataBuffer.TYPE_BYTE: 2824 case DataBuffer.TYPE_USHORT: 2825 raster = Raster.createInterleavedRaster(transferType, 2826 w, h, 2827 numComponents, null); 2828 break; 2829 default: 2830 SampleModel sm = createCompatibleSampleModel(w, h); 2831 DataBuffer db = sm.createDataBuffer(); 2832 raster = Raster.createWritableRaster(sm, db, null); 2833 } 2834 2835 return raster; 2836 } 2837 2838 /** 2839 * Creates a <CODE>SampleModel</CODE> with the specified width and height, 2840 * that has a data layout compatible with this <CODE>ColorModel</CODE>. 2841 * 2842 * @param w The width of the <CODE>SampleModel</CODE> you want to create. 2843 * @param h The height of the <CODE>SampleModel</CODE> you want to create. 2844 * 2845 * @return A <CODE>SampleModel</CODE> that is compatible with this 2846 * <CODE>ColorModel</CODE>. 2847 * 2848 * @see SampleModel 2849 */ 2850 public SampleModel createCompatibleSampleModel(int w, int h) { 2851 int[] bandOffsets = new int[numComponents]; 2852 for (int i=0; i < numComponents; i++) { 2853 bandOffsets[i] = i; 2854 } 2855 switch (transferType) { 2856 case DataBuffer.TYPE_BYTE: 2857 case DataBuffer.TYPE_USHORT: 2858 return new PixelInterleavedSampleModel(transferType, w, h, 2859 numComponents, 2860 w*numComponents, 2861 bandOffsets); 2862 default: 2863 return new ComponentSampleModel(transferType, w, h, 2864 numComponents, 2865 w*numComponents, 2866 bandOffsets); 2867 } 2868 } 2869 2870 /** 2871 * Checks whether or not the specified <CODE>SampleModel</CODE> 2872 * is compatible with this <CODE>ColorModel</CODE>. 2873 * 2874 * @param sm The <CODE>SampleModel</CODE> to test for compatibility. 2875 * 2876 * @return <CODE>true</CODE> if the <CODE>SampleModel</CODE> is 2877 * compatible with this <CODE>ColorModel</CODE>, <CODE>false</CODE> 2878 * if it is not. 2879 * 2880 * @see SampleModel 2881 */ 2882 public boolean isCompatibleSampleModel(SampleModel sm) { 2883 if (!(sm instanceof ComponentSampleModel)) { 2884 return false; 2885 } 2886 2887 // Must have the same number of components 2888 if (numComponents != sm.getNumBands()) { 2889 return false; 2890 } 2891 2892 if (sm.getTransferType() != transferType) { 2893 return false; 2894 } 2895 2896 return true; 2897 } 2898 2899 /** 2900 * Returns a <CODE>Raster</CODE> representing the alpha channel of an image, 2901 * extracted from the input <CODE>Raster</CODE>. 2902 * This method assumes that <CODE>Raster</CODE> objects associated with 2903 * this <CODE>ColorModel</CODE> store the alpha band, if present, as 2904 * the last band of image data. Returns null if there is no separate spatial 2905 * alpha channel associated with this <CODE>ColorModel</CODE>. 2906 * This method creates a new <CODE>Raster</CODE>, but will share the data 2907 * array. 2908 * 2909 * @param raster The <CODE>WritableRaster</CODE> from which to extract the 2910 * alpha channel. 2911 * 2912 * @return A <CODE>WritableRaster</CODE> containing the image's alpha channel. 2913 * 2914 */ 2915 public WritableRaster getAlphaRaster(WritableRaster raster) { 2916 if (hasAlpha() == false) { 2917 return null; 2918 } 2919 2920 int x = raster.getMinX(); 2921 int y = raster.getMinY(); 2922 int[] band = new int[1]; 2923 band[0] = raster.getNumBands() - 1; 2924 return raster.createWritableChild(x, y, raster.getWidth(), 2925 raster.getHeight(), x, y, 2926 band); 2927 } 2928 2929 /** 2930 * Compares this color model with another for equality. 2931 * 2932 * @param obj The object to compare with this color model. 2933 * @return <CODE>true</CODE> if the color model objects are equal, 2934 * <CODE>false</CODE> if they are not. 2935 */ 2936 public boolean equals(Object obj) { 2937 if (!super.equals(obj)) { 2938 return false; 2939 } 2940 2941 if (obj.getClass() != getClass()) { 2942 return false; 2943 } 2944 2945 return true; 2946 } 2947 2948 } | 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt.image; 27 28 import java.awt.color.ColorSpace; 29 import java.awt.color.ICC_ColorSpace; 30 31 /** 32 * A {@code ColorModel} class that works with pixel values that 33 * represent color and alpha information as separate samples and that 34 * store each sample in a separate data element. This class can be 35 * used with an arbitrary {@code ColorSpace}. The number of 36 * color samples in the pixel values must be same as the number of 37 * color components in the {@code ColorSpace}. There may be a 38 * single alpha sample. 39 * <p> 40 * For those methods that use 41 * a primitive array pixel representation of type {@code transferType}, 42 * the array length is the same as the number of color and alpha samples. 43 * Color samples are stored first in the array followed by the alpha 44 * sample, if present. The order of the color samples is specified 45 * by the {@code ColorSpace}. Typically, this order reflects the 46 * name of the color space type. For example, for {@code TYPE_RGB}, 47 * index 0 corresponds to red, index 1 to green, and index 2 to blue. 48 * <p> 49 * The translation from pixel sample values to color/alpha components for 50 * display or processing purposes is based on a one-to-one correspondence of 51 * samples to components. 52 * Depending on the transfer type used to create an instance of 53 * {@code ComponentColorModel}, the pixel sample values 54 * represented by that instance may be signed or unsigned and may 55 * be of integral type or float or double (see below for details). 56 * The translation from sample values to normalized color/alpha components 57 * must follow certain rules. For float and double samples, the translation 58 * is an identity, i.e. normalized component values are equal to the 59 * corresponding sample values. For integral samples, the translation 60 * should be only a simple scale and offset, where the scale and offset 61 * constants may be different for each component. The result of 62 * applying the scale and offset constants is a set of color/alpha 63 * component values, which are guaranteed to fall within a certain 64 * range. Typically, the range for a color component will be the range 65 * defined by the {@code getMinValue} and {@code getMaxValue} 66 * methods of the {@code ColorSpace} class. The range for an 67 * alpha component should be 0.0 to 1.0. 68 * <p> 69 * Instances of {@code ComponentColorModel} created with transfer types 70 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 71 * and {@code DataBuffer.TYPE_INT} have pixel sample values which 72 * are treated as unsigned integral values. 73 * The number of bits in a color or alpha sample of a pixel value might not 74 * be the same as the number of bits for the corresponding color or alpha 75 * sample passed to the 76 * {@code ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)} 77 * constructor. In 78 * that case, this class assumes that the least significant n bits of a sample 79 * value hold the component value, where n is the number of significant bits 80 * for the component passed to the constructor. It also assumes that 81 * any higher-order bits in a sample value are zero. Thus, sample values 82 * range from 0 to 2<sup>n</sup> - 1. This class maps these sample values 83 * to normalized color component values such that 0 maps to the value 84 * obtained from the {@code ColorSpace's getMinValue} 85 * method for each component and 2<sup>n</sup> - 1 maps to the value 86 * obtained from {@code getMaxValue}. To create a 87 * {@code ComponentColorModel} with a different color sample mapping 88 * requires subclassing this class and overriding the 89 * {@code getNormalizedComponents(Object, float[], int)} method. 90 * The mapping for an alpha sample always maps 0 to 0.0 and 91 * 2<sup>n</sup> - 1 to 1.0. 92 * <p> 93 * For instances with unsigned sample values, 94 * the unnormalized color/alpha component representation is only 95 * supported if two conditions hold. First, sample value 0 must 96 * map to normalized component value 0.0 and sample value 2<sup>n</sup> - 1 97 * to 1.0. Second the min/max range of all color components of the 98 * {@code ColorSpace} must be 0.0 to 1.0. In this case, the 99 * component representation is the n least 100 * significant bits of the corresponding sample. Thus each component is 101 * an unsigned integral value between 0 and 2<sup>n</sup> - 1, where 102 * n is the number of significant bits for a particular component. 103 * If these conditions are not met, any method taking an unnormalized 104 * component argument will throw an {@code IllegalArgumentException}. 105 * <p> 106 * Instances of {@code ComponentColorModel} created with transfer types 107 * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, and 108 * {@code DataBuffer.TYPE_DOUBLE} have pixel sample values which 109 * are treated as signed short, float, or double values. 110 * Such instances do not support the unnormalized color/alpha component 111 * representation, so any methods taking such a representation as an argument 112 * will throw an {@code IllegalArgumentException} when called on one 113 * of these instances. The normalized component values of instances 114 * of this class have a range which depends on the transfer 115 * type as follows: for float samples, the full range of the float data 116 * type; for double samples, the full range of the float data type 117 * (resulting from casting double to float); for short samples, 118 * from approximately -maxVal to +maxVal, where maxVal is the per 119 * component maximum value for the {@code ColorSpace} 120 * (-32767 maps to -maxVal, 0 maps to 0.0, and 32767 maps 121 * to +maxVal). A subclass may override the scaling for short sample 122 * values to normalized component values by overriding the 123 * {@code getNormalizedComponents(Object, float[], int)} method. 124 * For float and double samples, the normalized component values are 125 * taken to be equal to the corresponding sample values, and subclasses 126 * should not attempt to add any non-identity scaling for these transfer 127 * types. 128 * <p> 129 * Instances of {@code ComponentColorModel} created with transfer types 130 * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, and 131 * {@code DataBuffer.TYPE_DOUBLE} 132 * use all the bits of all sample values. Thus all color/alpha components 133 * have 16 bits when using {@code DataBuffer.TYPE_SHORT}, 32 bits when 134 * using {@code DataBuffer.TYPE_FLOAT}, and 64 bits when using 135 * {@code DataBuffer.TYPE_DOUBLE}. When the 136 * {@code ComponentColorModel(ColorSpace, int[], boolean, boolean, int, int)} 137 * form of constructor is used with one of these transfer types, the 138 * bits array argument is ignored. 139 * <p> 140 * It is possible to have color/alpha sample values 141 * which cannot be reasonably interpreted as component values for rendering. 142 * This can happen when {@code ComponentColorModel} is subclassed to 143 * override the mapping of unsigned sample values to normalized color 144 * component values or when signed sample values outside a certain range 145 * are used. (As an example, specifying an alpha component as a signed 146 * short value outside the range 0 to 32767, normalized range 0.0 to 1.0, can 147 * lead to unexpected results.) It is the 148 * responsibility of applications to appropriately scale pixel data before 149 * rendering such that color components fall within the normalized range 150 * of the {@code ColorSpace} (obtained using the {@code getMinValue} 151 * and {@code getMaxValue} methods of the {@code ColorSpace} class) 152 * and the alpha component is between 0.0 and 1.0. If color or alpha 153 * component values fall outside these ranges, rendering results are 154 * indeterminate. 155 * <p> 156 * Methods that use a single int pixel representation throw 157 * an {@code IllegalArgumentException}, unless the number of components 158 * for the {@code ComponentColorModel} is one and the component 159 * value is unsigned -- in other words, a single color component using 160 * a transfer type of {@code DataBuffer.TYPE_BYTE}, 161 * {@code DataBuffer.TYPE_USHORT}, or {@code DataBuffer.TYPE_INT} 162 * and no alpha. 163 * <p> 164 * A {@code ComponentColorModel} can be used in conjunction with a 165 * {@code ComponentSampleModel}, a {@code BandedSampleModel}, 166 * or a {@code PixelInterleavedSampleModel} to construct a 167 * {@code BufferedImage}. 168 * 169 * @see ColorModel 170 * @see ColorSpace 171 * @see ComponentSampleModel 172 * @see BandedSampleModel 173 * @see PixelInterleavedSampleModel 174 * @see BufferedImage 175 * 176 */ 177 public class ComponentColorModel extends ColorModel { 178 179 /** 180 * {@code signed} is {@code true} for {@code short}, 181 * {@code float}, and {@code double} transfer types; it 182 * is {@code false} for {@code byte}, {@code ushort}, 183 * and {@code int} transfer types. 184 */ 185 private boolean signed; // true for transfer types short, float, double 186 // false for byte, ushort, int 187 private boolean is_sRGB_stdScale; 188 private boolean is_LinearRGB_stdScale; 189 private boolean is_LinearGray_stdScale; 190 private boolean is_ICCGray_stdScale; 191 private byte[] tosRGB8LUT; 192 private byte[] fromsRGB8LUT8; 193 private short[] fromsRGB8LUT16; 194 private byte[] fromLinearGray16ToOtherGray8LUT; 195 private short[] fromLinearGray16ToOtherGray16LUT; 196 private boolean needScaleInit; 197 private boolean noUnnorm; 198 private boolean nonStdScale; 199 private float[] min; 200 private float[] diffMinMax; 201 private float[] compOffset; 202 private float[] compScale; 203 204 /** 205 * Constructs a {@code ComponentColorModel} from the specified 206 * parameters. Color components will be in the specified 207 * {@code ColorSpace}. The supported transfer types are 208 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 209 * {@code DataBuffer.TYPE_INT}, 210 * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, 211 * and {@code DataBuffer.TYPE_DOUBLE}. 212 * If not null, the {@code bits} array specifies the 213 * number of significant bits per color and alpha component and its 214 * length should be at least the number of components in the 215 * {@code ColorSpace} if there is no alpha 216 * information in the pixel values, or one more than this number if 217 * there is alpha information. When the {@code transferType} is 218 * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, 219 * or {@code DataBuffer.TYPE_DOUBLE} the {@code bits} array 220 * argument is ignored. {@code hasAlpha} indicates whether alpha 221 * information is present. If {@code hasAlpha} is true, then 222 * the boolean {@code isAlphaPremultiplied} 223 * specifies how to interpret color and alpha samples in pixel values. 224 * If the boolean is true, color samples are assumed to have been 225 * multiplied by the alpha sample. The {@code transparency} 226 * specifies what alpha values can be represented by this color model. 227 * The acceptable {@code transparency} values are 228 * {@code OPAQUE}, {@code BITMASK} or {@code TRANSLUCENT}. 229 * The {@code transferType} is the type of primitive array used 230 * to represent pixel values. 231 * 232 * @param colorSpace The {@code ColorSpace} associated 233 * with this color model. 234 * @param bits The number of significant bits per component. 235 * May be null, in which case all bits of all 236 * component samples will be significant. 237 * Ignored if transferType is one of 238 * {@code DataBuffer.TYPE_SHORT}, 239 * {@code DataBuffer.TYPE_FLOAT}, or 240 * {@code DataBuffer.TYPE_DOUBLE}, 241 * in which case all bits of all component 242 * samples will be significant. 243 * @param hasAlpha If true, this color model supports alpha. 244 * @param isAlphaPremultiplied If true, alpha is premultiplied. 245 * @param transparency Specifies what alpha values can be represented 246 * by this color model. 247 * @param transferType Specifies the type of primitive array used to 248 * represent pixel values. 249 * 250 * @throws IllegalArgumentException If the {@code bits} array 251 * argument is not null, its length is less than the number of 252 * color and alpha components, and transferType is one of 253 * {@code DataBuffer.TYPE_BYTE}, 254 * {@code DataBuffer.TYPE_USHORT}, or 255 * {@code DataBuffer.TYPE_INT}. 256 * @throws IllegalArgumentException If transferType is not one of 257 * {@code DataBuffer.TYPE_BYTE}, 258 * {@code DataBuffer.TYPE_USHORT}, 259 * {@code DataBuffer.TYPE_INT}, 260 * {@code DataBuffer.TYPE_SHORT}, 261 * {@code DataBuffer.TYPE_FLOAT}, or 262 * {@code DataBuffer.TYPE_DOUBLE}. 263 * 264 * @see ColorSpace 265 * @see java.awt.Transparency 266 */ 267 public ComponentColorModel (ColorSpace colorSpace, 268 int[] bits, 269 boolean hasAlpha, 270 boolean isAlphaPremultiplied, 271 int transparency, 272 int transferType) { 273 super (bitsHelper(transferType, colorSpace, hasAlpha), 274 bitsArrayHelper(bits, transferType, colorSpace, hasAlpha), 275 colorSpace, hasAlpha, isAlphaPremultiplied, transparency, 276 transferType); 277 switch(transferType) { 278 case DataBuffer.TYPE_BYTE: 279 case DataBuffer.TYPE_USHORT: 280 case DataBuffer.TYPE_INT: 281 signed = false; 282 needScaleInit = true; 283 break; 284 case DataBuffer.TYPE_SHORT: 285 signed = true; 286 needScaleInit = true; 287 break; 288 case DataBuffer.TYPE_FLOAT: 289 case DataBuffer.TYPE_DOUBLE: 290 signed = true; 291 needScaleInit = false; 292 noUnnorm = true; 293 nonStdScale = false; 294 break; 295 default: 296 throw new IllegalArgumentException("This constructor is not "+ 297 "compatible with transferType " + transferType); 298 } 299 setupLUTs(); 300 } 301 302 /** 303 * Constructs a {@code ComponentColorModel} from the specified 304 * parameters. Color components will be in the specified 305 * {@code ColorSpace}. The supported transfer types are 306 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 307 * {@code DataBuffer.TYPE_INT}, 308 * {@code DataBuffer.TYPE_SHORT}, {@code DataBuffer.TYPE_FLOAT}, 309 * and {@code DataBuffer.TYPE_DOUBLE}. The number of significant 310 * bits per color and alpha component will be 8, 16, 32, 16, 32, or 64, 311 * respectively. The number of color components will be the 312 * number of components in the {@code ColorSpace}. There will be 313 * an alpha component if {@code hasAlpha} is {@code true}. 314 * If {@code hasAlpha} is true, then 315 * the boolean {@code isAlphaPremultiplied} 316 * specifies how to interpret color and alpha samples in pixel values. 317 * If the boolean is true, color samples are assumed to have been 318 * multiplied by the alpha sample. The {@code transparency} 319 * specifies what alpha values can be represented by this color model. 320 * The acceptable {@code transparency} values are 321 * {@code OPAQUE}, {@code BITMASK} or {@code TRANSLUCENT}. 322 * The {@code transferType} is the type of primitive array used 323 * to represent pixel values. 324 * 325 * @param colorSpace The {@code ColorSpace} associated 326 * with this color model. 327 * @param hasAlpha If true, this color model supports alpha. 328 * @param isAlphaPremultiplied If true, alpha is premultiplied. 329 * @param transparency Specifies what alpha values can be represented 330 * by this color model. 331 * @param transferType Specifies the type of primitive array used to 332 * represent pixel values. 333 * 334 * @throws IllegalArgumentException If transferType is not one of 335 * {@code DataBuffer.TYPE_BYTE}, 336 * {@code DataBuffer.TYPE_USHORT}, 337 * {@code DataBuffer.TYPE_INT}, 338 * {@code DataBuffer.TYPE_SHORT}, 339 * {@code DataBuffer.TYPE_FLOAT}, or 340 * {@code DataBuffer.TYPE_DOUBLE}. 341 * 342 * @see ColorSpace 343 * @see java.awt.Transparency 344 * @since 1.4 345 */ 346 public ComponentColorModel (ColorSpace colorSpace, 347 boolean hasAlpha, 348 boolean isAlphaPremultiplied, 349 int transparency, 350 int transferType) { 351 this(colorSpace, null, hasAlpha, isAlphaPremultiplied, 352 transparency, transferType); 353 } 354 355 private static int bitsHelper(int transferType, 356 ColorSpace colorSpace, 357 boolean hasAlpha) { 358 int numBits = DataBuffer.getDataTypeSize(transferType); 359 int numComponents = colorSpace.getNumComponents(); 360 if (hasAlpha) { 645 float[] norm = getNormalizedComponents(opixel, null, 0); 646 float[] rgb = colorSpace.toRGB(norm); 647 648 return (int) (rgb[idx] * 255.0f + 0.5f); 649 } 650 651 /** 652 * Returns the red color component for the specified pixel, scaled 653 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 654 * is done if necessary. The pixel value is specified as an int. 655 * The returned value will be a non pre-multiplied value. 656 * If the alpha is premultiplied, this method divides 657 * it out before returning the value (if the alpha value is 0, 658 * the red value will be 0). 659 * 660 * @param pixel The pixel from which you want to get the red color component. 661 * 662 * @return The red color component for the specified pixel, as an int. 663 * 664 * @throws IllegalArgumentException If there is more than 665 * one component in this {@code ColorModel}. 666 * @throws IllegalArgumentException If the component value for this 667 * {@code ColorModel} is signed 668 */ 669 public int getRed(int pixel) { 670 return getRGBComponent(pixel, 0); 671 } 672 673 /** 674 * Returns the green color component for the specified pixel, scaled 675 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 676 * is done if necessary. The pixel value is specified as an int. 677 * The returned value will be a non 678 * pre-multiplied value. If the alpha is premultiplied, this method 679 * divides it out before returning the value (if the alpha value is 0, 680 * the green value will be 0). 681 * 682 * @param pixel The pixel from which you want to get the green color component. 683 * 684 * @return The green color component for the specified pixel, as an int. 685 * 686 * @throws IllegalArgumentException If there is more than 687 * one component in this {@code ColorModel}. 688 * @throws IllegalArgumentException If the component value for this 689 * {@code ColorModel} is signed 690 */ 691 public int getGreen(int pixel) { 692 return getRGBComponent(pixel, 1); 693 } 694 695 /** 696 * Returns the blue color component for the specified pixel, scaled 697 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 698 * is done if necessary. The pixel value is specified as an int. 699 * The returned value will be a non 700 * pre-multiplied value. If the alpha is premultiplied, this method 701 * divides it out before returning the value (if the alpha value is 0, 702 * the blue value will be 0). 703 * 704 * @param pixel The pixel from which you want to get the blue color component. 705 * 706 * @return The blue color component for the specified pixel, as an int. 707 * 708 * @throws IllegalArgumentException If there is more than 709 * one component in this {@code ColorModel}. 710 * @throws IllegalArgumentException If the component value for this 711 * {@code ColorModel} is signed 712 */ 713 public int getBlue(int pixel) { 714 return getRGBComponent(pixel, 2); 715 } 716 717 /** 718 * Returns the alpha component for the specified pixel, scaled 719 * from 0 to 255. The pixel value is specified as an int. 720 * 721 * @param pixel The pixel from which you want to get the alpha component. 722 * 723 * @return The alpha component for the specified pixel, as an int. 724 * 725 * @throws IllegalArgumentException If there is more than 726 * one component in this {@code ColorModel}. 727 * @throws IllegalArgumentException If the component value for this 728 * {@code ColorModel} is signed 729 */ 730 public int getAlpha(int pixel) { 731 if (supportsAlpha == false) { 732 return 255; 733 } 734 if (numComponents > 1) { 735 throw new 736 IllegalArgumentException("More than one component per pixel"); 737 } 738 if (signed) { 739 throw new 740 IllegalArgumentException("Component value is signed"); 741 } 742 743 return (int) ((((float) pixel) / ((1<<nBits[0])-1)) * 255.0f + 0.5f); 744 } 745 746 /** 747 * Returns the color/alpha components of the pixel in the default 748 * RGB color model format. A color conversion is done if necessary. 749 * The returned value will be in a non pre-multiplied format. If 750 * the alpha is premultiplied, this method divides it out of the 751 * color components (if the alpha value is 0, the color values will be 0). 752 * 753 * @param pixel The pixel from which you want to get the color/alpha components. 754 * 755 * @return The color/alpha components for the specified pixel, as an int. 756 * 757 * @throws IllegalArgumentException If there is more than 758 * one component in this {@code ColorModel}. 759 * @throws IllegalArgumentException If the component value for this 760 * {@code ColorModel} is signed 761 */ 762 public int getRGB(int pixel) { 763 if (numComponents > 1) { 764 throw new 765 IllegalArgumentException("More than one component per pixel"); 766 } 767 if (signed) { 768 throw new 769 IllegalArgumentException("Component value is signed"); 770 } 771 772 return (getAlpha(pixel) << 24) 773 | (getRed(pixel) << 16) 774 | (getGreen(pixel) << 8) 775 | (getBlue(pixel) << 0); 776 } 777 778 private int extractComponent(Object inData, int idx, int precision) { 779 // Extract component idx from inData. The precision argument 780 // should be either 8 or 16. If it's 8, this method will return 896 if (is_sRGB_stdScale) { 897 return extractComponent(inData, idx, 8); 898 } else if (is_LinearRGB_stdScale) { 899 int lutidx = extractComponent(inData, idx, 16); 900 return tosRGB8LUT[lutidx] & 0xff; 901 } else if (is_ICCGray_stdScale) { 902 int lutidx = extractComponent(inData, 0, 16); 903 return tosRGB8LUT[lutidx] & 0xff; 904 } 905 906 // Not CS_sRGB, CS_LINEAR_RGB, or any TYPE_GRAY ICC_ColorSpace 907 float[] norm = getNormalizedComponents(inData, null, 0); 908 // Note that getNormalizedComponents returns non-premultiplied values 909 float[] rgb = colorSpace.toRGB(norm); 910 return (int) (rgb[idx] * 255.0f + 0.5f); 911 } 912 913 /** 914 * Returns the red color component for the specified pixel, scaled 915 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion 916 * is done if necessary. The {@code pixel} value is specified by an array 917 * of data elements of type {@code transferType} passed in as an object 918 * reference. The returned value will be a non pre-multiplied value. If the 919 * alpha is premultiplied, this method divides it out before returning 920 * the value (if the alpha value is 0, the red value will be 0). Since 921 * {@code ComponentColorModel} can be subclassed, subclasses 922 * inherit the implementation of this method and if they don't override 923 * it then they throw an exception if they use an unsupported 924 * {@code transferType}. 925 * 926 * @param inData The pixel from which you want to get the red color component, 927 * specified by an array of data elements of type {@code transferType}. 928 * 929 * @return The red color component for the specified pixel, as an int. 930 * 931 * @throws ClassCastException If {@code inData} is not a primitive array 932 * of type {@code transferType}. 933 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not 934 * large enough to hold a pixel value for this 935 * {@code ColorModel}. 936 * @throws UnsupportedOperationException If the transfer type of 937 * this {@code ComponentColorModel} 938 * is not one of the supported transfer types: 939 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 940 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 941 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 942 */ 943 public int getRed(Object inData) { 944 return getRGBComponent(inData, 0); 945 } 946 947 948 /** 949 * Returns the green color component for the specified pixel, scaled 950 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. 951 * A color conversion is done if necessary. The {@code pixel} value 952 * is specified by an array of data elements of type {@code transferType} 953 * passed in as an object reference. The returned value is a non pre-multiplied 954 * value. If the alpha is premultiplied, this method divides it out before 955 * returning the value (if the alpha value is 0, the green value will be 0). 956 * Since {@code ComponentColorModel} can be subclassed, 957 * subclasses inherit the implementation of this method and if they 958 * don't override it then they throw an exception if they use an 959 * unsupported {@code transferType}. 960 * 961 * @param inData The pixel from which you want to get the green color component, 962 * specified by an array of data elements of type {@code transferType}. 963 * 964 * @return The green color component for the specified pixel, as an int. 965 * 966 * @throws ClassCastException If {@code inData} is not a primitive array 967 * of type {@code transferType}. 968 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not 969 * large enough to hold a pixel value for this 970 * {@code ColorModel}. 971 * @throws UnsupportedOperationException If the transfer type of 972 * this {@code ComponentColorModel} 973 * is not one of the supported transfer types: 974 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 975 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 976 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 977 */ 978 public int getGreen(Object inData) { 979 return getRGBComponent(inData, 1); 980 } 981 982 983 /** 984 * Returns the blue color component for the specified pixel, scaled 985 * from 0 to 255 in the default RGB {@code ColorSpace}, sRGB. 986 * A color conversion is done if necessary. The {@code pixel} value is 987 * specified by an array of data elements of type {@code transferType} 988 * passed in as an object reference. The returned value is a non pre-multiplied 989 * value. If the alpha is premultiplied, this method divides it out before 990 * returning the value (if the alpha value is 0, the blue value will be 0). 991 * Since {@code ComponentColorModel} can be subclassed, 992 * subclasses inherit the implementation of this method and if they 993 * don't override it then they throw an exception if they use an 994 * unsupported {@code transferType}. 995 * 996 * @param inData The pixel from which you want to get the blue color component, 997 * specified by an array of data elements of type {@code transferType}. 998 * 999 * @return The blue color component for the specified pixel, as an int. 1000 * 1001 * @throws ClassCastException If {@code inData} is not a primitive array 1002 * of type {@code transferType}. 1003 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not 1004 * large enough to hold a pixel value for this 1005 * {@code ColorModel}. 1006 * @throws UnsupportedOperationException If the transfer type of 1007 * this {@code ComponentColorModel} 1008 * is not one of the supported transfer types: 1009 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1010 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 1011 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 1012 */ 1013 public int getBlue(Object inData) { 1014 return getRGBComponent(inData, 2); 1015 } 1016 1017 /** 1018 * Returns the alpha component for the specified pixel, scaled from 1019 * 0 to 255. The pixel value is specified by an array of data 1020 * elements of type {@code transferType} passed in as an 1021 * object reference. Since {@code ComponentColorModel} can be 1022 * subclassed, subclasses inherit the 1023 * implementation of this method and if they don't override it then 1024 * they throw an exception if they use an unsupported 1025 * {@code transferType}. 1026 * 1027 * @param inData The pixel from which you want to get the alpha component, 1028 * specified by an array of data elements of type {@code transferType}. 1029 * 1030 * @return The alpha component for the specified pixel, as an int. 1031 * 1032 * @throws ClassCastException If {@code inData} is not a primitive array 1033 * of type {@code transferType}. 1034 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not 1035 * large enough to hold a pixel value for this 1036 * {@code ColorModel}. 1037 * @throws UnsupportedOperationException If the transfer type of 1038 * this {@code ComponentColorModel} 1039 * is not one of the supported transfer types: 1040 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1041 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 1042 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 1043 */ 1044 public int getAlpha(Object inData) { 1045 if (supportsAlpha == false) { 1046 return 255; 1047 } 1048 1049 int alpha = 0; 1050 int aIdx = numColorComponents; 1051 int mask = (1 << nBits[aIdx]) - 1; 1052 1053 switch (transferType) { 1054 case DataBuffer.TYPE_SHORT: 1055 short sdata[] = (short[])inData; 1056 alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f); 1057 return alpha; 1058 case DataBuffer.TYPE_FLOAT: 1059 float fdata[] = (float[])inData; 1060 alpha = (int) (fdata[aIdx] * 255.0f + 0.5f); 1061 return alpha; 1062 case DataBuffer.TYPE_DOUBLE: 1077 break; 1078 default: 1079 throw new 1080 UnsupportedOperationException("This method has not "+ 1081 "been implemented for transferType " + transferType); 1082 } 1083 1084 if (nBits[aIdx] == 8) { 1085 return alpha; 1086 } else { 1087 return (int) 1088 ((((float) alpha) / ((float) ((1 << nBits[aIdx]) - 1))) * 1089 255.0f + 0.5f); 1090 } 1091 } 1092 1093 /** 1094 * Returns the color/alpha components for the specified pixel in the 1095 * default RGB color model format. A color conversion is done if 1096 * necessary. The pixel value is specified by an 1097 * array of data elements of type {@code transferType} passed 1098 * in as an object reference. 1099 * The returned value is in a non pre-multiplied format. If 1100 * the alpha is premultiplied, this method divides it out of the 1101 * color components (if the alpha value is 0, the color values will be 0). 1102 * Since {@code ComponentColorModel} can be subclassed, 1103 * subclasses inherit the implementation of this method and if they 1104 * don't override it then they throw an exception if they use an 1105 * unsupported {@code transferType}. 1106 * 1107 * @param inData The pixel from which you want to get the color/alpha components, 1108 * specified by an array of data elements of type {@code transferType}. 1109 * 1110 * @return The color/alpha components for the specified pixel, as an int. 1111 * 1112 * @throws ClassCastException If {@code inData} is not a primitive array 1113 * of type {@code transferType}. 1114 * @throws ArrayIndexOutOfBoundsException if {@code inData} is not 1115 * large enough to hold a pixel value for this 1116 * {@code ColorModel}. 1117 * @throws UnsupportedOperationException If the transfer type of 1118 * this {@code ComponentColorModel} 1119 * is not one of the supported transfer types: 1120 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1121 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 1122 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 1123 * @see ColorModel#getRGBdefault 1124 */ 1125 public int getRGB(Object inData) { 1126 if (needScaleInit) { 1127 initScale(); 1128 } 1129 if (is_sRGB_stdScale || is_LinearRGB_stdScale) { 1130 return (getAlpha(inData) << 24) 1131 | (getRed(inData) << 16) 1132 | (getGreen(inData) << 8) 1133 | (getBlue(inData)); 1134 } else if (colorSpaceType == ColorSpace.TYPE_GRAY) { 1135 int gray = getRed(inData); // Red sRGB component should equal 1136 // green and blue components 1137 return (getAlpha(inData) << 24) 1138 | (gray << 16) 1139 | (gray << 8) 1140 | gray; 1141 } 1142 float[] norm = getNormalizedComponents(inData, null, 0); 1143 // Note that getNormalizedComponents returns non-premult values 1144 float[] rgb = colorSpace.toRGB(norm); 1145 return (getAlpha(inData) << 24) 1146 | (((int) (rgb[0] * 255.0f + 0.5f)) << 16) 1147 | (((int) (rgb[1] * 255.0f + 0.5f)) << 8) 1148 | (((int) (rgb[2] * 255.0f + 0.5f)) << 0); 1149 } 1150 1151 /** 1152 * Returns a data element array representation of a pixel in this 1153 * {@code ColorModel}, given an integer pixel representation 1154 * in the default RGB color model. 1155 * This array can then be passed to the {@code setDataElements} 1156 * method of a {@code WritableRaster} object. If the 1157 * {@code pixel} 1158 * parameter is null, a new array is allocated. Since 1159 * {@code ComponentColorModel} can be subclassed, subclasses 1160 * inherit the implementation of this method and if they don't 1161 * override it then 1162 * they throw an exception if they use an unsupported 1163 * {@code transferType}. 1164 * 1165 * @param rgb the integer representation of the pixel in the RGB 1166 * color model 1167 * @param pixel the specified pixel 1168 * @return The data element array representation of a pixel 1169 * in this {@code ColorModel}. 1170 * @throws ClassCastException If {@code pixel} is not null and 1171 * is not a primitive array of type {@code transferType}. 1172 * @throws ArrayIndexOutOfBoundsException If {@code pixel} is 1173 * not large enough to hold a pixel value for this 1174 * {@code ColorModel}. 1175 * @throws UnsupportedOperationException If the transfer type of 1176 * this {@code ComponentColorModel} 1177 * is not one of the supported transfer types: 1178 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1179 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 1180 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 1181 * 1182 * @see WritableRaster#setDataElements 1183 * @see SampleModel#setDataElements 1184 */ 1185 public Object getDataElements(int rgb, Object pixel) { 1186 // REMIND: Use rendering hints? 1187 1188 int red, grn, blu, alp; 1189 red = (rgb>>16) & 0xff; 1190 grn = (rgb>>8) & 0xff; 1191 blu = rgb & 0xff; 1192 1193 if (needScaleInit) { 1194 initScale(); 1195 } 1196 if (signed) { 1197 // Handle SHORT, FLOAT, & DOUBLE here 1198 1199 switch(transferType) { 1200 case DataBuffer.TYPE_SHORT: 1638 } 1639 case DataBuffer.TYPE_INT: 1640 if (maxBits > 23) { 1641 // fix 4412670 - for components of 24 or more bits 1642 // some calculations done above with float precision 1643 // may lose enough precision that the integer result 1644 // overflows nBits, so we need to clamp. 1645 for (int i = 0; i < numComponents; i++) { 1646 if (intpixel[i] > ((1<<nBits[i]) - 1)) { 1647 intpixel[i] = (1<<nBits[i]) - 1; 1648 } 1649 } 1650 } 1651 return intpixel; 1652 } 1653 throw new IllegalArgumentException("This method has not been "+ 1654 "implemented for transferType " + transferType); 1655 } 1656 1657 /** Returns an array of unnormalized color/alpha components given a pixel 1658 * in this {@code ColorModel}. 1659 * An IllegalArgumentException is thrown if the component value for this 1660 * {@code ColorModel} is not conveniently representable in the 1661 * unnormalized form. Color/alpha components are stored 1662 * in the {@code components} array starting at {@code offset} 1663 * (even if the array is allocated by this method). 1664 * 1665 * @param pixel The pixel value specified as an integer. 1666 * @param components An integer array in which to store the unnormalized 1667 * color/alpha components. If the {@code components} array is null, 1668 * a new array is allocated. 1669 * @param offset An offset into the {@code components} array. 1670 * 1671 * @return The components array. 1672 * 1673 * @throws IllegalArgumentException If there is more than one 1674 * component in this {@code ColorModel}. 1675 * @throws IllegalArgumentException If this 1676 * {@code ColorModel} does not support the unnormalized form 1677 * @throws ArrayIndexOutOfBoundsException If the {@code components} 1678 * array is not null and is not large enough to hold all the color and 1679 * alpha components (starting at offset). 1680 */ 1681 public int[] getComponents(int pixel, int[] components, int offset) { 1682 if (numComponents > 1) { 1683 throw new 1684 IllegalArgumentException("More than one component per pixel"); 1685 } 1686 if (needScaleInit) { 1687 initScale(); 1688 } 1689 if (noUnnorm) { 1690 throw new 1691 IllegalArgumentException( 1692 "This ColorModel does not support the unnormalized form"); 1693 } 1694 if (components == null) { 1695 components = new int[offset+1]; 1696 } 1697 1698 components[offset+0] = (pixel & ((1<<nBits[0]) - 1)); 1699 return components; 1700 } 1701 1702 /** 1703 * Returns an array of unnormalized color/alpha components given a pixel 1704 * in this {@code ColorModel}. The pixel value is specified by an 1705 * array of data elements of type {@code transferType} passed in as 1706 * an object reference. 1707 * An IllegalArgumentException is thrown if the component values for this 1708 * {@code ColorModel} are not conveniently representable in the 1709 * unnormalized form. 1710 * Color/alpha components are stored in the {@code components} array 1711 * starting at {@code offset} (even if the array is allocated by 1712 * this method). Since {@code ComponentColorModel} can be 1713 * subclassed, subclasses inherit the 1714 * implementation of this method and if they don't override it then 1715 * this method might throw an exception if they use an unsupported 1716 * {@code transferType}. 1717 * 1718 * @param pixel A pixel value specified by an array of data elements of 1719 * type {@code transferType}. 1720 * @param components An integer array in which to store the unnormalized 1721 * color/alpha components. If the {@code components} array is null, 1722 * a new array is allocated. 1723 * @param offset An offset into the {@code components} array. 1724 * 1725 * @return The {@code components} array. 1726 * 1727 * @throws IllegalArgumentException If this 1728 * {@code ComponentColorModel} does not support the unnormalized form 1729 * @throws UnsupportedOperationException in some cases iff the 1730 * transfer type of this {@code ComponentColorModel} 1731 * is not one of the following transfer types: 1732 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1733 * or {@code DataBuffer.TYPE_INT}. 1734 * @throws ClassCastException If {@code pixel} is not a primitive 1735 * array of type {@code transferType}. 1736 * @throws IllegalArgumentException If the {@code components} array is 1737 * not null and is not large enough to hold all the color and alpha 1738 * components (starting at offset), or if {@code pixel} is not large 1739 * enough to hold a pixel value for this ColorModel. 1740 */ 1741 public int[] getComponents(Object pixel, int[] components, int offset) { 1742 int intpixel[]; 1743 if (needScaleInit) { 1744 initScale(); 1745 } 1746 if (noUnnorm) { 1747 throw new 1748 IllegalArgumentException( 1749 "This ColorModel does not support the unnormalized form"); 1750 } 1751 if (pixel instanceof int[]) { 1752 intpixel = (int[])pixel; 1753 } else { 1754 intpixel = DataBuffer.toIntArray(pixel); 1755 if (intpixel == null) { 1756 throw new UnsupportedOperationException("This method has not been "+ 1757 "implemented for transferType " + transferType); 1758 } 1762 ("Length of pixel array < number of components in model"); 1763 } 1764 if (components == null) { 1765 components = new int[offset+numComponents]; 1766 } 1767 else if ((components.length-offset) < numComponents) { 1768 throw new IllegalArgumentException 1769 ("Length of components array < number of components in model"); 1770 } 1771 System.arraycopy(intpixel, 0, components, offset, numComponents); 1772 1773 return components; 1774 } 1775 1776 /** 1777 * Returns an array of all of the color/alpha components in unnormalized 1778 * form, given a normalized component array. Unnormalized components 1779 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where 1780 * n is the number of bits for a particular component. Normalized 1781 * components are float values between a per component minimum and 1782 * maximum specified by the {@code ColorSpace} object for this 1783 * {@code ColorModel}. An {@code IllegalArgumentException} 1784 * will be thrown if color component values for this 1785 * {@code ColorModel} are not conveniently representable in the 1786 * unnormalized form. If the 1787 * {@code components} array is {@code null}, a new array 1788 * will be allocated. The {@code components} array will 1789 * be returned. Color/alpha components are stored in the 1790 * {@code components} array starting at {@code offset} (even 1791 * if the array is allocated by this method). An 1792 * {@code ArrayIndexOutOfBoundsException} is thrown if the 1793 * {@code components} array is not {@code null} and is not 1794 * large enough to hold all the color and alpha 1795 * components (starting at {@code offset}). An 1796 * {@code IllegalArgumentException} is thrown if the 1797 * {@code normComponents} array is not large enough to hold 1798 * all the color and alpha components starting at 1799 * {@code normOffset}. 1800 * @param normComponents an array containing normalized components 1801 * @param normOffset the offset into the {@code normComponents} 1802 * array at which to start retrieving normalized components 1803 * @param components an array that receives the components from 1804 * {@code normComponents} 1805 * @param offset the index into {@code components} at which to 1806 * begin storing normalized components from 1807 * {@code normComponents} 1808 * @return an array containing unnormalized color and alpha 1809 * components. 1810 * @throws IllegalArgumentException If this 1811 * {@code ComponentColorModel} does not support the unnormalized form 1812 * @throws IllegalArgumentException if the length of 1813 * {@code normComponents} minus {@code normOffset} 1814 * is less than {@code numComponents} 1815 */ 1816 public int[] getUnnormalizedComponents(float[] normComponents, 1817 int normOffset, 1818 int[] components, int offset) { 1819 if (needScaleInit) { 1820 initScale(); 1821 } 1822 if (noUnnorm) { 1823 throw new 1824 IllegalArgumentException( 1825 "This ColorModel does not support the unnormalized form"); 1826 } 1827 return super.getUnnormalizedComponents(normComponents, normOffset, 1828 components, offset); 1829 } 1830 1831 /** 1832 * Returns an array of all of the color/alpha components in normalized 1833 * form, given an unnormalized component array. Unnormalized components 1834 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where 1835 * n is the number of bits for a particular component. Normalized 1836 * components are float values between a per component minimum and 1837 * maximum specified by the {@code ColorSpace} object for this 1838 * {@code ColorModel}. An {@code IllegalArgumentException} 1839 * will be thrown if color component values for this 1840 * {@code ColorModel} are not conveniently representable in the 1841 * unnormalized form. If the 1842 * {@code normComponents} array is {@code null}, a new array 1843 * will be allocated. The {@code normComponents} array 1844 * will be returned. Color/alpha components are stored in the 1845 * {@code normComponents} array starting at 1846 * {@code normOffset} (even if the array is allocated by this 1847 * method). An {@code ArrayIndexOutOfBoundsException} is thrown 1848 * if the {@code normComponents} array is not {@code null} 1849 * and is not large enough to hold all the color and alpha components 1850 * (starting at {@code normOffset}). An 1851 * {@code IllegalArgumentException} is thrown if the 1852 * {@code components} array is not large enough to hold all the 1853 * color and alpha components starting at {@code offset}. 1854 * @param components an array containing unnormalized components 1855 * @param offset the offset into the {@code components} array at 1856 * which to start retrieving unnormalized components 1857 * @param normComponents an array that receives the normalized components 1858 * @param normOffset the index into {@code normComponents} at 1859 * which to begin storing normalized components 1860 * @return an array containing normalized color and alpha 1861 * components. 1862 * @throws IllegalArgumentException If this 1863 * {@code ComponentColorModel} does not support the unnormalized form 1864 */ 1865 public float[] getNormalizedComponents(int[] components, int offset, 1866 float[] normComponents, 1867 int normOffset) { 1868 if (needScaleInit) { 1869 initScale(); 1870 } 1871 if (noUnnorm) { 1872 throw new 1873 IllegalArgumentException( 1874 "This ColorModel does not support the unnormalized form"); 1875 } 1876 return super.getNormalizedComponents(components, offset, 1877 normComponents, normOffset); 1878 } 1879 1880 /** 1881 * Returns a pixel value represented as an int in this {@code ColorModel}, 1882 * given an array of unnormalized color/alpha components. 1883 * 1884 * @param components An array of unnormalized color/alpha components. 1885 * @param offset An offset into the {@code components} array. 1886 * 1887 * @return A pixel value represented as an int. 1888 * 1889 * @throws IllegalArgumentException If there is more than one component 1890 * in this {@code ColorModel}. 1891 * @throws IllegalArgumentException If this 1892 * {@code ComponentColorModel} does not support the unnormalized form 1893 */ 1894 public int getDataElement(int[] components, int offset) { 1895 if (needScaleInit) { 1896 initScale(); 1897 } 1898 if (numComponents == 1) { 1899 if (noUnnorm) { 1900 throw new 1901 IllegalArgumentException( 1902 "This ColorModel does not support the unnormalized form"); 1903 } 1904 return components[offset+0]; 1905 } 1906 throw new IllegalArgumentException("This model returns "+ 1907 numComponents+ 1908 " elements in the pixel array."); 1909 } 1910 1911 /** 1912 * Returns a data element array representation of a pixel in this 1913 * {@code ColorModel}, given an array of unnormalized color/alpha 1914 * components. This array can then be passed to the {@code setDataElements} 1915 * method of a {@code WritableRaster} object. 1916 * 1917 * @param components An array of unnormalized color/alpha components. 1918 * @param offset The integer offset into the {@code components} array. 1919 * @param obj The object in which to store the data element array 1920 * representation of the pixel. If {@code obj} variable is null, 1921 * a new array is allocated. If {@code obj} is not null, it must 1922 * be a primitive array of type {@code transferType}. An 1923 * {@code ArrayIndexOutOfBoundsException} is thrown if 1924 * {@code obj} is not large enough to hold a pixel value 1925 * for this {@code ColorModel}. Since 1926 * {@code ComponentColorModel} can be subclassed, subclasses 1927 * inherit the implementation of this method and if they don't 1928 * override it then they throw an exception if they use an 1929 * unsupported {@code transferType}. 1930 * 1931 * @return The data element array representation of a pixel 1932 * in this {@code ColorModel}. 1933 * 1934 * @throws IllegalArgumentException If the components array 1935 * is not large enough to hold all the color and alpha components 1936 * (starting at offset). 1937 * @throws ClassCastException If {@code obj} is not null and is not a 1938 * primitive array of type {@code transferType}. 1939 * @throws ArrayIndexOutOfBoundsException If {@code obj} is not large 1940 * enough to hold a pixel value for this {@code ColorModel}. 1941 * @throws IllegalArgumentException If this 1942 * {@code ComponentColorModel} does not support the unnormalized form 1943 * @throws UnsupportedOperationException If the transfer type of 1944 * this {@code ComponentColorModel} 1945 * is not one of the following transfer types: 1946 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 1947 * or {@code DataBuffer.TYPE_INT}. 1948 * 1949 * @see WritableRaster#setDataElements 1950 * @see SampleModel#setDataElements 1951 */ 1952 public Object getDataElements(int[] components, int offset, Object obj) { 1953 if (needScaleInit) { 1954 initScale(); 1955 } 1956 if (noUnnorm) { 1957 throw new 1958 IllegalArgumentException( 1959 "This ColorModel does not support the unnormalized form"); 1960 } 1961 if ((components.length-offset) < numComponents) { 1962 throw new IllegalArgumentException("Component array too small"+ 1963 " (should be "+numComponents); 1964 } 1965 switch(transferType) { 1966 case DataBuffer.TYPE_INT: 1967 { 1998 if (obj == null) { 1999 pixel = new short[numComponents]; 2000 } 2001 else { 2002 pixel = (short[]) obj; 2003 } 2004 for (int i=0; i < numComponents; i++) { 2005 pixel[i] = (short) (components[offset+i]&0xffff); 2006 } 2007 return pixel; 2008 } 2009 2010 default: 2011 throw new UnsupportedOperationException("This method has not been "+ 2012 "implemented for transferType " + 2013 transferType); 2014 } 2015 } 2016 2017 /** 2018 * Returns a pixel value represented as an {@code int} in this 2019 * {@code ColorModel}, given an array of normalized color/alpha 2020 * components. This method will throw an 2021 * {@code IllegalArgumentException} if pixel values for this 2022 * {@code ColorModel} are not conveniently representable as a 2023 * single {@code int}. An 2024 * {@code ArrayIndexOutOfBoundsException} is thrown if the 2025 * {@code normComponents} array is not large enough to hold all the 2026 * color and alpha components (starting at {@code normOffset}). 2027 * @param normComponents an array of normalized color and alpha 2028 * components 2029 * @param normOffset the index into {@code normComponents} at which to 2030 * begin retrieving the color and alpha components 2031 * @return an {@code int} pixel value in this 2032 * {@code ColorModel} corresponding to the specified components. 2033 * @throws IllegalArgumentException if 2034 * pixel values for this {@code ColorModel} are not 2035 * conveniently representable as a single {@code int} 2036 * @throws ArrayIndexOutOfBoundsException if 2037 * the {@code normComponents} array is not large enough to 2038 * hold all of the color and alpha components starting at 2039 * {@code normOffset} 2040 * @since 1.4 2041 */ 2042 public int getDataElement(float[] normComponents, int normOffset) { 2043 if (numComponents > 1) { 2044 throw new 2045 IllegalArgumentException("More than one component per pixel"); 2046 } 2047 if (signed) { 2048 throw new 2049 IllegalArgumentException("Component value is signed"); 2050 } 2051 if (needScaleInit) { 2052 initScale(); 2053 } 2054 Object pixel = getDataElements(normComponents, normOffset, null); 2055 switch (transferType) { 2056 case DataBuffer.TYPE_BYTE: 2057 { 2058 byte bpixel[] = (byte[]) pixel; 2059 return bpixel[0] & 0xff; 2060 } 2061 case DataBuffer.TYPE_USHORT: 2062 { 2063 short[] uspixel = (short[]) pixel; 2064 return uspixel[0] & 0xffff; 2065 } 2066 case DataBuffer.TYPE_INT: 2067 { 2068 int[] ipixel = (int[]) pixel; 2069 return ipixel[0]; 2070 } 2071 default: 2072 throw new UnsupportedOperationException("This method has not been " 2073 + "implemented for transferType " + transferType); 2074 } 2075 } 2076 2077 /** 2078 * Returns a data element array representation of a pixel in this 2079 * {@code ColorModel}, given an array of normalized color/alpha 2080 * components. This array can then be passed to the 2081 * {@code setDataElements} method of a {@code WritableRaster} 2082 * object. An {@code ArrayIndexOutOfBoundsException} is thrown 2083 * if the {@code normComponents} array is not large enough to hold 2084 * all the color and alpha components (starting at 2085 * {@code normOffset}). If the {@code obj} variable is 2086 * {@code null}, a new array will be allocated. If 2087 * {@code obj} is not {@code null}, it must be a primitive 2088 * array of type transferType; otherwise, a 2089 * {@code ClassCastException} is thrown. An 2090 * {@code ArrayIndexOutOfBoundsException} is thrown if 2091 * {@code obj} is not large enough to hold a pixel value for this 2092 * {@code ColorModel}. 2093 * @param normComponents an array of normalized color and alpha 2094 * components 2095 * @param normOffset the index into {@code normComponents} at which to 2096 * begin retrieving color and alpha components 2097 * @param obj a primitive data array to hold the returned pixel 2098 * @return an {@code Object} which is a primitive data array 2099 * representation of a pixel 2100 * @throws ClassCastException if {@code obj} 2101 * is not a primitive array of type {@code transferType} 2102 * @throws ArrayIndexOutOfBoundsException if 2103 * {@code obj} is not large enough to hold a pixel value 2104 * for this {@code ColorModel} or the {@code normComponents} 2105 * array is not large enough to hold all of the color and alpha 2106 * components starting at {@code normOffset} 2107 * @see WritableRaster#setDataElements 2108 * @see SampleModel#setDataElements 2109 * @since 1.4 2110 */ 2111 public Object getDataElements(float[] normComponents, int normOffset, 2112 Object obj) { 2113 boolean needAlpha = supportsAlpha && isAlphaPremultiplied; 2114 float[] stdNormComponents; 2115 if (needScaleInit) { 2116 initScale(); 2117 } 2118 if (nonStdScale) { 2119 stdNormComponents = new float[numComponents]; 2120 for (int c = 0, nc = normOffset; c < numColorComponents; 2121 c++, nc++) { 2122 stdNormComponents[c] = (normComponents[nc] - compOffset[c]) * 2123 compScale[c]; 2124 // REMIND: need to analyze whether this 2125 // clamping is necessary 2126 if (stdNormComponents[c] < 0.0f) { 2281 c++, nc++) { 2282 dpixel[c] = normComponents[nc] * alpha; 2283 } 2284 dpixel[numColorComponents] = alpha; 2285 } else { 2286 for (int c = 0, nc = normOffset; c < numComponents; 2287 c++, nc++) { 2288 dpixel[c] = (double) normComponents[nc]; 2289 } 2290 } 2291 return dpixel; 2292 default: 2293 throw new UnsupportedOperationException("This method has not been "+ 2294 "implemented for transferType " + 2295 transferType); 2296 } 2297 } 2298 2299 /** 2300 * Returns an array of all of the color/alpha components in normalized 2301 * form, given a pixel in this {@code ColorModel}. The pixel 2302 * value is specified by an array of data elements of type transferType 2303 * passed in as an object reference. If pixel is not a primitive array 2304 * of type transferType, a {@code ClassCastException} is thrown. 2305 * An {@code ArrayIndexOutOfBoundsException} is thrown if 2306 * {@code pixel} is not large enough to hold a pixel value for this 2307 * {@code ColorModel}. 2308 * Normalized components are float values between a per component minimum 2309 * and maximum specified by the {@code ColorSpace} object for this 2310 * {@code ColorModel}. If the 2311 * {@code normComponents} array is {@code null}, a new array 2312 * will be allocated. The {@code normComponents} array 2313 * will be returned. Color/alpha components are stored in the 2314 * {@code normComponents} array starting at 2315 * {@code normOffset} (even if the array is allocated by this 2316 * method). An {@code ArrayIndexOutOfBoundsException} is thrown 2317 * if the {@code normComponents} array is not {@code null} 2318 * and is not large enough to hold all the color and alpha components 2319 * (starting at {@code normOffset}). 2320 * <p> 2321 * This method must be overridden by a subclass if that subclass 2322 * is designed to translate pixel sample values to color component values 2323 * in a non-default way. The default translations implemented by this 2324 * class is described in the class comments. Any subclass implementing 2325 * a non-default translation must follow the constraints on allowable 2326 * translations defined there. 2327 * @param pixel the specified pixel 2328 * @param normComponents an array to receive the normalized components 2329 * @param normOffset the offset into the {@code normComponents} 2330 * array at which to start storing normalized components 2331 * @return an array containing normalized color and alpha 2332 * components. 2333 * @throws ClassCastException if {@code pixel} is not a primitive 2334 * array of type transferType 2335 * @throws ArrayIndexOutOfBoundsException if 2336 * {@code normComponents} is not large enough to hold all 2337 * color and alpha components starting at {@code normOffset} 2338 * @throws ArrayIndexOutOfBoundsException if 2339 * {@code pixel} is not large enough to hold a pixel 2340 * value for this {@code ColorModel}. 2341 * @since 1.4 2342 */ 2343 public float[] getNormalizedComponents(Object pixel, 2344 float[] normComponents, 2345 int normOffset) { 2346 if (normComponents == null) { 2347 normComponents = new float[numComponents+normOffset]; 2348 } 2349 switch (transferType) { 2350 case DataBuffer.TYPE_BYTE: 2351 byte[] bpixel = (byte[]) pixel; 2352 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { 2353 normComponents[nc] = ((float) (bpixel[c] & 0xff)) / 2354 ((float) ((1 << nBits[c]) - 1)); 2355 } 2356 break; 2357 case DataBuffer.TYPE_USHORT: 2358 short[] uspixel = (short[]) pixel; 2359 for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { 2360 normComponents[nc] = ((float) (uspixel[c] & 0xffff)) / 2409 // possible case, in which this method is overridden, nonStdScale 2410 // is set true by initScale(), the subclass method for some 2411 // reason calls this superclass method, but the min and 2412 // diffMinMax arrays were never initialized by setupLUTs(). In 2413 // that case, the right thing to do is follow the intended 2414 // semantics of this method, and rescale the color components 2415 // only if the ColorSpace min/max were detected to be other 2416 // than 0.0/1.0 by setupLUTs(). Note that this implies the 2417 // transferType is byte, ushort, int, or short - i.e. components 2418 // derived from float and double pixel data are never rescaled. 2419 for (int c = 0; c < numColorComponents; c++) { 2420 normComponents[c + normOffset] = min[c] + 2421 diffMinMax[c] * normComponents[c + normOffset]; 2422 } 2423 } 2424 return normComponents; 2425 } 2426 2427 /** 2428 * Forces the raster data to match the state specified in the 2429 * {@code isAlphaPremultiplied} variable, assuming the data 2430 * is currently correctly described by this {@code ColorModel}. 2431 * It may multiply or divide the color raster data by alpha, or 2432 * do nothing if the data is in the correct state. If the data needs 2433 * to be coerced, this method also returns an instance of 2434 * this {@code ColorModel} with 2435 * the {@code isAlphaPremultiplied} flag set appropriately. 2436 * Since {@code ColorModel} can be subclassed, subclasses inherit 2437 * the implementation of this method and if they don't override it 2438 * then they throw an exception if they use an unsupported 2439 * {@code transferType}. 2440 * 2441 * @throws NullPointerException if {@code raster} is 2442 * {@code null} and data coercion is required. 2443 * @throws UnsupportedOperationException if the transfer type of 2444 * this {@code ComponentColorModel} 2445 * is not one of the supported transfer types: 2446 * {@code DataBuffer.TYPE_BYTE}, {@code DataBuffer.TYPE_USHORT}, 2447 * {@code DataBuffer.TYPE_INT}, {@code DataBuffer.TYPE_SHORT}, 2448 * {@code DataBuffer.TYPE_FLOAT}, or {@code DataBuffer.TYPE_DOUBLE}. 2449 */ 2450 public ColorModel coerceData (WritableRaster raster, 2451 boolean isAlphaPremultiplied) { 2452 if ((supportsAlpha == false) || 2453 (this.isAlphaPremultiplied == isAlphaPremultiplied)) 2454 { 2455 // Nothing to do 2456 return this; 2457 } 2458 2459 int w = raster.getWidth(); 2460 int h = raster.getHeight(); 2461 int aIdx = raster.getNumBands() - 1; 2462 float normAlpha; 2463 int rminX = raster.getMinX(); 2464 int rY = raster.getMinY(); 2465 int rX; 2466 if (isAlphaPremultiplied) { 2467 switch (transferType) { 2468 case DataBuffer.TYPE_BYTE: { 2757 default: 2758 throw new UnsupportedOperationException("This method has not been "+ 2759 "implemented for transferType " + transferType); 2760 } 2761 } 2762 2763 // Return a new color model 2764 if (!signed) { 2765 return new ComponentColorModel(colorSpace, nBits, supportsAlpha, 2766 isAlphaPremultiplied, transparency, 2767 transferType); 2768 } else { 2769 return new ComponentColorModel(colorSpace, supportsAlpha, 2770 isAlphaPremultiplied, transparency, 2771 transferType); 2772 } 2773 2774 } 2775 2776 /** 2777 * Returns true if {@code raster} is compatible with this 2778 * {@code ColorModel}; false if it is not. 2779 * 2780 * @param raster The {@code Raster} object to test for compatibility. 2781 * 2782 * @return {@code true} if {@code raster} is compatible with this 2783 * {@code ColorModel}, {@code false} if it is not. 2784 */ 2785 public boolean isCompatibleRaster(Raster raster) { 2786 2787 SampleModel sm = raster.getSampleModel(); 2788 2789 if (sm instanceof ComponentSampleModel) { 2790 if (sm.getNumBands() != getNumComponents()) { 2791 return false; 2792 } 2793 for (int i=0; i<nBits.length; i++) { 2794 if (sm.getSampleSize(i) < nBits[i]) { 2795 return false; 2796 } 2797 } 2798 return (raster.getTransferType() == transferType); 2799 } 2800 else { 2801 return false; 2802 } 2803 } 2804 2805 /** 2806 * Creates a {@code WritableRaster} with the specified width and height, 2807 * that has a data layout ({@code SampleModel}) compatible with 2808 * this {@code ColorModel}. 2809 * 2810 * @param w The width of the {@code WritableRaster} you want to create. 2811 * @param h The height of the {@code WritableRaster} you want to create. 2812 * 2813 * @return A {@code WritableRaster} that is compatible with 2814 * this {@code ColorModel}. 2815 * @see WritableRaster 2816 * @see SampleModel 2817 */ 2818 public WritableRaster createCompatibleWritableRaster (int w, int h) { 2819 int dataSize = w*h*numComponents; 2820 WritableRaster raster = null; 2821 2822 switch (transferType) { 2823 case DataBuffer.TYPE_BYTE: 2824 case DataBuffer.TYPE_USHORT: 2825 raster = Raster.createInterleavedRaster(transferType, 2826 w, h, 2827 numComponents, null); 2828 break; 2829 default: 2830 SampleModel sm = createCompatibleSampleModel(w, h); 2831 DataBuffer db = sm.createDataBuffer(); 2832 raster = Raster.createWritableRaster(sm, db, null); 2833 } 2834 2835 return raster; 2836 } 2837 2838 /** 2839 * Creates a {@code SampleModel} with the specified width and height, 2840 * that has a data layout compatible with this {@code ColorModel}. 2841 * 2842 * @param w The width of the {@code SampleModel} you want to create. 2843 * @param h The height of the {@code SampleModel} you want to create. 2844 * 2845 * @return A {@code SampleModel} that is compatible with this 2846 * {@code ColorModel}. 2847 * 2848 * @see SampleModel 2849 */ 2850 public SampleModel createCompatibleSampleModel(int w, int h) { 2851 int[] bandOffsets = new int[numComponents]; 2852 for (int i=0; i < numComponents; i++) { 2853 bandOffsets[i] = i; 2854 } 2855 switch (transferType) { 2856 case DataBuffer.TYPE_BYTE: 2857 case DataBuffer.TYPE_USHORT: 2858 return new PixelInterleavedSampleModel(transferType, w, h, 2859 numComponents, 2860 w*numComponents, 2861 bandOffsets); 2862 default: 2863 return new ComponentSampleModel(transferType, w, h, 2864 numComponents, 2865 w*numComponents, 2866 bandOffsets); 2867 } 2868 } 2869 2870 /** 2871 * Checks whether or not the specified {@code SampleModel} 2872 * is compatible with this {@code ColorModel}. 2873 * 2874 * @param sm The {@code SampleModel} to test for compatibility. 2875 * 2876 * @return {@code true} if the {@code SampleModel} is 2877 * compatible with this {@code ColorModel}, {@code false} 2878 * if it is not. 2879 * 2880 * @see SampleModel 2881 */ 2882 public boolean isCompatibleSampleModel(SampleModel sm) { 2883 if (!(sm instanceof ComponentSampleModel)) { 2884 return false; 2885 } 2886 2887 // Must have the same number of components 2888 if (numComponents != sm.getNumBands()) { 2889 return false; 2890 } 2891 2892 if (sm.getTransferType() != transferType) { 2893 return false; 2894 } 2895 2896 return true; 2897 } 2898 2899 /** 2900 * Returns a {@code Raster} representing the alpha channel of an image, 2901 * extracted from the input {@code Raster}. 2902 * This method assumes that {@code Raster} objects associated with 2903 * this {@code ColorModel} store the alpha band, if present, as 2904 * the last band of image data. Returns null if there is no separate spatial 2905 * alpha channel associated with this {@code ColorModel}. 2906 * This method creates a new {@code Raster}, but will share the data 2907 * array. 2908 * 2909 * @param raster The {@code WritableRaster} from which to extract the 2910 * alpha channel. 2911 * 2912 * @return A {@code WritableRaster} containing the image's alpha channel. 2913 * 2914 */ 2915 public WritableRaster getAlphaRaster(WritableRaster raster) { 2916 if (hasAlpha() == false) { 2917 return null; 2918 } 2919 2920 int x = raster.getMinX(); 2921 int y = raster.getMinY(); 2922 int[] band = new int[1]; 2923 band[0] = raster.getNumBands() - 1; 2924 return raster.createWritableChild(x, y, raster.getWidth(), 2925 raster.getHeight(), x, y, 2926 band); 2927 } 2928 2929 /** 2930 * Compares this color model with another for equality. 2931 * 2932 * @param obj The object to compare with this color model. 2933 * @return {@code true} if the color model objects are equal, 2934 * {@code false} if they are not. 2935 */ 2936 public boolean equals(Object obj) { 2937 if (!super.equals(obj)) { 2938 return false; 2939 } 2940 2941 if (obj.getClass() != getClass()) { 2942 return false; 2943 } 2944 2945 return true; 2946 } 2947 2948 } |