1 /*
2 * Portions Copyright 1997-2007 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
26 /**********************************************************************
27 **********************************************************************
28 **********************************************************************
29 *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
30 *** As an unpublished work pursuant to Title 17 of the United ***
31 *** States Code. All rights reserved. ***
32 **********************************************************************
33 **********************************************************************
34 **********************************************************************/
35
36 package java.awt.color;
37
38 import sun.java2d.cmm.ColorTransform;
39 import sun.java2d.cmm.CMSManager;
40 import sun.java2d.cmm.PCMM;
41
42
43 /**
44 *
45 * The ICC_ColorSpace class is an implementation of the abstract
46 * ColorSpace class. This representation of
47 * device independent and device dependent color spaces is based on the
48 * International Color Consortium Specification ICC.1:2001-12, File Format for
49 * Color Profiles (see <A href="http://www.color.org">http://www.color.org</A>).
50 * <p>
51 * Typically, a Color or ColorModel would be associated with an ICC
52 * Profile which is either an input, display, or output profile (see
53 * the ICC specification). There are other types of ICC Profiles, e.g.
54 * abstract profiles, device link profiles, and named color profiles,
55 * which do not contain information appropriate for representing the color
56 * space of a color, image, or device (see ICC_Profile).
57 * Attempting to create an ICC_ColorSpace object from an inappropriate ICC
58 * Profile is an error.
59 * <p>
60 * ICC Profiles represent transformations from the color space of
61 * the profile (e.g. a monitor) to a Profile Connection Space (PCS).
62 * Profiles of interest for tagging images or colors have a
63 * PCS which is one of the device independent
64 * spaces (one CIEXYZ space and two CIELab spaces) defined in the
65 * ICC Profile Format Specification. Most profiles of interest
66 * either have invertible transformations or explicitly specify
67 * transformations going both directions. Should an ICC_ColorSpace
68 * object be used in a way requiring a conversion from PCS to
69 * the profile's native space and there is inadequate data to
70 * correctly perform the conversion, the ICC_ColorSpace object will
71 * produce output in the specified type of color space (e.g. TYPE_RGB,
72 * TYPE_CMYK, etc.), but the specific color values of the output data
73 * will be undefined.
74 * <p>
75 * The details of this class are not important for simple applets,
76 * which draw in a default color space or manipulate and display
77 * imported images with a known color space. At most, such applets
78 * would need to get one of the default color spaces via
79 * ColorSpace.getInstance().
80 * <p>
81 * @see ColorSpace
82 * @see ICC_Profile
83 */
84
85
86
87 public class ICC_ColorSpace extends ColorSpace {
88
89 static final long serialVersionUID = 3455889114070431483L;
90
91 private ICC_Profile thisProfile;
92 private float[] minVal;
93 private float[] maxVal;
94 private float[] diffMinMax;
95 private float[] invDiffMinMax;
96 private boolean needScaleInit = true;
97
98 // {to,from}{RGB,CIEXYZ} methods create and cache these when needed
99 private transient ColorTransform this2srgb;
100 private transient ColorTransform srgb2this;
101 private transient ColorTransform this2xyz;
102 private transient ColorTransform xyz2this;
103
104
105 /**
106 * Constructs a new ICC_ColorSpace from an ICC_Profile object.
107 * @param profile the specified ICC_Profile object
108 * @exception IllegalArgumentException if profile is inappropriate for
109 * representing a ColorSpace.
110 */
111 public ICC_ColorSpace (ICC_Profile profile) {
112 super (profile.getColorSpaceType(), profile.getNumComponents());
113
114 int profileClass = profile.getProfileClass();
115
116 /* REMIND - is NAMEDCOLOR OK? */
117 if ((profileClass != ICC_Profile.CLASS_INPUT) &&
118 (profileClass != ICC_Profile.CLASS_DISPLAY) &&
119 (profileClass != ICC_Profile.CLASS_OUTPUT) &&
120 (profileClass != ICC_Profile.CLASS_COLORSPACECONVERSION) &&
121 (profileClass != ICC_Profile.CLASS_NAMEDCOLOR) &&
122 (profileClass != ICC_Profile.CLASS_ABSTRACT)) {
123 throw new IllegalArgumentException("Invalid profile type");
124 }
125
126 thisProfile = profile;
127 setMinMax();
128 }
129
130 /**
131 * Returns the ICC_Profile for this ICC_ColorSpace.
132 * @return the ICC_Profile for this ICC_ColorSpace.
133 */
134 public ICC_Profile getProfile() {
135 return thisProfile;
136 }
137
138 /**
139 * Transforms a color value assumed to be in this ColorSpace
140 * into a value in the default CS_sRGB color space.
141 * <p>
142 * This method transforms color values using algorithms designed
143 * to produce the best perceptual match between input and output
144 * colors. In order to do colorimetric conversion of color values,
145 * you should use the <code>toCIEXYZ</code>
146 * method of this color space to first convert from the input
147 * color space to the CS_CIEXYZ color space, and then use the
148 * <code>fromCIEXYZ</code> method of the CS_sRGB color space to
149 * convert from CS_CIEXYZ to the output color space.
150 * See {@link #toCIEXYZ(float[]) toCIEXYZ} and
151 * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
152 * <p>
153 * @param colorvalue a float array with length of at least the number
154 * of components in this ColorSpace.
155 * @return a float array of length 3.
156 * @throws ArrayIndexOutOfBoundsException if array length is not
157 * at least the number of components in this ColorSpace.
158 */
159 public float[] toRGB (float[] colorvalue) {
160
161 if (this2srgb == null) {
162 ColorTransform[] transformList = new ColorTransform [2];
163 ICC_ColorSpace srgbCS =
164 (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB);
165 PCMM mdl = CMSManager.getModule();
166 transformList[0] = mdl.createTransform(
167 thisProfile, ColorTransform.Any, ColorTransform.In);
168 transformList[1] = mdl.createTransform(
169 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
170 this2srgb = mdl.createTransform(transformList);
171 if (needScaleInit) {
172 setComponentScaling();
173 }
174 }
175
176 int nc = this.getNumComponents();
177 short tmp[] = new short[nc];
178 for (int i = 0; i < nc; i++) {
179 tmp[i] = (short)
180 ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f);
181 }
182 tmp = this2srgb.colorConvert(tmp, null);
183 float[] result = new float [3];
184 for (int i = 0; i < 3; i++) {
185 result[i] = ((float) (tmp[i] & 0xffff)) / 65535.0f;
186 }
187 return result;
188 }
189
190 /**
191 * Transforms a color value assumed to be in the default CS_sRGB
192 * color space into this ColorSpace.
193 * <p>
194 * This method transforms color values using algorithms designed
195 * to produce the best perceptual match between input and output
196 * colors. In order to do colorimetric conversion of color values,
197 * you should use the <code>toCIEXYZ</code>
198 * method of the CS_sRGB color space to first convert from the input
199 * color space to the CS_CIEXYZ color space, and then use the
200 * <code>fromCIEXYZ</code> method of this color space to
201 * convert from CS_CIEXYZ to the output color space.
202 * See {@link #toCIEXYZ(float[]) toCIEXYZ} and
203 * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
204 * <p>
205 * @param rgbvalue a float array with length of at least 3.
206 * @return a float array with length equal to the number of
207 * components in this ColorSpace.
208 * @throws ArrayIndexOutOfBoundsException if array length is not
209 * at least 3.
210 */
211 public float[] fromRGB(float[] rgbvalue) {
212
213 if (srgb2this == null) {
214 ColorTransform[] transformList = new ColorTransform [2];
215 ICC_ColorSpace srgbCS =
216 (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB);
217 PCMM mdl = CMSManager.getModule();
218 transformList[0] = mdl.createTransform(
219 srgbCS.getProfile(), ColorTransform.Any, ColorTransform.In);
220 transformList[1] = mdl.createTransform(
221 thisProfile, ColorTransform.Any, ColorTransform.Out);
222 srgb2this = mdl.createTransform(transformList);
223 if (needScaleInit) {
224 setComponentScaling();
225 }
226 }
227
228 short tmp[] = new short[3];
229 for (int i = 0; i < 3; i++) {
230 tmp[i] = (short) ((rgbvalue[i] * 65535.0f) + 0.5f);
231 }
232 tmp = srgb2this.colorConvert(tmp, null);
233 int nc = this.getNumComponents();
234 float[] result = new float [nc];
235 for (int i = 0; i < nc; i++) {
236 result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) *
237 diffMinMax[i] + minVal[i];
238 }
239 return result;
240 }
241
242
243 /**
244 * Transforms a color value assumed to be in this ColorSpace
245 * into the CS_CIEXYZ conversion color space.
246 * <p>
247 * This method transforms color values using relative colorimetry,
248 * as defined by the ICC Specification. This
249 * means that the XYZ values returned by this method are represented
250 * relative to the D50 white point of the CS_CIEXYZ color space.
251 * This representation is useful in a two-step color conversion
252 * process in which colors are transformed from an input color
253 * space to CS_CIEXYZ and then to an output color space. This
254 * representation is not the same as the XYZ values that would
255 * be measured from the given color value by a colorimeter.
256 * A further transformation is necessary to compute the XYZ values
257 * that would be measured using current CIE recommended practices.
258 * The paragraphs below explain this in more detail.
259 * <p>
260 * The ICC standard uses a device independent color space (DICS) as the
261 * mechanism for converting color from one device to another device. In
262 * this architecture, colors are converted from the source device's color
263 * space to the ICC DICS and then from the ICC DICS to the destination
264 * device's color space. The ICC standard defines device profiles which
265 * contain transforms which will convert between a device's color space
266 * and the ICC DICS. The overall conversion of colors from a source
267 * device to colors of a destination device is done by connecting the
268 * device-to-DICS transform of the profile for the source device to the
269 * DICS-to-device transform of the profile for the destination device.
270 * For this reason, the ICC DICS is commonly referred to as the profile
271 * connection space (PCS). The color space used in the methods
272 * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC
273 * Specification. This is also the color space represented by
274 * ColorSpace.CS_CIEXYZ.
275 * <p>
276 * The XYZ values of a color are often represented as relative to some
277 * white point, so the actual meaning of the XYZ values cannot be known
278 * without knowing the white point of those values. This is known as
279 * relative colorimetry. The PCS uses a white point of D50, so the XYZ
280 * values of the PCS are relative to D50. For example, white in the PCS
281 * will have the XYZ values of D50, which is defined to be X=.9642,
282 * Y=1.000, and Z=0.8249. This white point is commonly used for graphic
283 * arts applications, but others are often used in other applications.
284 * <p>
285 * To quantify the color characteristics of a device such as a printer
286 * or monitor, measurements of XYZ values for particular device colors
287 * are typically made. For purposes of this discussion, the term
288 * device XYZ values is used to mean the XYZ values that would be
289 * measured from device colors using current CIE recommended practices.
290 * <p>
291 * Converting between device XYZ values and the PCS XYZ values returned
292 * by this method corresponds to converting between the device's color
293 * space, as represented by CIE colorimetric values, and the PCS. There
294 * are many factors involved in this process, some of which are quite
295 * subtle. The most important, however, is the adjustment made to account
296 * for differences between the device's white point and the white point of
297 * the PCS. There are many techniques for doing this and it is the
298 * subject of much current research and controversy. Some commonly used
299 * methods are XYZ scaling, the von Kries transform, and the Bradford
300 * transform. The proper method to use depends upon each particular
301 * application.
302 * <p>
303 * The simplest method is XYZ scaling. In this method each device XYZ
304 * value is converted to a PCS XYZ value by multiplying it by the ratio
305 * of the PCS white point (D50) to the device white point.
306 * <pre>
307 *
308 * Xd, Yd, Zd are the device XYZ values
309 * Xdw, Ydw, Zdw are the device XYZ white point values
310 * Xp, Yp, Zp are the PCS XYZ values
311 * Xd50, Yd50, Zd50 are the PCS XYZ white point values
312 *
313 * Xp = Xd * (Xd50 / Xdw)
314 * Yp = Yd * (Yd50 / Ydw)
315 * Zp = Zd * (Zd50 / Zdw)
316 *
317 * </pre>
318 * <p>
319 * Conversion from the PCS to the device would be done by inverting these
320 * equations:
321 * <pre>
322 *
323 * Xd = Xp * (Xdw / Xd50)
324 * Yd = Yp * (Ydw / Yd50)
325 * Zd = Zp * (Zdw / Zd50)
326 *
327 * </pre>
328 * <p>
329 * Note that the media white point tag in an ICC profile is not the same
330 * as the device white point. The media white point tag is expressed in
331 * PCS values and is used to represent the difference between the XYZ of
332 * device illuminant and the XYZ of the device media when measured under
333 * that illuminant. The device white point is expressed as the device
334 * XYZ values corresponding to white displayed on the device. For
335 * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device
336 * will result in a measured device XYZ value of D65. This will not
337 * be the same as the media white point tag XYZ value in the ICC
338 * profile for an sRGB device.
339 * <p>
340 * @param colorvalue a float array with length of at least the number
341 * of components in this ColorSpace.
342 * @return a float array of length 3.
343 * @throws ArrayIndexOutOfBoundsException if array length is not
344 * at least the number of components in this ColorSpace.
345 */
346 public float[] toCIEXYZ(float[] colorvalue) {
347
348 if (this2xyz == null) {
349 ColorTransform[] transformList = new ColorTransform [2];
350 ICC_ColorSpace xyzCS =
351 (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ);
352 PCMM mdl = CMSManager.getModule();
353 try {
354 transformList[0] = mdl.createTransform(
355 thisProfile, ICC_Profile.icRelativeColorimetric,
356 ColorTransform.In);
357 } catch (CMMException e) {
358 transformList[0] = mdl.createTransform(
359 thisProfile, ColorTransform.Any, ColorTransform.In);
360 }
361 transformList[1] = mdl.createTransform(
362 xyzCS.getProfile(), ColorTransform.Any, ColorTransform.Out);
363 this2xyz = mdl.createTransform (transformList);
364 if (needScaleInit) {
365 setComponentScaling();
366 }
367 }
368
369 int nc = this.getNumComponents();
370 short tmp[] = new short[nc];
371 for (int i = 0; i < nc; i++) {
372 tmp[i] = (short)
373 ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f);
374 }
375 tmp = this2xyz.colorConvert(tmp, null);
376 float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f);
377 // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components
378 float[] result = new float [3];
379 for (int i = 0; i < 3; i++) {
380 result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * ALMOST_TWO;
381 }
382 return result;
383 }
384
385
386 /**
387 * Transforms a color value assumed to be in the CS_CIEXYZ conversion
388 * color space into this ColorSpace.
389 * <p>
390 * This method transforms color values using relative colorimetry,
391 * as defined by the ICC Specification. This
392 * means that the XYZ argument values taken by this method are represented
393 * relative to the D50 white point of the CS_CIEXYZ color space.
394 * This representation is useful in a two-step color conversion
395 * process in which colors are transformed from an input color
396 * space to CS_CIEXYZ and then to an output color space. The color
397 * values returned by this method are not those that would produce
398 * the XYZ value passed to the method when measured by a colorimeter.
399 * If you have XYZ values corresponding to measurements made using
400 * current CIE recommended practices, they must be converted to D50
401 * relative values before being passed to this method.
402 * The paragraphs below explain this in more detail.
403 * <p>
404 * The ICC standard uses a device independent color space (DICS) as the
405 * mechanism for converting color from one device to another device. In
406 * this architecture, colors are converted from the source device's color
407 * space to the ICC DICS and then from the ICC DICS to the destination
408 * device's color space. The ICC standard defines device profiles which
409 * contain transforms which will convert between a device's color space
410 * and the ICC DICS. The overall conversion of colors from a source
411 * device to colors of a destination device is done by connecting the
412 * device-to-DICS transform of the profile for the source device to the
413 * DICS-to-device transform of the profile for the destination device.
414 * For this reason, the ICC DICS is commonly referred to as the profile
415 * connection space (PCS). The color space used in the methods
416 * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC
417 * Specification. This is also the color space represented by
418 * ColorSpace.CS_CIEXYZ.
419 * <p>
420 * The XYZ values of a color are often represented as relative to some
421 * white point, so the actual meaning of the XYZ values cannot be known
422 * without knowing the white point of those values. This is known as
423 * relative colorimetry. The PCS uses a white point of D50, so the XYZ
424 * values of the PCS are relative to D50. For example, white in the PCS
425 * will have the XYZ values of D50, which is defined to be X=.9642,
426 * Y=1.000, and Z=0.8249. This white point is commonly used for graphic
427 * arts applications, but others are often used in other applications.
428 * <p>
429 * To quantify the color characteristics of a device such as a printer
430 * or monitor, measurements of XYZ values for particular device colors
431 * are typically made. For purposes of this discussion, the term
432 * device XYZ values is used to mean the XYZ values that would be
433 * measured from device colors using current CIE recommended practices.
434 * <p>
435 * Converting between device XYZ values and the PCS XYZ values taken as
436 * arguments by this method corresponds to converting between the device's
437 * color space, as represented by CIE colorimetric values, and the PCS.
438 * There are many factors involved in this process, some of which are quite
439 * subtle. The most important, however, is the adjustment made to account
440 * for differences between the device's white point and the white point of
441 * the PCS. There are many techniques for doing this and it is the
442 * subject of much current research and controversy. Some commonly used
443 * methods are XYZ scaling, the von Kries transform, and the Bradford
444 * transform. The proper method to use depends upon each particular
445 * application.
446 * <p>
447 * The simplest method is XYZ scaling. In this method each device XYZ
448 * value is converted to a PCS XYZ value by multiplying it by the ratio
449 * of the PCS white point (D50) to the device white point.
450 * <pre>
451 *
452 * Xd, Yd, Zd are the device XYZ values
453 * Xdw, Ydw, Zdw are the device XYZ white point values
454 * Xp, Yp, Zp are the PCS XYZ values
455 * Xd50, Yd50, Zd50 are the PCS XYZ white point values
456 *
457 * Xp = Xd * (Xd50 / Xdw)
458 * Yp = Yd * (Yd50 / Ydw)
459 * Zp = Zd * (Zd50 / Zdw)
460 *
461 * </pre>
462 * <p>
463 * Conversion from the PCS to the device would be done by inverting these
464 * equations:
465 * <pre>
466 *
467 * Xd = Xp * (Xdw / Xd50)
468 * Yd = Yp * (Ydw / Yd50)
469 * Zd = Zp * (Zdw / Zd50)
470 *
471 * </pre>
472 * <p>
473 * Note that the media white point tag in an ICC profile is not the same
474 * as the device white point. The media white point tag is expressed in
475 * PCS values and is used to represent the difference between the XYZ of
476 * device illuminant and the XYZ of the device media when measured under
477 * that illuminant. The device white point is expressed as the device
478 * XYZ values corresponding to white displayed on the device. For
479 * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device
480 * will result in a measured device XYZ value of D65. This will not
481 * be the same as the media white point tag XYZ value in the ICC
482 * profile for an sRGB device.
483 * <p>
484 * <p>
485 * @param colorvalue a float array with length of at least 3.
486 * @return a float array with length equal to the number of
487 * components in this ColorSpace.
488 * @throws ArrayIndexOutOfBoundsException if array length is not
489 * at least 3.
490 */
491 public float[] fromCIEXYZ(float[] colorvalue) {
492
493 if (xyz2this == null) {
494 ColorTransform[] transformList = new ColorTransform [2];
495 ICC_ColorSpace xyzCS =
496 (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ);
497 PCMM mdl = CMSManager.getModule();
498 transformList[0] = mdl.createTransform (
499 xyzCS.getProfile(), ColorTransform.Any, ColorTransform.In);
500 try {
501 transformList[1] = mdl.createTransform(
502 thisProfile, ICC_Profile.icRelativeColorimetric,
503 ColorTransform.Out);
504 } catch (CMMException e) {
505 transformList[1] = CMSManager.getModule().createTransform(
506 thisProfile, ColorTransform.Any, ColorTransform.Out);
507 }
508 xyz2this = mdl.createTransform(transformList);
509 if (needScaleInit) {
510 setComponentScaling();
511 }
512 }
513
514 short tmp[] = new short[3];
515 float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f);
516 float factor = 65535.0f / ALMOST_TWO;
517 // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components
518 for (int i = 0; i < 3; i++) {
519 tmp[i] = (short) ((colorvalue[i] * factor) + 0.5f);
520 }
521 tmp = xyz2this.colorConvert(tmp, null);
522 int nc = this.getNumComponents();
523 float[] result = new float [nc];
524 for (int i = 0; i < nc; i++) {
525 result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) *
526 diffMinMax[i] + minVal[i];
527 }
528 return result;
529 }
530
531 /**
532 * Returns the minimum normalized color component value for the
533 * specified component. For TYPE_XYZ spaces, this method returns
534 * minimum values of 0.0 for all components. For TYPE_Lab spaces,
535 * this method returns 0.0 for L and -128.0 for a and b components.
536 * This is consistent with the encoding of the XYZ and Lab Profile
537 * Connection Spaces in the ICC specification. For all other types, this
538 * method returns 0.0 for all components. When using an ICC_ColorSpace
539 * with a profile that requires different minimum component values,
540 * it is necessary to subclass this class and override this method.
541 * @param component The component index.
542 * @return The minimum normalized component value.
543 * @throws IllegalArgumentException if component is less than 0 or
544 * greater than numComponents - 1.
545 * @since 1.4
546 */
547 public float getMinValue(int component) {
548 if ((component < 0) || (component > this.getNumComponents() - 1)) {
549 throw new IllegalArgumentException(
550 "Component index out of range: + component");
551 }
552 return minVal[component];
553 }
554
555 /**
556 * Returns the maximum normalized color component value for the
557 * specified component. For TYPE_XYZ spaces, this method returns
558 * maximum values of 1.0 + (32767.0 / 32768.0) for all components.
559 * For TYPE_Lab spaces,
560 * this method returns 100.0 for L and 127.0 for a and b components.
561 * This is consistent with the encoding of the XYZ and Lab Profile
562 * Connection Spaces in the ICC specification. For all other types, this
563 * method returns 1.0 for all components. When using an ICC_ColorSpace
564 * with a profile that requires different maximum component values,
565 * it is necessary to subclass this class and override this method.
566 * @param component The component index.
567 * @return The maximum normalized component value.
568 * @throws IllegalArgumentException if component is less than 0 or
569 * greater than numComponents - 1.
570 * @since 1.4
571 */
572 public float getMaxValue(int component) {
573 if ((component < 0) || (component > this.getNumComponents() - 1)) {
574 throw new IllegalArgumentException(
575 "Component index out of range: + component");
576 }
577 return maxVal[component];
578 }
579
580 private void setMinMax() {
581 int nc = this.getNumComponents();
582 int type = this.getType();
583 minVal = new float[nc];
584 maxVal = new float[nc];
585 if (type == ColorSpace.TYPE_Lab) {
586 minVal[0] = 0.0f; // L
587 maxVal[0] = 100.0f;
588 minVal[1] = -128.0f; // a
589 maxVal[1] = 127.0f;
590 minVal[2] = -128.0f; // b
591 maxVal[2] = 127.0f;
592 } else if (type == ColorSpace.TYPE_XYZ) {
593 minVal[0] = minVal[1] = minVal[2] = 0.0f; // X, Y, Z
594 maxVal[0] = maxVal[1] = maxVal[2] = 1.0f + (32767.0f/ 32768.0f);
595 } else {
596 for (int i = 0; i < nc; i++) {
597 minVal[i] = 0.0f;
598 maxVal[i] = 1.0f;
599 }
600 }
601 }
602
603 private void setComponentScaling() {
604 int nc = this.getNumComponents();
605 diffMinMax = new float[nc];
606 invDiffMinMax = new float[nc];
607 for (int i = 0; i < nc; i++) {
608 minVal[i] = this.getMinValue(i); // in case getMinVal is overridden
609 maxVal[i] = this.getMaxValue(i); // in case getMaxVal is overridden
610 diffMinMax[i] = maxVal[i] - minVal[i];
611 invDiffMinMax[i] = 65535.0f / diffMinMax[i];
612 }
613 needScaleInit = false;
614 }
615
616 }