jdk/src/share/classes/java/awt/color/ICC_ColorSpace.java
changeset 539 7952521a4ad3
child 715 f16baef3a20e
equal deleted inserted replaced
538:d95bc71a5732 539:7952521a4ad3
       
     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 }