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