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 java.lang.annotation.Native;
40 
41 import sun.java2d.cmm.PCMM;
42 import sun.java2d.cmm.CMSManager;
43 
44 
45 /**
46  * This abstract class is used to serve as a color space tag to identify the
47  * specific color space of a Color object or, via a ColorModel object,
48  * of an Image, a BufferedImage, or a GraphicsDevice.  It contains
49  * methods that transform colors in a specific color space to/from sRGB
50  * and to/from a well-defined CIEXYZ color space.
51  * <p>
52  * For purposes of the methods in this class, colors are represented as
53  * arrays of color components represented as floats in a normalized range
54  * defined by each ColorSpace.  For many ColorSpaces (e.g. sRGB), this
55  * range is 0.0 to 1.0.  However, some ColorSpaces have components whose
56  * values have a different range.  Methods are provided to inquire per
57  * component minimum and maximum normalized values.
58  * <p>
59  * Several variables are defined for purposes of referring to color
60  * space types (e.g. TYPE_RGB, TYPE_XYZ, etc.) and to refer to specific
61  * color spaces (e.g. CS_sRGB and CS_CIEXYZ).
62  * sRGB is a proposed standard RGB color space.  For more information,
63  * see <A href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
64  * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
65  * </A>.
66  * <p>
67  * The purpose of the methods to transform to/from the well-defined
68  * CIEXYZ color space is to support conversions between any two color
69  * spaces at a reasonably high degree of accuracy.  It is expected that
70  * particular implementations of subclasses of ColorSpace (e.g.
71  * ICC_ColorSpace) will support high performance conversion based on
72  * underlying platform color management systems.
73  * <p>
74  * The CS_CIEXYZ space used by the toCIEXYZ/fromCIEXYZ methods can be
75  * described as follows:
76 <pre>
77 
78 &nbsp;     CIEXYZ
79 &nbsp;     viewing illuminance: 200 lux
80 &nbsp;     viewing white point: CIE D50
81 &nbsp;     media white point: "that of a perfectly reflecting diffuser" -- D50
82 &nbsp;     media black point: 0 lux or 0 Reflectance
83 &nbsp;     flare: 1 percent
84 &nbsp;     surround: 20percent of the media white point
85 &nbsp;     media description: reflection print (i.e., RLAB, Hunt viewing media)
86 &nbsp;     note: For developers creating an ICC profile for this conversion
87 &nbsp;           space, the following is applicable.  Use a simple Von Kries
88 &nbsp;           white point adaptation folded into the 3X3 matrix parameters
89 &nbsp;           and fold the flare and surround effects into the three
90 &nbsp;           one-dimensional lookup tables (assuming one uses the minimal
91 &nbsp;           model for monitors).
92 
93 </pre>
94  *
95  * @see ICC_ColorSpace
96  */
97 
98 public abstract class ColorSpace implements java.io.Serializable {
99 
100     static final long serialVersionUID = -409452704308689724L;
101 
102     private int type;
103     private int numComponents;
104     private transient String [] compName = null;
105 
106     // Cache of singletons for the predefined color spaces.
107     private static ColorSpace sRGBspace;
108     private static ColorSpace XYZspace;
109     private static ColorSpace PYCCspace;
110     private static ColorSpace GRAYspace;
111     private static ColorSpace LINEAR_RGBspace;
112 
113     /**
114      * Any of the family of XYZ color spaces.
115      */
116     @Native public static final int TYPE_XYZ = 0;
117 
118     /**
119      * Any of the family of Lab color spaces.
120      */
121     @Native public static final int TYPE_Lab = 1;
122 
123     /**
124      * Any of the family of Luv color spaces.
125      */
126     @Native public static final int TYPE_Luv = 2;
127 
128     /**
129      * Any of the family of YCbCr color spaces.
130      */
131     @Native public static final int TYPE_YCbCr = 3;
132 
133     /**
134      * Any of the family of Yxy color spaces.
135      */
136     @Native public static final int TYPE_Yxy = 4;
137 
138     /**
139      * Any of the family of RGB color spaces.
140      */
141     @Native public static final int TYPE_RGB = 5;
142 
143     /**
144      * Any of the family of GRAY color spaces.
145      */
146     @Native public static final int TYPE_GRAY = 6;
147 
148     /**
149      * Any of the family of HSV color spaces.
150      */
151     @Native public static final int TYPE_HSV = 7;
152 
153     /**
154      * Any of the family of HLS color spaces.
155      */
156     @Native public static final int TYPE_HLS = 8;
157 
158     /**
159      * Any of the family of CMYK color spaces.
160      */
161     @Native public static final int TYPE_CMYK = 9;
162 
163     /**
164      * Any of the family of CMY color spaces.
165      */
166     @Native public static final int TYPE_CMY = 11;
167 
168     /**
169      * Generic 2 component color spaces.
170      */
171     @Native public static final int TYPE_2CLR = 12;
172 
173     /**
174      * Generic 3 component color spaces.
175      */
176     @Native public static final int TYPE_3CLR = 13;
177 
178     /**
179      * Generic 4 component color spaces.
180      */
181     @Native public static final int TYPE_4CLR = 14;
182 
183     /**
184      * Generic 5 component color spaces.
185      */
186     @Native public static final int TYPE_5CLR = 15;
187 
188     /**
189      * Generic 6 component color spaces.
190      */
191     @Native public static final int TYPE_6CLR = 16;
192 
193     /**
194      * Generic 7 component color spaces.
195      */
196     @Native public static final int TYPE_7CLR = 17;
197 
198     /**
199      * Generic 8 component color spaces.
200      */
201     @Native public static final int TYPE_8CLR = 18;
202 
203     /**
204      * Generic 9 component color spaces.
205      */
206     @Native public static final int TYPE_9CLR = 19;
207 
208     /**
209      * Generic 10 component color spaces.
210      */
211     @Native public static final int TYPE_ACLR = 20;
212 
213     /**
214      * Generic 11 component color spaces.
215      */
216     @Native public static final int TYPE_BCLR = 21;
217 
218     /**
219      * Generic 12 component color spaces.
220      */
221     @Native public static final int TYPE_CCLR = 22;
222 
223     /**
224      * Generic 13 component color spaces.
225      */
226     @Native public static final int TYPE_DCLR = 23;
227 
228     /**
229      * Generic 14 component color spaces.
230      */
231     @Native public static final int TYPE_ECLR = 24;
232 
233     /**
234      * Generic 15 component color spaces.
235      */
236     @Native public static final int TYPE_FCLR = 25;
237 
238     /**
239      * The sRGB color space defined at
240      * <A href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
241      * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
242      * </A>.
243      */
244     @Native public static final int CS_sRGB = 1000;
245 
246     /**
247      * A built-in linear RGB color space.  This space is based on the
248      * same RGB primaries as CS_sRGB, but has a linear tone reproduction curve.
249      */
250     @Native public static final int CS_LINEAR_RGB = 1004;
251 
252     /**
253      * The CIEXYZ conversion color space defined above.
254      */
255     @Native public static final int CS_CIEXYZ = 1001;
256 
257     /**
258      * The Photo YCC conversion color space.
259      */
260     @Native public static final int CS_PYCC = 1002;
261 
262     /**
263      * The built-in linear gray scale color space.
264      */
265     @Native public static final int CS_GRAY = 1003;
266 
267 
268     /**
269      * Constructs a ColorSpace object given a color space type
270      * and the number of components.
271      * @param type one of the {@code ColorSpace} type constants
272      * @param numcomponents the number of components in the color space
273      */
ColorSpace(int type, int numcomponents)274     protected ColorSpace (int type, int numcomponents) {
275         this.type = type;
276         this.numComponents = numcomponents;
277     }
278 
279 
280     /**
281      * Returns a ColorSpace representing one of the specific
282      * predefined color spaces.
283      * @param colorspace a specific color space identified by one of
284      *        the predefined class constants (e.g. CS_sRGB, CS_LINEAR_RGB,
285      *        CS_CIEXYZ, CS_GRAY, or CS_PYCC)
286      * @return the requested {@code ColorSpace} object
287      */
288     // NOTE: This method may be called by privileged threads.
289     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
getInstance(int colorspace)290     public static ColorSpace getInstance (int colorspace)
291     {
292     ColorSpace    theColorSpace;
293 
294         switch (colorspace) {
295         case CS_sRGB:
296             synchronized(ColorSpace.class) {
297                 if (sRGBspace == null) {
298                     ICC_Profile theProfile = ICC_Profile.getInstance (CS_sRGB);
299                     sRGBspace = new ICC_ColorSpace (theProfile);
300                 }
301 
302                 theColorSpace = sRGBspace;
303             }
304             break;
305 
306         case CS_CIEXYZ:
307             synchronized(ColorSpace.class) {
308                 if (XYZspace == null) {
309                     ICC_Profile theProfile =
310                         ICC_Profile.getInstance (CS_CIEXYZ);
311                     XYZspace = new ICC_ColorSpace (theProfile);
312                 }
313 
314                 theColorSpace = XYZspace;
315             }
316             break;
317 
318         case CS_PYCC:
319             synchronized(ColorSpace.class) {
320                 if (PYCCspace == null) {
321                     ICC_Profile theProfile = ICC_Profile.getInstance (CS_PYCC);
322                     PYCCspace = new ICC_ColorSpace (theProfile);
323                 }
324 
325                 theColorSpace = PYCCspace;
326             }
327             break;
328 
329 
330         case CS_GRAY:
331             synchronized(ColorSpace.class) {
332                 if (GRAYspace == null) {
333                     ICC_Profile theProfile = ICC_Profile.getInstance (CS_GRAY);
334                     GRAYspace = new ICC_ColorSpace (theProfile);
335                     /* to allow access from java.awt.ColorModel */
336                     CMSManager.GRAYspace = GRAYspace;
337                 }
338 
339                 theColorSpace = GRAYspace;
340             }
341             break;
342 
343 
344         case CS_LINEAR_RGB:
345             synchronized(ColorSpace.class) {
346                 if (LINEAR_RGBspace == null) {
347                     ICC_Profile theProfile =
348                         ICC_Profile.getInstance(CS_LINEAR_RGB);
349                     LINEAR_RGBspace = new ICC_ColorSpace (theProfile);
350                     /* to allow access from java.awt.ColorModel */
351                     CMSManager.LINEAR_RGBspace = LINEAR_RGBspace;
352                 }
353 
354                 theColorSpace = LINEAR_RGBspace;
355             }
356             break;
357 
358 
359         default:
360             throw new IllegalArgumentException ("Unknown color space");
361         }
362 
363         return theColorSpace;
364     }
365 
366 
367     /**
368      * Returns true if the ColorSpace is CS_sRGB.
369      * @return {@code true} if this is a {@code CS_sRGB} color
370      *         space, {@code false} if it is not
371      */
isCS_sRGB()372     public boolean isCS_sRGB () {
373         /* REMIND - make sure we know sRGBspace exists already */
374         return (this == sRGBspace);
375     }
376 
377     /**
378      * Transforms a color value assumed to be in this ColorSpace
379      * into a value in the default CS_sRGB color space.
380      * <p>
381      * This method transforms color values using algorithms designed
382      * to produce the best perceptual match between input and output
383      * colors.  In order to do colorimetric conversion of color values,
384      * you should use the {@code toCIEXYZ}
385      * method of this color space to first convert from the input
386      * color space to the CS_CIEXYZ color space, and then use the
387      * {@code fromCIEXYZ} method of the CS_sRGB color space to
388      * convert from CS_CIEXYZ to the output color space.
389      * See {@link #toCIEXYZ(float[]) toCIEXYZ} and
390      * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
391      *
392      * @param colorvalue a float array with length of at least the number
393      *        of components in this ColorSpace
394      * @return a float array of length 3
395      * @throws ArrayIndexOutOfBoundsException if array length is not
396      *         at least the number of components in this ColorSpace
397      */
toRGB(float[] colorvalue)398     public abstract float[] toRGB(float[] colorvalue);
399 
400 
401     /**
402      * Transforms a color value assumed to be in the default CS_sRGB
403      * color space into this ColorSpace.
404      * <p>
405      * This method transforms color values using algorithms designed
406      * to produce the best perceptual match between input and output
407      * colors.  In order to do colorimetric conversion of color values,
408      * you should use the {@code toCIEXYZ}
409      * method of the CS_sRGB color space to first convert from the input
410      * color space to the CS_CIEXYZ color space, and then use the
411      * {@code fromCIEXYZ} method of this color space to
412      * convert from CS_CIEXYZ to the output color space.
413      * See {@link #toCIEXYZ(float[]) toCIEXYZ} and
414      * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information.
415      *
416      * @param rgbvalue a float array with length of at least 3
417      * @return a float array with length equal to the number of
418      *         components in this ColorSpace
419      * @throws ArrayIndexOutOfBoundsException if array length is not
420      *         at least 3
421      */
fromRGB(float[] rgbvalue)422     public abstract float[] fromRGB(float[] rgbvalue);
423 
424 
425     /**
426      * Transforms a color value assumed to be in this ColorSpace
427      * into the CS_CIEXYZ conversion color space.
428      * <p>
429      * This method transforms color values using relative colorimetry,
430      * as defined by the International Color Consortium standard.  This
431      * means that the XYZ values returned by this method are represented
432      * relative to the D50 white point of the CS_CIEXYZ color space.
433      * This representation is useful in a two-step color conversion
434      * process in which colors are transformed from an input color
435      * space to CS_CIEXYZ and then to an output color space.  This
436      * representation is not the same as the XYZ values that would
437      * be measured from the given color value by a colorimeter.
438      * A further transformation is necessary to compute the XYZ values
439      * that would be measured using current CIE recommended practices.
440      * See the {@link ICC_ColorSpace#toCIEXYZ(float[]) toCIEXYZ} method of
441      * {@code ICC_ColorSpace} for further information.
442      *
443      * @param colorvalue a float array with length of at least the number
444      *        of components in this ColorSpace
445      * @return a float array of length 3
446      * @throws ArrayIndexOutOfBoundsException if array length is not
447      *         at least the number of components in this ColorSpace.
448      */
toCIEXYZ(float[] colorvalue)449     public abstract float[] toCIEXYZ(float[] colorvalue);
450 
451 
452     /**
453      * Transforms a color value assumed to be in the CS_CIEXYZ conversion
454      * color space into this ColorSpace.
455      * <p>
456      * This method transforms color values using relative colorimetry,
457      * as defined by the International Color Consortium standard.  This
458      * means that the XYZ argument values taken by this method are represented
459      * relative to the D50 white point of the CS_CIEXYZ color space.
460      * This representation is useful in a two-step color conversion
461      * process in which colors are transformed from an input color
462      * space to CS_CIEXYZ and then to an output color space.  The color
463      * values returned by this method are not those that would produce
464      * the XYZ value passed to the method when measured by a colorimeter.
465      * If you have XYZ values corresponding to measurements made using
466      * current CIE recommended practices, they must be converted to D50
467      * relative values before being passed to this method.
468      * See the {@link ICC_ColorSpace#fromCIEXYZ(float[]) fromCIEXYZ} method of
469      * {@code ICC_ColorSpace} for further information.
470      *
471      * @param colorvalue a float array with length of at least 3
472      * @return a float array with length equal to the number of
473      *         components in this ColorSpace
474      * @throws ArrayIndexOutOfBoundsException if array length is not
475      *         at least 3
476      */
fromCIEXYZ(float[] colorvalue)477     public abstract float[] fromCIEXYZ(float[] colorvalue);
478 
479     /**
480      * Returns the color space type of this ColorSpace (for example
481      * TYPE_RGB, TYPE_XYZ, ...).  The type defines the
482      * number of components of the color space and the interpretation,
483      * e.g. TYPE_RGB identifies a color space with three components - red,
484      * green, and blue.  It does not define the particular color
485      * characteristics of the space, e.g. the chromaticities of the
486      * primaries.
487      *
488      * @return the type constant that represents the type of this
489      *         {@code ColorSpace}
490      */
getType()491     public int getType() {
492         return type;
493     }
494 
495     /**
496      * Returns the number of components of this ColorSpace.
497      * @return The number of components in this {@code ColorSpace}.
498      */
getNumComponents()499     public int getNumComponents() {
500         return numComponents;
501     }
502 
503     /**
504      * Returns the name of the component given the component index.
505      *
506      * @param idx the component index
507      * @return the name of the component at the specified index
508      * @throws IllegalArgumentException if {@code idx} is
509      *         less than 0 or greater than numComponents - 1
510      */
getName(int idx)511     public String getName (int idx) {
512         /* REMIND - handle common cases here */
513         if ((idx < 0) || (idx > numComponents - 1)) {
514             throw new IllegalArgumentException(
515                 "Component index out of range: " + idx);
516         }
517 
518         if (compName == null) {
519             switch (type) {
520                 case ColorSpace.TYPE_XYZ:
521                     compName = new String[] {"X", "Y", "Z"};
522                     break;
523                 case ColorSpace.TYPE_Lab:
524                     compName = new String[] {"L", "a", "b"};
525                     break;
526                 case ColorSpace.TYPE_Luv:
527                     compName = new String[] {"L", "u", "v"};
528                     break;
529                 case ColorSpace.TYPE_YCbCr:
530                     compName = new String[] {"Y", "Cb", "Cr"};
531                     break;
532                 case ColorSpace.TYPE_Yxy:
533                     compName = new String[] {"Y", "x", "y"};
534                     break;
535                 case ColorSpace.TYPE_RGB:
536                     compName = new String[] {"Red", "Green", "Blue"};
537                     break;
538                 case ColorSpace.TYPE_GRAY:
539                     compName = new String[] {"Gray"};
540                     break;
541                 case ColorSpace.TYPE_HSV:
542                     compName = new String[] {"Hue", "Saturation", "Value"};
543                     break;
544                 case ColorSpace.TYPE_HLS:
545                     compName = new String[] {"Hue", "Lightness",
546                                              "Saturation"};
547                     break;
548                 case ColorSpace.TYPE_CMYK:
549                     compName = new String[] {"Cyan", "Magenta", "Yellow",
550                                              "Black"};
551                     break;
552                 case ColorSpace.TYPE_CMY:
553                     compName = new String[] {"Cyan", "Magenta", "Yellow"};
554                     break;
555                 default:
556                     String [] tmp = new String[numComponents];
557                     for (int i = 0; i < tmp.length; i++) {
558                         tmp[i] = "Unnamed color component(" + i + ")";
559                     }
560                     compName = tmp;
561             }
562         }
563         return compName[idx];
564     }
565 
566     /**
567      * Returns the minimum normalized color component value for the
568      * specified component.  The default implementation in this abstract
569      * class returns 0.0 for all components.  Subclasses should override
570      * this method if necessary.
571      *
572      * @param component the component index
573      * @return the minimum normalized component value
574      * @throws IllegalArgumentException if component is less than 0 or
575      *         greater than numComponents - 1
576      * @since 1.4
577      */
getMinValue(int component)578     public float getMinValue(int component) {
579         if ((component < 0) || (component > numComponents - 1)) {
580             throw new IllegalArgumentException(
581                 "Component index out of range: " + component);
582         }
583         return 0.0f;
584     }
585 
586     /**
587      * Returns the maximum normalized color component value for the
588      * specified component.  The default implementation in this abstract
589      * class returns 1.0 for all components.  Subclasses should override
590      * this method if necessary.
591      *
592      * @param component the component index
593      * @return the maximum normalized component value
594      * @throws IllegalArgumentException if component is less than 0 or
595      *         greater than numComponents - 1
596      * @since 1.4
597      */
getMaxValue(int component)598     public float getMaxValue(int component) {
599         if ((component < 0) || (component > numComponents - 1)) {
600             throw new IllegalArgumentException(
601                 "Component index out of range: " + component);
602         }
603         return 1.0f;
604     }
605 
606     /* Returns true if cspace is the XYZspace.
607      */
isCS_CIEXYZ(ColorSpace cspace)608     static boolean isCS_CIEXYZ(ColorSpace cspace) {
609         return (cspace == XYZspace);
610     }
611 }
612