blob: 59bb389bd6e3040cbd97c3126be4f7e5dffeab3d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.awt.image;
27
28import java.awt.Transparency;
29import java.awt.color.ColorSpace;
30import java.awt.color.ICC_ColorSpace;
31import sun.java2d.cmm.CMSManager;
32import sun.java2d.cmm.ColorTransform;
33import sun.java2d.cmm.PCMM;
34import java.awt.Toolkit;
35import java.util.Collections;
36import java.util.Map;
37import java.util.WeakHashMap;
38
39/**
40 * The <code>ColorModel</code> abstract class encapsulates the
41 * methods for translating a pixel value to color components
42 * (for example, red, green, and blue) and an alpha component.
43 * In order to render an image to the screen, a printer, or another
44 * image, pixel values must be converted to color and alpha components.
45 * As arguments to or return values from methods of this class,
46 * pixels are represented as 32-bit ints or as arrays of primitive types.
47 * The number, order, and interpretation of color components for a
48 * <code>ColorModel</code> is specified by its <code>ColorSpace</code>.
49 * A <code>ColorModel</code> used with pixel data that does not include
50 * alpha information treats all pixels as opaque, which is an alpha
51 * value of 1.0.
52 * <p>
53 * This <code>ColorModel</code> class supports two representations of
54 * pixel values. A pixel value can be a single 32-bit int or an
55 * array of primitive types. The Java(tm) Platform 1.0 and 1.1 APIs
56 * represented pixels as single <code>byte</code> or single
57 * <code>int</code> values. For purposes of the <code>ColorModel</code>
58 * class, pixel value arguments were passed as ints. The Java(tm) 2
59 * Platform API introduced additional classes for representing images.
60 * With {@link BufferedImage} or {@link RenderedImage}
61 * objects, based on {@link Raster} and {@link SampleModel} classes, pixel
62 * values might not be conveniently representable as a single int.
63 * Consequently, <code>ColorModel</code> now has methods that accept
64 * pixel values represented as arrays of primitive types. The primitive
65 * type used by a particular <code>ColorModel</code> object is called its
66 * transfer type.
67 * <p>
68 * <code>ColorModel</code> objects used with images for which pixel values
69 * are not conveniently representable as a single int throw an
70 * {@link IllegalArgumentException} when methods taking a single int pixel
71 * argument are called. Subclasses of <code>ColorModel</code> must
72 * specify the conditions under which this occurs. This does not
73 * occur with {@link DirectColorModel} or {@link IndexColorModel} objects.
74 * <p>
75 * Currently, the transfer types supported by the Java 2D(tm) API are
76 * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT,
77 * DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, and DataBuffer.TYPE_DOUBLE.
78 * Most rendering operations will perform much faster when using ColorModels
79 * and images based on the first three of these types. In addition, some
80 * image filtering operations are not supported for ColorModels and
81 * images based on the latter three types.
82 * The transfer type for a particular <code>ColorModel</code> object is
83 * specified when the object is created, either explicitly or by default.
84 * All subclasses of <code>ColorModel</code> must specify what the
85 * possible transfer types are and how the number of elements in the
86 * primitive arrays representing pixels is determined.
87 * <p>
88 * For <code>BufferedImages</code>, the transfer type of its
89 * <code>Raster</code> and of the <code>Raster</code> object's
90 * <code>SampleModel</code> (available from the
91 * <code>getTransferType</code> methods of these classes) must match that
92 * of the <code>ColorModel</code>. The number of elements in an array
93 * representing a pixel for the <code>Raster</code> and
94 * <code>SampleModel</code> (available from the
95 * <code>getNumDataElements</code> methods of these classes) must match
96 * that of the <code>ColorModel</code>.
97 * <p>
98 * The algorithm used to convert from pixel values to color and alpha
99 * components varies by subclass. For example, there is not necessarily
100 * a one-to-one correspondence between samples obtained from the
101 * <code>SampleModel</code> of a <code>BufferedImage</code> object's
102 * <code>Raster</code> and color/alpha components. Even when
103 * there is such a correspondence, the number of bits in a sample is not
104 * necessarily the same as the number of bits in the corresponding color/alpha
105 * component. Each subclass must specify how the translation from
106 * pixel values to color/alpha components is done.
107 * <p>
108 * Methods in the <code>ColorModel</code> class use two different
109 * representations of color and alpha components - a normalized form
110 * and an unnormalized form. In the normalized form, each component is a
111 * <code>float</code> value between some minimum and maximum values. For
112 * the alpha component, the minimum is 0.0 and the maximum is 1.0. For
113 * color components the minimum and maximum values for each component can
114 * be obtained from the <code>ColorSpace</code> object. These values
115 * will often be 0.0 and 1.0 (e.g. normalized component values for the
116 * default sRGB color space range from 0.0 to 1.0), but some color spaces
117 * have component values with different upper and lower limits. These
118 * limits can be obtained using the <code>getMinValue</code> and
119 * <code>getMaxValue</code> methods of the <code>ColorSpace</code>
120 * class. Normalized color component values are not premultiplied.
121 * All <code>ColorModels</code> must support the normalized form.
122 * <p>
123 * In the unnormalized
124 * form, each component is an unsigned integral value between 0 and
125 * 2<sup>n</sup> - 1, where n is the number of significant bits for a
126 * particular component. If pixel values for a particular
127 * <code>ColorModel</code> represent color samples premultiplied by
128 * the alpha sample, unnormalized color component values are
129 * also premultiplied. The unnormalized form is used only with instances
130 * of <code>ColorModel</code> whose <code>ColorSpace</code> has minimum
131 * component values of 0.0 for all components and maximum values of
132 * 1.0 for all components.
133 * The unnormalized form for color and alpha components can be a convenient
134 * representation for <code>ColorModels</code> whose normalized component
135 * values all lie
136 * between 0.0 and 1.0. In such cases the integral value 0 maps to 0.0 and
137 * the value 2<sup>n</sup> - 1 maps to 1.0. In other cases, such as
138 * when the normalized component values can be either negative or positive,
139 * the unnormalized form is not convenient. Such <code>ColorModel</code>
140 * objects throw an {@link IllegalArgumentException} when methods involving
141 * an unnormalized argument are called. Subclasses of <code>ColorModel</code>
142 * must specify the conditions under which this occurs.
143 *
144 * @see IndexColorModel
145 * @see ComponentColorModel
146 * @see PackedColorModel
147 * @see DirectColorModel
148 * @see java.awt.Image
149 * @see BufferedImage
150 * @see RenderedImage
151 * @see java.awt.color.ColorSpace
152 * @see SampleModel
153 * @see Raster
154 * @see DataBuffer
155 */
156public abstract class ColorModel implements Transparency{
157 private long pData; // Placeholder for data for native functions
158
159 /**
160 * The total number of bits in the pixel.
161 */
162 protected int pixel_bits;
163 int nBits[];
164 int transparency = Transparency.TRANSLUCENT;
165 boolean supportsAlpha = true;
166 boolean isAlphaPremultiplied = false;
167 int numComponents = -1;
168 int numColorComponents = -1;
169 ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
170 int colorSpaceType = ColorSpace.TYPE_RGB;
171 int maxBits;
172 boolean is_sRGB = true;
173
174 /**
175 * Data type of the array used to represent pixel values.
176 */
177 protected int transferType;
178
179 /**
180 * This is copied from java.awt.Toolkit since we need the library
181 * loaded in java.awt.image also:
182 *
183 * WARNING: This is a temporary workaround for a problem in the
184 * way the AWT loads native libraries. A number of classes in the
185 * AWT package have a native method, initIDs(), which initializes
186 * the JNI field and method ids used in the native portion of
187 * their implementation.
188 *
189 * Since the use and storage of these ids is done by the
190 * implementation libraries, the implementation of these method is
191 * provided by the particular AWT implementations (for example,
192 * "Toolkit"s/Peer), such as Motif, Microsoft Windows, or Tiny. The
193 * problem is that this means that the native libraries must be
194 * loaded by the java.* classes, which do not necessarily know the
195 * names of the libraries to load. A better way of doing this
196 * would be to provide a separate library which defines java.awt.*
197 * initIDs, and exports the relevant symbols out to the
198 * implementation libraries.
199 *
200 * For now, we know it's done by the implementation, and we assume
201 * that the name of the library is "awt". -br.
202 */
203 private static boolean loaded = false;
204 static void loadLibraries() {
205 if (!loaded) {
206 java.security.AccessController.doPrivileged(
207 new sun.security.action.LoadLibraryAction("awt"));
208 loaded = true;
209 }
210 }
211 private static native void initIDs();
212 static {
213 /* ensure that the proper libraries are loaded */
214 loadLibraries();
215 initIDs();
216 }
217 private static ColorModel RGBdefault;
218
219 /**
220 * Returns a <code>DirectColorModel</code> that describes the default
221 * format for integer RGB values used in many of the methods in the
222 * AWT image interfaces for the convenience of the programmer.
223 * The color space is the default {@link ColorSpace}, sRGB.
224 * The format for the RGB values is an integer with 8 bits
225 * each of alpha, red, green, and blue color components ordered
226 * correspondingly from the most significant byte to the least
227 * significant byte, as in: 0xAARRGGBB. Color components are
228 * not premultiplied by the alpha component. This format does not
229 * necessarily represent the native or the most efficient
230 * <code>ColorModel</code> for a particular device or for all images.
231 * It is merely used as a common color model format.
232 * @return a <code>DirectColorModel</code>object describing default
233 * RGB values.
234 */
235 public static ColorModel getRGBdefault() {
236 if (RGBdefault == null) {
237 RGBdefault = new DirectColorModel(32,
238 0x00ff0000, // Red
239 0x0000ff00, // Green
240 0x000000ff, // Blue
241 0xff000000 // Alpha
242 );
243 }
244 return RGBdefault;
245 }
246
247 /**
248 * Constructs a <code>ColorModel</code> that translates pixels of the
249 * specified number of bits to color/alpha components. The color
250 * space is the default RGB <code>ColorSpace</code>, which is sRGB.
251 * Pixel values are assumed to include alpha information. If color
252 * and alpha information are represented in the pixel value as
253 * separate spatial bands, the color bands are assumed not to be
254 * premultiplied with the alpha value. The transparency type is
255 * java.awt.Transparency.TRANSLUCENT. The transfer type will be the
256 * smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
257 * or DataBuffer.TYPE_INT that can hold a single pixel
258 * (or DataBuffer.TYPE_UNDEFINED if bits is greater
259 * than 32). Since this constructor has no information about the
260 * number of bits per color and alpha component, any subclass calling
261 * this constructor should override any method that requires this
262 * information.
263 * @param bits the number of bits of a pixel
264 * @throws IllegalArgumentException if the number
265 * of bits in <code>bits</code> is less than 1
266 */
267 public ColorModel(int bits) {
268 pixel_bits = bits;
269 if (bits < 1) {
270 throw new IllegalArgumentException("Number of bits must be > 0");
271 }
272 numComponents = 4;
273 numColorComponents = 3;
274 maxBits = bits;
275 // REMIND: make sure transferType is set correctly
276 transferType = ColorModel.getDefaultTransferType(bits);
277 }
278
279 /**
280 * Constructs a <code>ColorModel</code> that translates pixel values
281 * to color/alpha components. Color components will be in the
282 * specified <code>ColorSpace</code>. <code>pixel_bits</code> is the
283 * number of bits in the pixel values. The bits array
284 * specifies the number of significant bits per color and alpha component.
285 * Its length should be the number of components in the
286 * <code>ColorSpace</code> if there is no alpha information in the
287 * pixel values, or one more than this number if there is alpha
288 * information. <code>hasAlpha</code> indicates whether or not alpha
289 * information is present. The <code>boolean</code>
290 * <code>isAlphaPremultiplied</code> specifies how to interpret pixel
291 * values in which color and alpha information are represented as
292 * separate spatial bands. If the <code>boolean</code>
293 * is <code>true</code>, color samples are assumed to have been
294 * multiplied by the alpha sample. The <code>transparency</code>
295 * specifies what alpha values can be represented by this color model.
296 * The transfer type is the type of primitive array used to represent
297 * pixel values. Note that the bits array contains the number of
298 * significant bits per color/alpha component after the translation
299 * from pixel values. For example, for an
300 * <code>IndexColorModel</code> with <code>pixel_bits</code> equal to
301 * 16, the bits array might have four elements with each element set
302 * to 8.
303 * @param pixel_bits the number of bits in the pixel values
304 * @param bits array that specifies the number of significant bits
305 * per color and alpha component
306 * @param cspace the specified <code>ColorSpace</code>
307 * @param hasAlpha <code>true</code> if alpha information is present;
308 * <code>false</code> otherwise
309 * @param isAlphaPremultiplied <code>true</code> if color samples are
310 * assumed to be premultiplied by the alpha samples;
311 * <code>false</code> otherwise
312 * @param transparency what alpha values can be represented by this
313 * color model
314 * @param transferType the type of the array used to represent pixel
315 * values
316 * @throws IllegalArgumentException if the length of
317 * the bit array is less than the number of color or alpha
318 * components in this <code>ColorModel</code>, or if the
319 * transparency is not a valid value.
320 * @throws IllegalArgumentException if the sum of the number
321 * of bits in <code>bits</code> is less than 1 or if
322 * any of the elements in <code>bits</code> is less than 0.
323 * @see java.awt.Transparency
324 */
325 protected ColorModel(int pixel_bits, int[] bits, ColorSpace cspace,
326 boolean hasAlpha,
327 boolean isAlphaPremultiplied,
328 int transparency,
329 int transferType) {
330 colorSpace = cspace;
331 colorSpaceType = cspace.getType();
332 numColorComponents = cspace.getNumComponents();
333 numComponents = numColorComponents + (hasAlpha ? 1 : 0);
334 supportsAlpha = hasAlpha;
335 if (bits.length < numComponents) {
336 throw new IllegalArgumentException("Number of color/alpha "+
337 "components should be "+
338 numComponents+
339 " but length of bits array is "+
340 bits.length);
341 }
342
343 // 4186669
344 if (transparency < Transparency.OPAQUE ||
345 transparency > Transparency.TRANSLUCENT)
346 {
347 throw new IllegalArgumentException("Unknown transparency: "+
348 transparency);
349 }
350
351 if (supportsAlpha == false) {
352 this.isAlphaPremultiplied = false;
353 this.transparency = Transparency.OPAQUE;
354 }
355 else {
356 this.isAlphaPremultiplied = isAlphaPremultiplied;
357 this.transparency = transparency;
358 }
359
360 nBits = (int[]) bits.clone();
361 this.pixel_bits = pixel_bits;
362 if (pixel_bits <= 0) {
363 throw new IllegalArgumentException("Number of pixel bits must "+
364 "be > 0");
365 }
366 // Check for bits < 0
367 maxBits = 0;
368 for (int i=0; i < bits.length; i++) {
369 // bug 4304697
370 if (bits[i] < 0) {
371 throw new
372 IllegalArgumentException("Number of bits must be >= 0");
373 }
374 if (maxBits < bits[i]) {
375 maxBits = bits[i];
376 }
377 }
378
379 // Make sure that we don't have all 0-bit components
380 if (maxBits == 0) {
381 throw new IllegalArgumentException("There must be at least "+
382 "one component with > 0 "+
383 "pixel bits.");
384 }
385
386 // Save this since we always need to check if it is the default CS
387 if (cspace != ColorSpace.getInstance(ColorSpace.CS_sRGB)) {
388 is_sRGB = false;
389 }
390
391 // Save the transfer type
392 this.transferType = transferType;
393 }
394
395 /**
396 * Returns whether or not alpha is supported in this
397 * <code>ColorModel</code>.
398 * @return <code>true</code> if alpha is supported in this
399 * <code>ColorModel</code>; <code>false</code> otherwise.
400 */
401 final public boolean hasAlpha() {
402 return supportsAlpha;
403 }
404
405 /**
406 * Returns whether or not the alpha has been premultiplied in the
407 * pixel values to be translated by this <code>ColorModel</code>.
408 * If the boolean is <code>true</code>, this <code>ColorModel</code>
409 * is to be used to interpret pixel values in which color and alpha
410 * information are represented as separate spatial bands, and color
411 * samples are assumed to have been multiplied by the
412 * alpha sample.
413 * @return <code>true</code> if the alpha values are premultiplied
414 * in the pixel values to be translated by this
415 * <code>ColorModel</code>; <code>false</code> otherwise.
416 */
417 final public boolean isAlphaPremultiplied() {
418 return isAlphaPremultiplied;
419 }
420
421 /**
422 * Returns the transfer type of this <code>ColorModel</code>.
423 * The transfer type is the type of primitive array used to represent
424 * pixel values as arrays.
425 * @return the transfer type.
426 * @since 1.3
427 */
428 final public int getTransferType() {
429 return transferType;
430 }
431
432 /**
433 * Returns the number of bits per pixel described by this
434 * <code>ColorModel</code>.
435 * @return the number of bits per pixel.
436 */
437 public int getPixelSize() {
438 return pixel_bits;
439 }
440
441 /**
442 * Returns the number of bits for the specified color/alpha component.
443 * Color components are indexed in the order specified by the
444 * <code>ColorSpace</code>. Typically, this order reflects the name
445 * of the color space type. For example, for TYPE_RGB, index 0
446 * corresponds to red, index 1 to green, and index 2
447 * to blue. If this <code>ColorModel</code> supports alpha, the alpha
448 * component corresponds to the index following the last color
449 * component.
450 * @param componentIdx the index of the color/alpha component
451 * @return the number of bits for the color/alpha component at the
452 * specified index.
453 * @throws ArrayIndexOutOfBoundsException if <code>componentIdx</code>
454 * is greater than the number of components or
455 * less than zero
456 * @throws NullPointerException if the number of bits array is
457 * <code>null</code>
458 */
459 public int getComponentSize(int componentIdx) {
460 // REMIND:
461 if (nBits == null) {
462 throw new NullPointerException("Number of bits array is null.");
463 }
464
465 return nBits[componentIdx];
466 }
467
468 /**
469 * Returns an array of the number of bits per color/alpha component.
470 * The array contains the color components in the order specified by the
471 * <code>ColorSpace</code>, followed by the alpha component, if
472 * present.
473 * @return an array of the number of bits per color/alpha component
474 */
475 public int[] getComponentSize() {
476 if (nBits != null) {
477 return (int[]) nBits.clone();
478 }
479
480 return null;
481 }
482
483 /**
484 * Returns the transparency. Returns either OPAQUE, BITMASK,
485 * or TRANSLUCENT.
486 * @return the transparency of this <code>ColorModel</code>.
487 * @see Transparency#OPAQUE
488 * @see Transparency#BITMASK
489 * @see Transparency#TRANSLUCENT
490 */
491 public int getTransparency() {
492 return transparency;
493 }
494
495 /**
496 * Returns the number of components, including alpha, in this
497 * <code>ColorModel</code>. This is equal to the number of color
498 * components, optionally plus one, if there is an alpha component.
499 * @return the number of components in this <code>ColorModel</code>
500 */
501 public int getNumComponents() {
502 return numComponents;
503 }
504
505 /**
506 * Returns the number of color components in this
507 * <code>ColorModel</code>.
508 * This is the number of components returned by
509 * {@link ColorSpace#getNumComponents}.
510 * @return the number of color components in this
511 * <code>ColorModel</code>.
512 * @see ColorSpace#getNumComponents
513 */
514 public int getNumColorComponents() {
515 return numColorComponents;
516 }
517
518 /**
519 * Returns the red color component for the specified pixel, scaled
520 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
521 * is done if necessary. The pixel value is specified as an int.
522 * An <code>IllegalArgumentException</code> is thrown if pixel
523 * values for this <code>ColorModel</code> are not conveniently
524 * representable as a single int. The returned value is not a
525 * pre-multiplied value. For example, if the
526 * alpha is premultiplied, this method divides it out before returning
527 * the value. If the alpha value is 0, the red value is 0.
528 * @param pixel a specified pixel
529 * @return the value of the red component of the specified pixel.
530 */
531 public abstract int getRed(int pixel);
532
533 /**
534 * Returns the green color component for the specified pixel, scaled
535 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
536 * is done if necessary. The pixel value is specified as an int.
537 * An <code>IllegalArgumentException</code> is thrown if pixel
538 * values for this <code>ColorModel</code> are not conveniently
539 * representable as a single int. The returned value is a non
540 * pre-multiplied value. For example, if the alpha is premultiplied,
541 * this method divides it out before returning
542 * the value. If the alpha value is 0, the green value is 0.
543 * @param pixel the specified pixel
544 * @return the value of the green component of the specified pixel.
545 */
546 public abstract int getGreen(int pixel);
547
548 /**
549 * Returns the blue color component for the specified pixel, scaled
550 * from 0 to 255 in the default RGB ColorSpace, sRGB. A color conversion
551 * is done if necessary. The pixel value is specified as an int.
552 * An <code>IllegalArgumentException</code> is thrown if pixel values
553 * for this <code>ColorModel</code> are not conveniently representable
554 * as a single int. The returned value is a non pre-multiplied
555 * value, for example, if the alpha is premultiplied, this method
556 * divides it out before returning the value. If the alpha value is
557 * 0, the blue value is 0.
558 * @param pixel the specified pixel
559 * @return the value of the blue component of the specified pixel.
560 */
561 public abstract int getBlue(int pixel);
562
563 /**
564 * Returns the alpha component for the specified pixel, scaled
565 * from 0 to 255. The pixel value is specified as an int.
566 * An <code>IllegalArgumentException</code> is thrown if pixel
567 * values for this <code>ColorModel</code> are not conveniently
568 * representable as a single int.
569 * @param pixel the specified pixel
570 * @return the value of alpha component of the specified pixel.
571 */
572 public abstract int getAlpha(int pixel);
573
574 /**
575 * Returns the color/alpha components of the pixel in the default
576 * RGB color model format. A color conversion is done if necessary.
577 * The pixel value is specified as an int.
578 * An <code>IllegalArgumentException</code> thrown if pixel values
579 * for this <code>ColorModel</code> are not conveniently representable
580 * as a single int. The returned value is in a non
581 * pre-multiplied format. For example, if the alpha is premultiplied,
582 * this method divides it out of the color components. If the alpha
583 * value is 0, the color values are 0.
584 * @param pixel the specified pixel
585 * @return the RGB value of the color/alpha components of the
586 * specified pixel.
587 * @see ColorModel#getRGBdefault
588 */
589 public int getRGB(int pixel) {
590 return (getAlpha(pixel) << 24)
591 | (getRed(pixel) << 16)
592 | (getGreen(pixel) << 8)
593 | (getBlue(pixel) << 0);
594 }
595
596 /**
597 * Returns the red color component for the specified pixel, scaled
598 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
599 * color conversion is done if necessary. The pixel value is
600 * specified by an array of data elements of type transferType passed
601 * in as an object reference. The returned value is a non
602 * pre-multiplied value. For example, if alpha is premultiplied,
603 * this method divides it out before returning
604 * the value. If the alpha value is 0, the red value is 0.
605 * If <code>inData</code> is not a primitive array of type
606 * transferType, a <code>ClassCastException</code> is thrown. An
607 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
608 * <code>inData</code> is not large enough to hold a pixel value for
609 * this <code>ColorModel</code>.
610 * If this <code>transferType</code> is not supported, a
611 * <code>UnsupportedOperationException</code> will be
612 * thrown. Since
613 * <code>ColorModel</code> is an abstract class, any instance
614 * must be an instance of a subclass. Subclasses inherit the
615 * implementation of this method and if they don't override it, this
616 * method throws an exception if the subclass uses a
617 * <code>transferType</code> other than
618 * <code>DataBuffer.TYPE_BYTE</code>,
619 * <code>DataBuffer.TYPE_USHORT</code>, or
620 * <code>DataBuffer.TYPE_INT</code>.
621 * @param inData an array of pixel values
622 * @return the value of the red component of the specified pixel.
623 * @throws ClassCastException if <code>inData</code>
624 * is not a primitive array of type <code>transferType</code>
625 * @throws ArrayIndexOutOfBoundsException if
626 * <code>inData</code> is not large enough to hold a pixel value
627 * for this <code>ColorModel</code>
628 * @throws UnsupportedOperationException if this
629 * <code>tranferType</code> is not supported by this
630 * <code>ColorModel</code>
631 */
632 public int getRed(Object inData) {
633 int pixel=0,length=0;
634 switch (transferType) {
635 case DataBuffer.TYPE_BYTE:
636 byte bdata[] = (byte[])inData;
637 pixel = bdata[0] & 0xff;
638 length = bdata.length;
639 break;
640 case DataBuffer.TYPE_USHORT:
641 short sdata[] = (short[])inData;
642 pixel = sdata[0] & 0xffff;
643 length = sdata.length;
644 break;
645 case DataBuffer.TYPE_INT:
646 int idata[] = (int[])inData;
647 pixel = idata[0];
648 length = idata.length;
649 break;
650 default:
651 throw new UnsupportedOperationException("This method has not been "+
652 "implemented for transferType " + transferType);
653 }
654 if (length == 1) {
655 return getRed(pixel);
656 }
657 else {
658 throw new UnsupportedOperationException
659 ("This method is not supported by this color model");
660 }
661 }
662
663 /**
664 * Returns the green color component for the specified pixel, scaled
665 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
666 * color conversion is done if necessary. The pixel value is
667 * specified by an array of data elements of type transferType passed
668 * in as an object reference. The returned value will be a non
669 * pre-multiplied value. For example, if the alpha is premultiplied,
670 * this method divides it out before returning the value. If the
671 * alpha value is 0, the green value is 0. If <code>inData</code> is
672 * not a primitive array of type transferType, a
673 * <code>ClassCastException</code> is thrown. An
674 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
675 * <code>inData</code> is not large enough to hold a pixel value for
676 * this <code>ColorModel</code>.
677 * If this <code>transferType</code> is not supported, a
678 * <code>UnsupportedOperationException</code> will be
679 * thrown. Since
680 * <code>ColorModel</code> is an abstract class, any instance
681 * must be an instance of a subclass. Subclasses inherit the
682 * implementation of this method and if they don't override it, this
683 * method throws an exception if the subclass uses a
684 * <code>transferType</code> other than
685 * <code>DataBuffer.TYPE_BYTE</code>,
686 * <code>DataBuffer.TYPE_USHORT</code>, or
687 * <code>DataBuffer.TYPE_INT</code>.
688 * @param inData an array of pixel values
689 * @return the value of the green component of the specified pixel.
690 * @throws <code>ClassCastException</code> if <code>inData</code>
691 * is not a primitive array of type <code>transferType</code>
692 * @throws <code>ArrayIndexOutOfBoundsException</code> if
693 * <code>inData</code> is not large enough to hold a pixel value
694 * for this <code>ColorModel</code>
695 * @throws <code>UnsupportedOperationException</code> if this
696 * <code>tranferType</code> is not supported by this
697 * <code>ColorModel</code>
698 */
699 public int getGreen(Object inData) {
700 int pixel=0,length=0;
701 switch (transferType) {
702 case DataBuffer.TYPE_BYTE:
703 byte bdata[] = (byte[])inData;
704 pixel = bdata[0] & 0xff;
705 length = bdata.length;
706 break;
707 case DataBuffer.TYPE_USHORT:
708 short sdata[] = (short[])inData;
709 pixel = sdata[0] & 0xffff;
710 length = sdata.length;
711 break;
712 case DataBuffer.TYPE_INT:
713 int idata[] = (int[])inData;
714 pixel = idata[0];
715 length = idata.length;
716 break;
717 default:
718 throw new UnsupportedOperationException("This method has not been "+
719 "implemented for transferType " + transferType);
720 }
721 if (length == 1) {
722 return getGreen(pixel);
723 }
724 else {
725 throw new UnsupportedOperationException
726 ("This method is not supported by this color model");
727 }
728 }
729
730 /**
731 * Returns the blue color component for the specified pixel, scaled
732 * from 0 to 255 in the default RGB <code>ColorSpace</code>, sRGB. A
733 * color conversion is done if necessary. The pixel value is
734 * specified by an array of data elements of type transferType passed
735 * in as an object reference. The returned value is a non
736 * pre-multiplied value. For example, if the alpha is premultiplied,
737 * this method divides it out before returning the value. If the
738 * alpha value is 0, the blue value will be 0. If
739 * <code>inData</code> is not a primitive array of type transferType,
740 * a <code>ClassCastException</code> is thrown. An
741 * <code>ArrayIndexOutOfBoundsException</code> is
742 * thrown if <code>inData</code> is not large enough to hold a pixel
743 * value for this <code>ColorModel</code>.
744 * If this <code>transferType</code> is not supported, a
745 * <code>UnsupportedOperationException</code> will be
746 * thrown. Since
747 * <code>ColorModel</code> is an abstract class, any instance
748 * must be an instance of a subclass. Subclasses inherit the
749 * implementation of this method and if they don't override it, this
750 * method throws an exception if the subclass uses a
751 * <code>transferType</code> other than
752 * <code>DataBuffer.TYPE_BYTE</code>,
753 * <code>DataBuffer.TYPE_USHORT</code>, or
754 * <code>DataBuffer.TYPE_INT</code>.
755 * @param inData an array of pixel values
756 * @return the value of the blue component of the specified pixel.
757 * @throws ClassCastException if <code>inData</code>
758 * is not a primitive array of type <code>transferType</code>
759 * @throws ArrayIndexOutOfBoundsException if
760 * <code>inData</code> is not large enough to hold a pixel value
761 * for this <code>ColorModel</code>
762 * @throws UnsupportedOperationException if this
763 * <code>tranferType</code> is not supported by this
764 * <code>ColorModel</code>
765 */
766 public int getBlue(Object inData) {
767 int pixel=0,length=0;
768 switch (transferType) {
769 case DataBuffer.TYPE_BYTE:
770 byte bdata[] = (byte[])inData;
771 pixel = bdata[0] & 0xff;
772 length = bdata.length;
773 break;
774 case DataBuffer.TYPE_USHORT:
775 short sdata[] = (short[])inData;
776 pixel = sdata[0] & 0xffff;
777 length = sdata.length;
778 break;
779 case DataBuffer.TYPE_INT:
780 int idata[] = (int[])inData;
781 pixel = idata[0];
782 length = idata.length;
783 break;
784 default:
785 throw new UnsupportedOperationException("This method has not been "+
786 "implemented for transferType " + transferType);
787 }
788 if (length == 1) {
789 return getBlue(pixel);
790 }
791 else {
792 throw new UnsupportedOperationException
793 ("This method is not supported by this color model");
794 }
795 }
796
797 /**
798 * Returns the alpha component for the specified pixel, scaled
799 * from 0 to 255. The pixel value is specified by an array of data
800 * elements of type transferType passed in as an object reference.
801 * If inData is not a primitive array of type transferType, a
802 * <code>ClassCastException</code> is thrown. An
803 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
804 * <code>inData</code> is not large enough to hold a pixel value for
805 * this <code>ColorModel</code>.
806 * If this <code>transferType</code> is not supported, a
807 * <code>UnsupportedOperationException</code> will be
808 * thrown. Since
809 * <code>ColorModel</code> is an abstract class, any instance
810 * must be an instance of a subclass. Subclasses inherit the
811 * implementation of this method and if they don't override it, this
812 * method throws an exception if the subclass uses a
813 * <code>transferType</code> other than
814 * <code>DataBuffer.TYPE_BYTE</code>,
815 * <code>DataBuffer.TYPE_USHORT</code>, or
816 * <code>DataBuffer.TYPE_INT</code>.
817 * @param inData the specified pixel
818 * @return the alpha component of the specified pixel, scaled from
819 * 0 to 255.
820 * @throws ClassCastException if <code>inData</code>
821 * is not a primitive array of type <code>transferType</code>
822 * @throws ArrayIndexOutOfBoundsException if
823 * <code>inData</code> is not large enough to hold a pixel value
824 * for this <code>ColorModel</code>
825 * @throws UnsupportedOperationException if this
826 * <code>tranferType</code> is not supported by this
827 * <code>ColorModel</code>
828 */
829 public int getAlpha(Object inData) {
830 int pixel=0,length=0;
831 switch (transferType) {
832 case DataBuffer.TYPE_BYTE:
833 byte bdata[] = (byte[])inData;
834 pixel = bdata[0] & 0xff;
835 length = bdata.length;
836 break;
837 case DataBuffer.TYPE_USHORT:
838 short sdata[] = (short[])inData;
839 pixel = sdata[0] & 0xffff;
840 length = sdata.length;
841 break;
842 case DataBuffer.TYPE_INT:
843 int idata[] = (int[])inData;
844 pixel = idata[0];
845 length = idata.length;
846 break;
847 default:
848 throw new UnsupportedOperationException("This method has not been "+
849 "implemented for transferType " + transferType);
850 }
851 if (length == 1) {
852 return getAlpha(pixel);
853 }
854 else {
855 throw new UnsupportedOperationException
856 ("This method is not supported by this color model");
857 }
858 }
859
860 /**
861 * Returns the color/alpha components for the specified pixel in the
862 * default RGB color model format. A color conversion is done if
863 * necessary. The pixel value is specified by an array of data
864 * elements of type transferType passed in as an object reference.
865 * If inData is not a primitive array of type transferType, a
866 * <code>ClassCastException</code> is thrown. An
867 * <code>ArrayIndexOutOfBoundsException</code> is
868 * thrown if <code>inData</code> is not large enough to hold a pixel
869 * value for this <code>ColorModel</code>.
870 * The returned value will be in a non pre-multiplied format, i.e. if
871 * the alpha is premultiplied, this method will divide it out of the
872 * color components (if the alpha value is 0, the color values will be 0).
873 * @param inData the specified pixel
874 * @return the color and alpha components of the specified pixel.
875 * @see ColorModel#getRGBdefault
876 */
877 public int getRGB(Object inData) {
878 return (getAlpha(inData) << 24)
879 | (getRed(inData) << 16)
880 | (getGreen(inData) << 8)
881 | (getBlue(inData) << 0);
882 }
883
884 /**
885 * Returns a data element array representation of a pixel in this
886 * <code>ColorModel</code>, given an integer pixel representation in
887 * the default RGB color model.
888 * This array can then be passed to the
889 * {@link WritableRaster#setDataElements} method of
890 * a {@link WritableRaster} object. If the pixel variable is
891 * <code>null</code>, a new array will be allocated. If
892 * <code>pixel</code> is not
893 * <code>null</code>, it must be a primitive array of type
894 * <code>transferType</code>; otherwise, a
895 * <code>ClassCastException</code> is thrown. An
896 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
897 * <code>pixel</code> is
898 * not large enough to hold a pixel value for this
899 * <code>ColorModel</code>. The pixel array is returned.
900 * If this <code>transferType</code> is not supported, a
901 * <code>UnsupportedOperationException</code> will be
902 * thrown. Since <code>ColorModel</code> is an abstract class,
903 * any instance is an instance of a subclass. Subclasses must
904 * override this method since the implementation in this abstract
905 * class throws an <code>UnsupportedOperationException</code>.
906 * @param rgb the integer pixel representation in the default RGB
907 * color model
908 * @param pixel the specified pixel
909 * @return an array representation of the specified pixel in this
910 * <code>ColorModel</code>.
911 * @throws ClassCastException if <code>pixel</code>
912 * is not a primitive array of type <code>transferType</code>
913 * @throws ArrayIndexOutOfBoundsException if
914 * <code>pixel</code> is not large enough to hold a pixel value
915 * for this <code>ColorModel</code>
916 * @throws UnsupportedOperationException if this
917 * method is not supported by this <code>ColorModel</code>
918 * @see WritableRaster#setDataElements
919 * @see SampleModel#setDataElements
920 */
921 public Object getDataElements(int rgb, Object pixel) {
922 throw new UnsupportedOperationException
923 ("This method is not supported by this color model.");
924 }
925
926 /**
927 * Returns an array of unnormalized color/alpha components given a pixel
928 * in this <code>ColorModel</code>. The pixel value is specified as
929 * an <code>int</code>. An <code>IllegalArgumentException</code>
930 * will be thrown if pixel values for this <code>ColorModel</code> are
931 * not conveniently representable as a single <code>int</code> or if
932 * color component values for this <code>ColorModel</code> are not
933 * conveniently representable in the unnormalized form.
934 * For example, this method can be used to retrieve the
935 * components for a specific pixel value in a
936 * <code>DirectColorModel</code>. If the components array is
937 * <code>null</code>, a new array will be allocated. The
938 * components array will be returned. Color/alpha components are
939 * stored in the components array starting at <code>offset</code>
940 * (even if the array is allocated by this method). An
941 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
942 * components array is not <code>null</code> and is not large
943 * enough to hold all the color and alpha components (starting at offset).
944 * Since <code>ColorModel</code> is an abstract class,
945 * any instance is an instance of a subclass. Subclasses must
946 * override this method since the implementation in this abstract
947 * class throws an <code>UnsupportedOperationException</code>.
948 * @param pixel the specified pixel
949 * @param components the array to receive the color and alpha
950 * components of the specified pixel
951 * @param offset the offset into the <code>components</code> array at
952 * which to start storing the color and alpha components
953 * @return an array containing the color and alpha components of the
954 * specified pixel starting at the specified offset.
955 * @throws UnsupportedOperationException if this
956 * method is not supported by this <code>ColorModel</code>
957 */
958 public int[] getComponents(int pixel, int[] components, int offset) {
959 throw new UnsupportedOperationException
960 ("This method is not supported by this color model.");
961 }
962
963 /**
964 * Returns an array of unnormalized color/alpha components given a pixel
965 * in this <code>ColorModel</code>. The pixel value is specified by
966 * an array of data elements of type transferType passed in as an
967 * object reference. If <code>pixel</code> is not a primitive array
968 * of type transferType, a <code>ClassCastException</code> is thrown.
969 * An <code>IllegalArgumentException</code> will be thrown if color
970 * component values for this <code>ColorModel</code> are not
971 * conveniently representable in the unnormalized form.
972 * An <code>ArrayIndexOutOfBoundsException</code> is
973 * thrown if <code>pixel</code> is not large enough to hold a pixel
974 * value for this <code>ColorModel</code>.
975 * This method can be used to retrieve the components for a specific
976 * pixel value in any <code>ColorModel</code>. If the components
977 * array is <code>null</code>, a new array will be allocated. The
978 * components array will be returned. Color/alpha components are
979 * stored in the <code>components</code> array starting at
980 * <code>offset</code> (even if the array is allocated by this
981 * method). An <code>ArrayIndexOutOfBoundsException</code>
982 * is thrown if the components array is not <code>null</code> and is
983 * not large enough to hold all the color and alpha components
984 * (starting at <code>offset</code>).
985 * Since <code>ColorModel</code> is an abstract class,
986 * any instance is an instance of a subclass. Subclasses must
987 * override this method since the implementation in this abstract
988 * class throws an <code>UnsupportedOperationException</code>.
989 * @param pixel the specified pixel
990 * @param components an array that receives the color and alpha
991 * components of the specified pixel
992 * @param offset the index into the <code>components</code> array at
993 * which to begin storing the color and alpha components of the
994 * specified pixel
995 * @return an array containing the color and alpha components of the
996 * specified pixel starting at the specified offset.
997 * @throws UnsupportedOperationException if this
998 * method is not supported by this <code>ColorModel</code>
999 */
1000 public int[] getComponents(Object pixel, int[] components, int offset) {
1001 throw new UnsupportedOperationException
1002 ("This method is not supported by this color model.");
1003 }
1004
1005 /**
1006 * Returns an array of all of the color/alpha components in unnormalized
1007 * form, given a normalized component array. Unnormalized components
1008 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1009 * n is the number of bits for a particular component. Normalized
1010 * components are float values between a per component minimum and
1011 * maximum specified by the <code>ColorSpace</code> object for this
1012 * <code>ColorModel</code>. An <code>IllegalArgumentException</code>
1013 * will be thrown if color component values for this
1014 * <code>ColorModel</code> are not conveniently representable in the
1015 * unnormalized form. If the
1016 * <code>components</code> array is <code>null</code>, a new array
1017 * will be allocated. The <code>components</code> array will
1018 * be returned. Color/alpha components are stored in the
1019 * <code>components</code> array starting at <code>offset</code> (even
1020 * if the array is allocated by this method). An
1021 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1022 * <code>components</code> array is not <code>null</code> and is not
1023 * large enough to hold all the color and alpha
1024 * components (starting at <code>offset</code>). An
1025 * <code>IllegalArgumentException</code> is thrown if the
1026 * <code>normComponents</code> array is not large enough to hold
1027 * all the color and alpha components starting at
1028 * <code>normOffset</code>.
1029 * @param normComponents an array containing normalized components
1030 * @param normOffset the offset into the <code>normComponents</code>
1031 * array at which to start retrieving normalized components
1032 * @param components an array that receives the components from
1033 * <code>normComponents</code>
1034 * @param offset the index into <code>components</code> at which to
1035 * begin storing normalized components from
1036 * <code>normComponents</code>
1037 * @return an array containing unnormalized color and alpha
1038 * components.
1039 * @throws IllegalArgumentException If the component values for this
1040 * <CODE>ColorModel</CODE> are not conveniently representable in the
1041 * unnormalized form.
1042 * @throws IllegalArgumentException if the length of
1043 * <code>normComponents</code> minus <code>normOffset</code>
1044 * is less than <code>numComponents</code>
1045 * @throws UnsupportedOperationException if the
1046 * constructor of this <code>ColorModel</code> called the
1047 * <code>super(bits)</code> constructor, but did not
1048 * override this method. See the constructor,
1049 * {@link #ColorModel(int)}.
1050 */
1051 public int[] getUnnormalizedComponents(float[] normComponents,
1052 int normOffset,
1053 int[] components, int offset) {
1054 // Make sure that someone isn't using a custom color model
1055 // that called the super(bits) constructor.
1056 if (colorSpace == null) {
1057 throw new UnsupportedOperationException("This method is not supported "+
1058 "by this color model.");
1059 }
1060
1061 if (nBits == null) {
1062 throw new UnsupportedOperationException ("This method is not supported. "+
1063 "Unable to determine #bits per "+
1064 "component.");
1065 }
1066 if ((normComponents.length - normOffset) < numComponents) {
1067 throw new
1068 IllegalArgumentException(
1069 "Incorrect number of components. Expecting "+
1070 numComponents);
1071 }
1072
1073 if (components == null) {
1074 components = new int[offset+numComponents];
1075 }
1076
1077 if (supportsAlpha && isAlphaPremultiplied) {
1078 float normAlpha = normComponents[normOffset+numColorComponents];
1079 for (int i=0; i < numColorComponents; i++) {
1080 components[offset+i] = (int) (normComponents[normOffset+i]
1081 * ((1<<nBits[i]) - 1)
1082 * normAlpha + 0.5f);
1083 }
1084 components[offset+numColorComponents] = (int)
1085 (normAlpha * ((1<<nBits[numColorComponents]) - 1) + 0.5f);
1086 }
1087 else {
1088 for (int i=0; i < numComponents; i++) {
1089 components[offset+i] = (int) (normComponents[normOffset+i]
1090 * ((1<<nBits[i]) - 1) + 0.5f);
1091 }
1092 }
1093
1094 return components;
1095 }
1096
1097 /**
1098 * Returns an array of all of the color/alpha components in normalized
1099 * form, given an unnormalized component array. Unnormalized components
1100 * are unsigned integral values between 0 and 2<sup>n</sup> - 1, where
1101 * n is the number of bits for a particular component. Normalized
1102 * components are float values between a per component minimum and
1103 * maximum specified by the <code>ColorSpace</code> object for this
1104 * <code>ColorModel</code>. An <code>IllegalArgumentException</code>
1105 * will be thrown if color component values for this
1106 * <code>ColorModel</code> are not conveniently representable in the
1107 * unnormalized form. If the
1108 * <code>normComponents</code> array is <code>null</code>, a new array
1109 * will be allocated. The <code>normComponents</code> array
1110 * will be returned. Color/alpha components are stored in the
1111 * <code>normComponents</code> array starting at
1112 * <code>normOffset</code> (even if the array is allocated by this
1113 * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
1114 * if the <code>normComponents</code> array is not <code>null</code>
1115 * and is not large enough to hold all the color and alpha components
1116 * (starting at <code>normOffset</code>). An
1117 * <code>IllegalArgumentException</code> is thrown if the
1118 * <code>components</code> array is not large enough to hold all the
1119 * color and alpha components starting at <code>offset</code>.
1120 * <p>
1121 * Since <code>ColorModel</code> is an abstract class,
1122 * any instance is an instance of a subclass. The default implementation
1123 * of this method in this abstract class assumes that component values
1124 * for this class are conveniently representable in the unnormalized
1125 * form. Therefore, subclasses which may
1126 * have instances which do not support the unnormalized form must
1127 * override this method.
1128 * @param components an array containing unnormalized components
1129 * @param offset the offset into the <code>components</code> array at
1130 * which to start retrieving unnormalized components
1131 * @param normComponents an array that receives the normalized components
1132 * @param normOffset the index into <code>normComponents</code> at
1133 * which to begin storing normalized components
1134 * @return an array containing normalized color and alpha
1135 * components.
1136 * @throws IllegalArgumentException If the component values for this
1137 * <CODE>ColorModel</CODE> are not conveniently representable in the
1138 * unnormalized form.
1139 * @throws UnsupportedOperationException if the
1140 * constructor of this <code>ColorModel</code> called the
1141 * <code>super(bits)</code> constructor, but did not
1142 * override this method. See the constructor,
1143 * {@link #ColorModel(int)}.
1144 * @throws UnsupportedOperationException if this method is unable
1145 * to determine the number of bits per component
1146 */
1147 public float[] getNormalizedComponents(int[] components, int offset,
1148 float[] normComponents,
1149 int normOffset) {
1150 // Make sure that someone isn't using a custom color model
1151 // that called the super(bits) constructor.
1152 if (colorSpace == null) {
1153 throw new UnsupportedOperationException("This method is not supported by "+
1154 "this color model.");
1155 }
1156 if (nBits == null) {
1157 throw new UnsupportedOperationException ("This method is not supported. "+
1158 "Unable to determine #bits per "+
1159 "component.");
1160 }
1161
1162 if ((components.length - offset) < numComponents) {
1163 throw new
1164 IllegalArgumentException(
1165 "Incorrect number of components. Expecting "+
1166 numComponents);
1167 }
1168
1169 if (normComponents == null) {
1170 normComponents = new float[numComponents+normOffset];
1171 }
1172
1173 if (supportsAlpha && isAlphaPremultiplied) {
1174 // Normalized coordinates are non premultiplied
1175 float normAlpha = (float)components[offset+numColorComponents];
1176 normAlpha /= (float) ((1<<nBits[numColorComponents]) - 1);
1177 if (normAlpha != 0.0f) {
1178 for (int i=0; i < numColorComponents; i++) {
1179 normComponents[normOffset+i] =
1180 ((float) components[offset+i]) /
1181 (normAlpha * ((float) ((1<<nBits[i]) - 1)));
1182 }
1183 } else {
1184 for (int i=0; i < numColorComponents; i++) {
1185 normComponents[normOffset+i] = 0.0f;
1186 }
1187 }
1188 normComponents[normOffset+numColorComponents] = normAlpha;
1189 }
1190 else {
1191 for (int i=0; i < numComponents; i++) {
1192 normComponents[normOffset+i] = ((float) components[offset+i]) /
1193 ((float) ((1<<nBits[i]) - 1));
1194 }
1195 }
1196
1197 return normComponents;
1198 }
1199
1200 /**
1201 * Returns a pixel value represented as an <code>int</code> in this
1202 * <code>ColorModel</code>, given an array of unnormalized color/alpha
1203 * components. This method will throw an
1204 * <code>IllegalArgumentException</code> if component values for this
1205 * <code>ColorModel</code> are not conveniently representable as a
1206 * single <code>int</code> or if color component values for this
1207 * <code>ColorModel</code> are not conveniently representable in the
1208 * unnormalized form. An
1209 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1210 * <code>components</code> array is not large enough to hold all the
1211 * color and alpha components (starting at <code>offset</code>).
1212 * Since <code>ColorModel</code> is an abstract class,
1213 * any instance is an instance of a subclass. Subclasses must
1214 * override this method since the implementation in this abstract
1215 * class throws an <code>UnsupportedOperationException</code>.
1216 * @param components an array of unnormalized color and alpha
1217 * components
1218 * @param offset the index into <code>components</code> at which to
1219 * begin retrieving the color and alpha components
1220 * @return an <code>int</code> pixel value in this
1221 * <code>ColorModel</code> corresponding to the specified components.
1222 * @throws IllegalArgumentException if
1223 * pixel values for this <code>ColorModel</code> are not
1224 * conveniently representable as a single <code>int</code>
1225 * @throws IllegalArgumentException if
1226 * component values for this <code>ColorModel</code> are not
1227 * conveniently representable in the unnormalized form
1228 * @throws ArrayIndexOutOfBoundsException if
1229 * the <code>components</code> array is not large enough to
1230 * hold all of the color and alpha components starting at
1231 * <code>offset</code>
1232 * @throws UnsupportedOperationException if this
1233 * method is not supported by this <code>ColorModel</code>
1234 */
1235 public int getDataElement(int[] components, int offset) {
1236 throw new UnsupportedOperationException("This method is not supported "+
1237 "by this color model.");
1238 }
1239
1240 /**
1241 * Returns a data element array representation of a pixel in this
1242 * <code>ColorModel</code>, given an array of unnormalized color/alpha
1243 * components. This array can then be passed to the
1244 * <code>setDataElements</code> method of a <code>WritableRaster</code>
1245 * object. This method will throw an <code>IllegalArgumentException</code>
1246 * if color component values for this <code>ColorModel</code> are not
1247 * conveniently representable in the unnormalized form.
1248 * An <code>ArrayIndexOutOfBoundsException</code> is thrown
1249 * if the <code>components</code> array is not large enough to hold
1250 * all the color and alpha components (starting at
1251 * <code>offset</code>). If the <code>obj</code> variable is
1252 * <code>null</code>, a new array will be allocated. If
1253 * <code>obj</code> is not <code>null</code>, it must be a primitive
1254 * array of type transferType; otherwise, a
1255 * <code>ClassCastException</code> is thrown. An
1256 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
1257 * <code>obj</code> is not large enough to hold a pixel value for this
1258 * <code>ColorModel</code>.
1259 * Since <code>ColorModel</code> is an abstract class,
1260 * any instance is an instance of a subclass. Subclasses must
1261 * override this method since the implementation in this abstract
1262 * class throws an <code>UnsupportedOperationException</code>.
1263 * @param components an array of unnormalized color and alpha
1264 * components
1265 * @param offset the index into <code>components</code> at which to
1266 * begin retrieving color and alpha components
1267 * @param obj the <code>Object</code> representing an array of color
1268 * and alpha components
1269 * @return an <code>Object</code> representing an array of color and
1270 * alpha components.
1271 * @throws ClassCastException if <code>obj</code>
1272 * is not a primitive array of type <code>transferType</code>
1273 * @throws ArrayIndexOutOfBoundsException if
1274 * <code>obj</code> is not large enough to hold a pixel value
1275 * for this <code>ColorModel</code> or the <code>components</code>
1276 * array is not large enough to hold all of the color and alpha
1277 * components starting at <code>offset</code>
1278 * @throws IllegalArgumentException if
1279 * component values for this <code>ColorModel</code> are not
1280 * conveniently representable in the unnormalized form
1281 * @throws UnsupportedOperationException if this
1282 * method is not supported by this <code>ColorModel</code>
1283 * @see WritableRaster#setDataElements
1284 * @see SampleModel#setDataElements
1285 */
1286 public Object getDataElements(int[] components, int offset, Object obj) {
1287 throw new UnsupportedOperationException("This method has not been implemented "+
1288 "for this color model.");
1289 }
1290
1291 /**
1292 * Returns a pixel value represented as an <code>int</code> in this
1293 * <code>ColorModel</code>, given an array of normalized color/alpha
1294 * components. This method will throw an
1295 * <code>IllegalArgumentException</code> if pixel values for this
1296 * <code>ColorModel</code> are not conveniently representable as a
1297 * single <code>int</code>. An
1298 * <code>ArrayIndexOutOfBoundsException</code> is thrown if the
1299 * <code>normComponents</code> array is not large enough to hold all the
1300 * color and alpha components (starting at <code>normOffset</code>).
1301 * Since <code>ColorModel</code> is an abstract class,
1302 * any instance is an instance of a subclass. The default implementation
1303 * of this method in this abstract class first converts from the
1304 * normalized form to the unnormalized form and then calls
1305 * <code>getDataElement(int[], int)</code>. Subclasses which may
1306 * have instances which do not support the unnormalized form must
1307 * override this method.
1308 * @param normComponents an array of normalized color and alpha
1309 * components
1310 * @param normOffset the index into <code>normComponents</code> at which to
1311 * begin retrieving the color and alpha components
1312 * @return an <code>int</code> pixel value in this
1313 * <code>ColorModel</code> corresponding to the specified components.
1314 * @throws IllegalArgumentException if
1315 * pixel values for this <code>ColorModel</code> are not
1316 * conveniently representable as a single <code>int</code>
1317 * @throws ArrayIndexOutOfBoundsException if
1318 * the <code>normComponents</code> array is not large enough to
1319 * hold all of the color and alpha components starting at
1320 * <code>normOffset</code>
1321 * @since 1.4
1322 */
1323 public int getDataElement(float[] normComponents, int normOffset) {
1324 int components[] = getUnnormalizedComponents(normComponents,
1325 normOffset, null, 0);
1326 return getDataElement(components, 0);
1327 }
1328
1329 /**
1330 * Returns a data element array representation of a pixel in this
1331 * <code>ColorModel</code>, given an array of normalized color/alpha
1332 * components. This array can then be passed to the
1333 * <code>setDataElements</code> method of a <code>WritableRaster</code>
1334 * object. An <code>ArrayIndexOutOfBoundsException</code> is thrown
1335 * if the <code>normComponents</code> array is not large enough to hold
1336 * all the color and alpha components (starting at
1337 * <code>normOffset</code>). If the <code>obj</code> variable is
1338 * <code>null</code>, a new array will be allocated. If
1339 * <code>obj</code> is not <code>null</code>, it must be a primitive
1340 * array of type transferType; otherwise, a
1341 * <code>ClassCastException</code> is thrown. An
1342 * <code>ArrayIndexOutOfBoundsException</code> is thrown if
1343 * <code>obj</code> is not large enough to hold a pixel value for this
1344 * <code>ColorModel</code>.
1345 * Since <code>ColorModel</code> is an abstract class,
1346 * any instance is an instance of a subclass. The default implementation
1347 * of this method in this abstract class first converts from the
1348 * normalized form to the unnormalized form and then calls
1349 * <code>getDataElement(int[], int, Object)</code>. Subclasses which may
1350 * have instances which do not support the unnormalized form must
1351 * override this method.
1352 * @param normComponents an array of normalized color and alpha
1353 * components
1354 * @param normOffset the index into <code>normComponents</code> at which to
1355 * begin retrieving color and alpha components
1356 * @param obj a primitive data array to hold the returned pixel
1357 * @return an <code>Object</code> which is a primitive data array
1358 * representation of a pixel
1359 * @throws ClassCastException if <code>obj</code>
1360 * is not a primitive array of type <code>transferType</code>
1361 * @throws ArrayIndexOutOfBoundsException if
1362 * <code>obj</code> is not large enough to hold a pixel value
1363 * for this <code>ColorModel</code> or the <code>normComponents</code>
1364 * array is not large enough to hold all of the color and alpha
1365 * components starting at <code>normOffset</code>
1366 * @see WritableRaster#setDataElements
1367 * @see SampleModel#setDataElements
1368 * @since 1.4
1369 */
1370 public Object getDataElements(float[] normComponents, int normOffset,
1371 Object obj) {
1372 int components[] = getUnnormalizedComponents(normComponents,
1373 normOffset, null, 0);
1374 return getDataElements(components, 0, obj);
1375 }
1376
1377 /**
1378 * Returns an array of all of the color/alpha components in normalized
1379 * form, given a pixel in this <code>ColorModel</code>. The pixel
1380 * value is specified by an array of data elements of type transferType
1381 * passed in as an object reference. If pixel is not a primitive array
1382 * of type transferType, a <code>ClassCastException</code> is thrown.
1383 * An <code>ArrayIndexOutOfBoundsException</code> is thrown if
1384 * <code>pixel</code> is not large enough to hold a pixel value for this
1385 * <code>ColorModel</code>.
1386 * Normalized components are float values between a per component minimum
1387 * and maximum specified by the <code>ColorSpace</code> object for this
1388 * <code>ColorModel</code>. If the
1389 * <code>normComponents</code> array is <code>null</code>, a new array
1390 * will be allocated. The <code>normComponents</code> array
1391 * will be returned. Color/alpha components are stored in the
1392 * <code>normComponents</code> array starting at
1393 * <code>normOffset</code> (even if the array is allocated by this
1394 * method). An <code>ArrayIndexOutOfBoundsException</code> is thrown
1395 * if the <code>normComponents</code> array is not <code>null</code>
1396 * and is not large enough to hold all the color and alpha components
1397 * (starting at <code>normOffset</code>).
1398 * Since <code>ColorModel</code> is an abstract class,
1399 * any instance is an instance of a subclass. The default implementation
1400 * of this method in this abstract class first retrieves color and alpha
1401 * components in the unnormalized form using
1402 * <code>getComponents(Object, int[], int)</code> and then calls
1403 * <code>getNormalizedComponents(int[], int, float[], int)</code>.
1404 * Subclasses which may
1405 * have instances which do not support the unnormalized form must
1406 * override this method.
1407 * @param pixel the specified pixel
1408 * @param normComponents an array to receive the normalized components
1409 * @param normOffset the offset into the <code>normComponents</code>
1410 * array at which to start storing normalized components
1411 * @return an array containing normalized color and alpha
1412 * components.
1413 * @throws ClassCastException if <code>pixel</code> is not a primitive
1414 * array of type transferType
1415 * @throws ArrayIndexOutOfBoundsException if
1416 * <code>normComponents</code> is not large enough to hold all
1417 * color and alpha components starting at <code>normOffset</code>
1418 * @throws ArrayIndexOutOfBoundsException if
1419 * <code>pixel</code> is not large enough to hold a pixel
1420 * value for this <code>ColorModel</code>.
1421 * @throws UnsupportedOperationException if the
1422 * constructor of this <code>ColorModel</code> called the
1423 * <code>super(bits)</code> constructor, but did not
1424 * override this method. See the constructor,
1425 * {@link #ColorModel(int)}.
1426 * @throws UnsupportedOperationException if this method is unable
1427 * to determine the number of bits per component
1428 * @since 1.4
1429 */
1430 public float[] getNormalizedComponents(Object pixel,
1431 float[] normComponents,
1432 int normOffset) {
1433 int components[] = getComponents(pixel, null, 0);
1434 return getNormalizedComponents(components, 0,
1435 normComponents, normOffset);
1436 }
1437
1438 /**
1439 * Tests if the specified <code>Object</code> is an instance of
1440 * <code>ColorModel</code> and if it equals this
1441 * <code>ColorModel</code>.
1442 * @param obj the <code>Object</code> to test for equality
1443 * @return <code>true</code> if the specified <code>Object</code>
1444 * is an instance of <code>ColorModel</code> and equals this
1445 * <code>ColorModel</code>; <code>false</code> otherwise.
1446 */
1447 public boolean equals(Object obj) {
1448 if (!(obj instanceof ColorModel)) {
1449 return false;
1450 }
1451 ColorModel cm = (ColorModel) obj;
1452
1453 if (this == cm) {
1454 return true;
1455 }
1456 if (supportsAlpha != cm.hasAlpha() ||
1457 isAlphaPremultiplied != cm.isAlphaPremultiplied() ||
1458 pixel_bits != cm.getPixelSize() ||
1459 transparency != cm.getTransparency() ||
1460 numComponents != cm.getNumComponents())
1461 {
1462 return false;
1463 }
1464
1465 int[] nb = cm.getComponentSize();
1466
1467 if ((nBits != null) && (nb != null)) {
1468 for (int i = 0; i < numComponents; i++) {
1469 if (nBits[i] != nb[i]) {
1470 return false;
1471 }
1472 }
1473 } else {
1474 return ((nBits == null) && (nb == null));
1475 }
1476
1477 return true;
1478 }
1479
1480 /**
1481 * Returns the hash code for this ColorModel.
1482 *
1483 * @return a hash code for this ColorModel.
1484 */
1485 public int hashCode() {
1486
1487 int result = 0;
1488
1489 result = (supportsAlpha ? 2 : 3) +
1490 (isAlphaPremultiplied ? 4 : 5) +
1491 pixel_bits * 6 +
1492 transparency * 7 +
1493 numComponents * 8;
1494
1495 if (nBits != null) {
1496 for (int i = 0; i < numComponents; i++) {
1497 result = result + nBits[i] * (i + 9);
1498 }
1499 }
1500
1501 return result;
1502 }
1503
1504 /**
1505 * Returns the <code>ColorSpace</code> associated with this
1506 * <code>ColorModel</code>.
1507 * @return the <code>ColorSpace</code> of this
1508 * <code>ColorModel</code>.
1509 */
1510 final public ColorSpace getColorSpace() {
1511 return colorSpace;
1512 }
1513
1514 /**
1515 * Forces the raster data to match the state specified in the
1516 * <code>isAlphaPremultiplied</code> variable, assuming the data is
1517 * currently correctly described by this <code>ColorModel</code>. It
1518 * may multiply or divide the color raster data by alpha, or do
1519 * nothing if the data is in the correct state. If the data needs to
1520 * be coerced, this method will also return an instance of this
1521 * <code>ColorModel</code> with the <code>isAlphaPremultiplied</code>
1522 * flag set appropriately. This method will throw a
1523 * <code>UnsupportedOperationException</code> if it is not supported
1524 * by this <code>ColorModel</code>.
1525 * Since <code>ColorModel</code> is an abstract class,
1526 * any instance is an instance of a subclass. Subclasses must
1527 * override this method since the implementation in this abstract
1528 * class throws an <code>UnsupportedOperationException</code>.
1529 * @param raster the <code>WritableRaster</code> data
1530 * @param isAlphaPremultiplied <code>true</code> if the alpha is
1531 * premultiplied; <code>false</code> otherwise
1532 * @return a <code>ColorModel</code> object that represents the
1533 * coerced data.
1534 */
1535 public ColorModel coerceData (WritableRaster raster,
1536 boolean isAlphaPremultiplied) {
1537 throw new UnsupportedOperationException
1538 ("This method is not supported by this color model");
1539 }
1540
1541 /**
1542 * Returns <code>true</code> if <code>raster</code> is compatible
1543 * with this <code>ColorModel</code> and <code>false</code> if it is
1544 * not.
1545 * Since <code>ColorModel</code> is an abstract class,
1546 * any instance is an instance of a subclass. Subclasses must
1547 * override this method since the implementation in this abstract
1548 * class throws an <code>UnsupportedOperationException</code>.
1549 * @param raster the {@link Raster} object to test for compatibility
1550 * @return <code>true</code> if <code>raster</code> is compatible
1551 * with this <code>ColorModel</code>.
1552 * @throws UnsupportedOperationException if this
1553 * method has not been implemented for this
1554 * <code>ColorModel</code>
1555 */
1556 public boolean isCompatibleRaster(Raster raster) {
1557 throw new UnsupportedOperationException(
1558 "This method has not been implemented for this ColorModel.");
1559 }
1560
1561 /**
1562 * Creates a <code>WritableRaster</code> with the specified width and
1563 * height that has a data layout (<code>SampleModel</code>) compatible
1564 * with this <code>ColorModel</code>.
1565 * Since <code>ColorModel</code> is an abstract class,
1566 * any instance is an instance of a subclass. Subclasses must
1567 * override this method since the implementation in this abstract
1568 * class throws an <code>UnsupportedOperationException</code>.
1569 * @param w the width to apply to the new <code>WritableRaster</code>
1570 * @param h the height to apply to the new <code>WritableRaster</code>
1571 * @return a <code>WritableRaster</code> object with the specified
1572 * width and height.
1573 * @throws UnsupportedOperationException if this
1574 * method is not supported by this <code>ColorModel</code>
1575 * @see WritableRaster
1576 * @see SampleModel
1577 */
1578 public WritableRaster createCompatibleWritableRaster(int w, int h) {
1579 throw new UnsupportedOperationException
1580 ("This method is not supported by this color model");
1581 }
1582
1583 /**
1584 * Creates a <code>SampleModel</code> with the specified width and
1585 * height that has a data layout compatible with this
1586 * <code>ColorModel</code>.
1587 * Since <code>ColorModel</code> is an abstract class,
1588 * any instance is an instance of a subclass. Subclasses must
1589 * override this method since the implementation in this abstract
1590 * class throws an <code>UnsupportedOperationException</code>.
1591 * @param w the width to apply to the new <code>SampleModel</code>
1592 * @param h the height to apply to the new <code>SampleModel</code>
1593 * @return a <code>SampleModel</code> object with the specified
1594 * width and height.
1595 * @throws UnsupportedOperationException if this
1596 * method is not supported by this <code>ColorModel</code>
1597 * @see SampleModel
1598 */
1599 public SampleModel createCompatibleSampleModel(int w, int h) {
1600 throw new UnsupportedOperationException
1601 ("This method is not supported by this color model");
1602 }
1603
1604 /** Checks if the <code>SampleModel</code> is compatible with this
1605 * <code>ColorModel</code>.
1606 * Since <code>ColorModel</code> is an abstract class,
1607 * any instance is an instance of a subclass. Subclasses must
1608 * override this method since the implementation in this abstract
1609 * class throws an <code>UnsupportedOperationException</code>.
1610 * @param sm the specified <code>SampleModel</code>
1611 * @return <code>true</code> if the specified <code>SampleModel</code>
1612 * is compatible with this <code>ColorModel</code>; <code>false</code>
1613 * otherwise.
1614 * @throws UnsupportedOperationException if this
1615 * method is not supported by this <code>ColorModel</code>
1616 * @see SampleModel
1617 */
1618 public boolean isCompatibleSampleModel(SampleModel sm) {
1619 throw new UnsupportedOperationException
1620 ("This method is not supported by this color model");
1621 }
1622
1623 /**
1624 * Disposes of system resources associated with this
1625 * <code>ColorModel</code> once this <code>ColorModel</code> is no
1626 * longer referenced.
1627 */
1628 public void finalize() {
1629 }
1630
1631
1632 /**
1633 * Returns a <code>Raster</code> representing the alpha channel of an
1634 * image, extracted from the input <code>Raster</code>, provided that
1635 * pixel values of this <code>ColorModel</code> represent color and
1636 * alpha information as separate spatial bands (e.g.
1637 * {@link ComponentColorModel} and <code>DirectColorModel</code>).
1638 * This method assumes that <code>Raster</code> objects associated
1639 * with such a <code>ColorModel</code> store the alpha band, if
1640 * present, as the last band of image data. Returns <code>null</code>
1641 * if there is no separate spatial alpha channel associated with this
1642 * <code>ColorModel</code>. If this is an
1643 * <code>IndexColorModel</code> which has alpha in the lookup table,
1644 * this method will return <code>null</code> since
1645 * there is no spatially discrete alpha channel.
1646 * This method will create a new <code>Raster</code> (but will share
1647 * the data array).
1648 * Since <code>ColorModel</code> is an abstract class, any instance
1649 * is an instance of a subclass. Subclasses must override this
1650 * method to get any behavior other than returning <code>null</code>
1651 * because the implementation in this abstract class returns
1652 * <code>null</code>.
1653 * @param raster the specified <code>Raster</code>
1654 * @return a <code>Raster</code> representing the alpha channel of
1655 * an image, obtained from the specified <code>Raster</code>.
1656 */
1657 public WritableRaster getAlphaRaster(WritableRaster raster) {
1658 return null;
1659 }
1660
1661 /**
1662 * Returns the <code>String</code> representation of the contents of
1663 * this <code>ColorModel</code>object.
1664 * @return a <code>String</code> representing the contents of this
1665 * <code>ColorModel</code> object.
1666 */
1667 public String toString() {
1668 return new String("ColorModel: #pixelBits = "+pixel_bits
1669 + " numComponents = "+numComponents
1670 + " color space = "+colorSpace
1671 + " transparency = "+transparency
1672 + " has alpha = "+supportsAlpha
1673 + " isAlphaPre = "+isAlphaPremultiplied
1674 );
1675 }
1676
1677 static int getDefaultTransferType(int pixel_bits) {
1678 if (pixel_bits <= 8) {
1679 return DataBuffer.TYPE_BYTE;
1680 } else if (pixel_bits <= 16) {
1681 return DataBuffer.TYPE_USHORT;
1682 } else if (pixel_bits <= 32) {
1683 return DataBuffer.TYPE_INT;
1684 } else {
1685 return DataBuffer.TYPE_UNDEFINED;
1686 }
1687 }
1688
1689 static byte[] l8Tos8 = null; // 8-bit linear to 8-bit non-linear sRGB LUT
1690 static byte[] s8Tol8 = null; // 8-bit non-linear sRGB to 8-bit linear LUT
1691 static byte[] l16Tos8 = null; // 16-bit linear to 8-bit non-linear sRGB LUT
1692 static short[] s8Tol16 = null; // 8-bit non-linear sRGB to 16-bit linear LUT
1693
1694 // Maps to hold LUTs for grayscale conversions
1695 static Map g8Tos8Map = null; // 8-bit gray values to 8-bit sRGB values
1696 static Map lg16Toog8Map = null; // 16-bit linear to 8-bit "other" gray
1697 static Map g16Tos8Map = null; // 16-bit gray values to 8-bit sRGB values
1698 static Map lg16Toog16Map = null; // 16-bit linear to 16-bit "other" gray
1699
1700 static boolean isLinearRGBspace(ColorSpace cs) {
1701 // Note: CMM.LINEAR_RGBspace will be null if the linear
1702 // RGB space has not been created yet.
1703 return (cs == CMSManager.LINEAR_RGBspace);
1704 }
1705
1706 static boolean isLinearGRAYspace(ColorSpace cs) {
1707 // Note: CMM.GRAYspace will be null if the linear
1708 // gray space has not been created yet.
1709 return (cs == CMSManager.GRAYspace);
1710 }
1711
1712 static byte[] getLinearRGB8TosRGB8LUT() {
1713 if (l8Tos8 == null) {
1714 l8Tos8 = new byte[256];
1715 float input, output;
1716 // algorithm for linear RGB to nonlinear sRGB conversion
1717 // is from the IEC 61966-2-1 International Standard,
1718 // Colour Management - Default RGB colour space - sRGB,
1719 // First Edition, 1999-10,
1720 // avaiable for order at http://www.iec.ch
1721 for (int i = 0; i <= 255; i++) {
1722 input = ((float) i) / 255.0f;
1723 if (input <= 0.0031308f) {
1724 output = input * 12.92f;
1725 } else {
1726 output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4)))
1727 - 0.055f;
1728 }
1729 l8Tos8[i] = (byte) Math.round(output * 255.0f);
1730 }
1731 }
1732 return l8Tos8;
1733 }
1734
1735 static byte[] getsRGB8ToLinearRGB8LUT() {
1736 if (s8Tol8 == null) {
1737 s8Tol8 = new byte[256];
1738 float input, output;
1739 // algorithm from IEC 61966-2-1 International Standard
1740 for (int i = 0; i <= 255; i++) {
1741 input = ((float) i) / 255.0f;
1742 if (input <= 0.04045f) {
1743 output = input / 12.92f;
1744 } else {
1745 output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4);
1746 }
1747 s8Tol8[i] = (byte) Math.round(output * 255.0f);
1748 }
1749 }
1750 return s8Tol8;
1751 }
1752
1753 static byte[] getLinearRGB16TosRGB8LUT() {
1754 if (l16Tos8 == null) {
1755 l16Tos8 = new byte[65536];
1756 float input, output;
1757 // algorithm from IEC 61966-2-1 International Standard
1758 for (int i = 0; i <= 65535; i++) {
1759 input = ((float) i) / 65535.0f;
1760 if (input <= 0.0031308f) {
1761 output = input * 12.92f;
1762 } else {
1763 output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4)))
1764 - 0.055f;
1765 }
1766 l16Tos8[i] = (byte) Math.round(output * 255.0f);
1767 }
1768 }
1769 return l16Tos8;
1770 }
1771
1772 static short[] getsRGB8ToLinearRGB16LUT() {
1773 if (s8Tol16 == null) {
1774 s8Tol16 = new short[256];
1775 float input, output;
1776 // algorithm from IEC 61966-2-1 International Standard
1777 for (int i = 0; i <= 255; i++) {
1778 input = ((float) i) / 255.0f;
1779 if (input <= 0.04045f) {
1780 output = input / 12.92f;
1781 } else {
1782 output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4);
1783 }
1784 s8Tol16[i] = (short) Math.round(output * 65535.0f);
1785 }
1786 }
1787 return s8Tol16;
1788 }
1789
1790 /*
1791 * Return a byte LUT that converts 8-bit gray values in the grayCS
1792 * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut
1793 * is the byte array returned by this method and sval = lut[gval],
1794 * then the sRGB triple (sval,sval,sval) is the best match to gval.
1795 * Cache references to any computed LUT in a Map.
1796 */
1797 static byte[] getGray8TosRGB8LUT(ICC_ColorSpace grayCS) {
1798 if (isLinearGRAYspace(grayCS)) {
1799 return getLinearRGB8TosRGB8LUT();
1800 }
1801 if (g8Tos8Map != null) {
1802 byte[] g8Tos8LUT = (byte []) g8Tos8Map.get(grayCS);
1803 if (g8Tos8LUT != null) {
1804 return g8Tos8LUT;
1805 }
1806 }
1807 byte[] g8Tos8LUT = new byte[256];
1808 for (int i = 0; i <= 255; i++) {
1809 g8Tos8LUT[i] = (byte) i;
1810 }
1811 ColorTransform[] transformList = new ColorTransform[2];
1812 PCMM mdl = CMSManager.getModule();
1813 ICC_ColorSpace srgbCS =
1814 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB);
1815 transformList[0] = mdl.createTransform(
1816 grayCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1817 transformList[1] = mdl.createTransform(
1818 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1819 ColorTransform t = mdl.createTransform(transformList);
1820 byte[] tmp = t.colorConvert(g8Tos8LUT, null);
1821 for (int i = 0, j= 2; i <= 255; i++, j += 3) {
1822 // All three components of tmp should be equal, since
1823 // the input color space to colorConvert is a gray scale
1824 // space. However, there are slight anomalies in the results.
1825 // Copy tmp starting at index 2, since colorConvert seems
1826 // to be slightly more accurate for the third component!
1827 g8Tos8LUT[i] = tmp[j];
1828 }
1829 if (g8Tos8Map == null) {
1830 g8Tos8Map = Collections.synchronizedMap(new WeakHashMap(2));
1831 }
1832 g8Tos8Map.put(grayCS, g8Tos8LUT);
1833 return g8Tos8LUT;
1834 }
1835
1836 /*
1837 * Return a byte LUT that converts 16-bit gray values in the CS_GRAY
1838 * linear gray ColorSpace to the appropriate 8-bit value in the
1839 * grayCS ColorSpace. Cache references to any computed LUT in a Map.
1840 */
1841 static byte[] getLinearGray16ToOtherGray8LUT(ICC_ColorSpace grayCS) {
1842 if (lg16Toog8Map != null) {
1843 byte[] lg16Toog8LUT = (byte []) lg16Toog8Map.get(grayCS);
1844 if (lg16Toog8LUT != null) {
1845 return lg16Toog8LUT;
1846 }
1847 }
1848 short[] tmp = new short[65536];
1849 for (int i = 0; i <= 65535; i++) {
1850 tmp[i] = (short) i;
1851 }
1852 ColorTransform[] transformList = new ColorTransform[2];
1853 PCMM mdl = CMSManager.getModule();
1854 ICC_ColorSpace lgCS =
1855 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY);
1856 transformList[0] = mdl.createTransform (
1857 lgCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1858 transformList[1] = mdl.createTransform (
1859 grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1860 ColorTransform t = mdl.createTransform(transformList);
1861 tmp = t.colorConvert(tmp, null);
1862 byte[] lg16Toog8LUT = new byte[65536];
1863 for (int i = 0; i <= 65535; i++) {
1864 // scale unsigned short (0 - 65535) to unsigned byte (0 - 255)
1865 lg16Toog8LUT[i] =
1866 (byte) (((float) (tmp[i] & 0xffff)) * (1.0f /257.0f) + 0.5f);
1867 }
1868 if (lg16Toog8Map == null) {
1869 lg16Toog8Map = Collections.synchronizedMap(new WeakHashMap(2));
1870 }
1871 lg16Toog8Map.put(grayCS, lg16Toog8LUT);
1872 return lg16Toog8LUT;
1873 }
1874
1875 /*
1876 * Return a byte LUT that converts 16-bit gray values in the grayCS
1877 * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut
1878 * is the byte array returned by this method and sval = lut[gval],
1879 * then the sRGB triple (sval,sval,sval) is the best match to gval.
1880 * Cache references to any computed LUT in a Map.
1881 */
1882 static byte[] getGray16TosRGB8LUT(ICC_ColorSpace grayCS) {
1883 if (isLinearGRAYspace(grayCS)) {
1884 return getLinearRGB16TosRGB8LUT();
1885 }
1886 if (g16Tos8Map != null) {
1887 byte[] g16Tos8LUT = (byte []) g16Tos8Map.get(grayCS);
1888 if (g16Tos8LUT != null) {
1889 return g16Tos8LUT;
1890 }
1891 }
1892 short[] tmp = new short[65536];
1893 for (int i = 0; i <= 65535; i++) {
1894 tmp[i] = (short) i;
1895 }
1896 ColorTransform[] transformList = new ColorTransform[2];
1897 PCMM mdl = CMSManager.getModule();
1898 ICC_ColorSpace srgbCS =
1899 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB);
1900 transformList[0] = mdl.createTransform (
1901 grayCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1902 transformList[1] = mdl.createTransform (
1903 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1904 ColorTransform t = mdl.createTransform(transformList);
1905 tmp = t.colorConvert(tmp, null);
1906 byte[] g16Tos8LUT = new byte[65536];
1907 for (int i = 0, j= 2; i <= 65535; i++, j += 3) {
1908 // All three components of tmp should be equal, since
1909 // the input color space to colorConvert is a gray scale
1910 // space. However, there are slight anomalies in the results.
1911 // Copy tmp starting at index 2, since colorConvert seems
1912 // to be slightly more accurate for the third component!
1913
1914 // scale unsigned short (0 - 65535) to unsigned byte (0 - 255)
1915 g16Tos8LUT[i] =
1916 (byte) (((float) (tmp[j] & 0xffff)) * (1.0f /257.0f) + 0.5f);
1917 }
1918 if (g16Tos8Map == null) {
1919 g16Tos8Map = Collections.synchronizedMap(new WeakHashMap(2));
1920 }
1921 g16Tos8Map.put(grayCS, g16Tos8LUT);
1922 return g16Tos8LUT;
1923 }
1924
1925 /*
1926 * Return a short LUT that converts 16-bit gray values in the CS_GRAY
1927 * linear gray ColorSpace to the appropriate 16-bit value in the
1928 * grayCS ColorSpace. Cache references to any computed LUT in a Map.
1929 */
1930 static short[] getLinearGray16ToOtherGray16LUT(ICC_ColorSpace grayCS) {
1931 if (lg16Toog16Map != null) {
1932 short[] lg16Toog16LUT = (short []) lg16Toog16Map.get(grayCS);
1933 if (lg16Toog16LUT != null) {
1934 return lg16Toog16LUT;
1935 }
1936 }
1937 short[] tmp = new short[65536];
1938 for (int i = 0; i <= 65535; i++) {
1939 tmp[i] = (short) i;
1940 }
1941 ColorTransform[] transformList = new ColorTransform[2];
1942 PCMM mdl = CMSManager.getModule();
1943 ICC_ColorSpace lgCS =
1944 (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY);
1945 transformList[0] = mdl.createTransform (
1946 lgCS.getProfile(), ColorTransform.Any, ColorTransform.In);
1947 transformList[1] = mdl.createTransform(
1948 grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
1949 ColorTransform t = mdl.createTransform(
1950 transformList);
1951 short[] lg16Toog16LUT = t.colorConvert(tmp, null);
1952 if (lg16Toog16Map == null) {
1953 lg16Toog16Map = Collections.synchronizedMap(new WeakHashMap(2));
1954 }
1955 lg16Toog16Map.put(grayCS, lg16Toog16LUT);
1956 return lg16Toog16LUT;
1957 }
1958
1959}