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