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