View Javadoc
1   /*
2    * Copyright (c) 1997, 2013, 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     * 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      * @param colorvalue a float array with length of at least 3.
485      * @return a float array with length equal to the number of
486      *         components in this ColorSpace.
487      * @throws ArrayIndexOutOfBoundsException if array length is not
488      * at least 3.
489      */
490     public float[]    fromCIEXYZ(float[] colorvalue) {
491 
492         if (xyz2this == null) {
493             ColorTransform[] transformList = new ColorTransform [2];
494             ICC_ColorSpace xyzCS =
495                 (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ);
496             PCMM mdl = CMSManager.getModule();
497             transformList[0] = mdl.createTransform (
498                 xyzCS.getProfile(), ColorTransform.Any, ColorTransform.In);
499             try {
500                 transformList[1] = mdl.createTransform(
501                     thisProfile, ICC_Profile.icRelativeColorimetric,
502                     ColorTransform.Out);
503             } catch (CMMException e) {
504                 transformList[1] = CMSManager.getModule().createTransform(
505                 thisProfile, ColorTransform.Any, ColorTransform.Out);
506             }
507             xyz2this = mdl.createTransform(transformList);
508             if (needScaleInit) {
509                 setComponentScaling();
510             }
511         }
512 
513         short tmp[] = new short[3];
514         float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f);
515         float factor = 65535.0f / ALMOST_TWO;
516         // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components
517         for (int i = 0; i < 3; i++) {
518             tmp[i] = (short) ((colorvalue[i] * factor) + 0.5f);
519         }
520         tmp = xyz2this.colorConvert(tmp, null);
521         int nc = this.getNumComponents();
522         float[] result = new float [nc];
523         for (int i = 0; i < nc; i++) {
524             result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) *
525                         diffMinMax[i] + minVal[i];
526         }
527         return result;
528     }
529 
530     /**
531      * Returns the minimum normalized color component value for the
532      * specified component.  For TYPE_XYZ spaces, this method returns
533      * minimum values of 0.0 for all components.  For TYPE_Lab spaces,
534      * this method returns 0.0 for L and -128.0 for a and b components.
535      * This is consistent with the encoding of the XYZ and Lab Profile
536      * Connection Spaces in the ICC specification.  For all other types, this
537      * method returns 0.0 for all components.  When using an ICC_ColorSpace
538      * with a profile that requires different minimum component values,
539      * it is necessary to subclass this class and override this method.
540      * @param component The component index.
541      * @return The minimum normalized component value.
542      * @throws IllegalArgumentException if component is less than 0 or
543      *         greater than numComponents - 1.
544      * @since 1.4
545      */
546     public float getMinValue(int component) {
547         if ((component < 0) || (component > this.getNumComponents() - 1)) {
548             throw new IllegalArgumentException(
549                 "Component index out of range: + component");
550         }
551         return minVal[component];
552     }
553 
554     /**
555      * Returns the maximum normalized color component value for the
556      * specified component.  For TYPE_XYZ spaces, this method returns
557      * maximum values of 1.0 + (32767.0 / 32768.0) for all components.
558      * For TYPE_Lab spaces,
559      * this method returns 100.0 for L and 127.0 for a and b components.
560      * This is consistent with the encoding of the XYZ and Lab Profile
561      * Connection Spaces in the ICC specification.  For all other types, this
562      * method returns 1.0 for all components.  When using an ICC_ColorSpace
563      * with a profile that requires different maximum component values,
564      * it is necessary to subclass this class and override this method.
565      * @param component The component index.
566      * @return The maximum normalized component value.
567      * @throws IllegalArgumentException if component is less than 0 or
568      *         greater than numComponents - 1.
569      * @since 1.4
570      */
571     public float getMaxValue(int component) {
572         if ((component < 0) || (component > this.getNumComponents() - 1)) {
573             throw new IllegalArgumentException(
574                 "Component index out of range: + component");
575         }
576         return maxVal[component];
577     }
578 
579     private void setMinMax() {
580         int nc = this.getNumComponents();
581         int type = this.getType();
582         minVal = new float[nc];
583         maxVal = new float[nc];
584         if (type == ColorSpace.TYPE_Lab) {
585             minVal[0] = 0.0f;    // L
586             maxVal[0] = 100.0f;
587             minVal[1] = -128.0f; // a
588             maxVal[1] = 127.0f;
589             minVal[2] = -128.0f; // b
590             maxVal[2] = 127.0f;
591         } else if (type == ColorSpace.TYPE_XYZ) {
592             minVal[0] = minVal[1] = minVal[2] = 0.0f; // X, Y, Z
593             maxVal[0] = maxVal[1] = maxVal[2] = 1.0f + (32767.0f/ 32768.0f);
594         } else {
595             for (int i = 0; i < nc; i++) {
596                 minVal[i] = 0.0f;
597                 maxVal[i] = 1.0f;
598             }
599         }
600     }
601 
602     private void setComponentScaling() {
603         int nc = this.getNumComponents();
604         diffMinMax = new float[nc];
605         invDiffMinMax = new float[nc];
606         for (int i = 0; i < nc; i++) {
607             minVal[i] = this.getMinValue(i); // in case getMinVal is overridden
608             maxVal[i] = this.getMaxValue(i); // in case getMaxVal is overridden
609             diffMinMax[i] = maxVal[i] - minVal[i];
610             invDiffMinMax[i] = 65535.0f / diffMinMax[i];
611         }
612         needScaleInit = false;
613     }
614 
615 }