001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 *  image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause 
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 
006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 
007 * Visit http://imagingbook.com for additional details.
008 *******************************************************************************/
009
010package imagingbook.pub.color.image;
011
012/**
013 * This is a utility class with static methods for gamma correction
014 * used by LabColorSpace and LuvColorSpace color spaces.
015 * Implemented with double values for better accuracy.
016 * Should be modified to implement a a subclass of ColorSpace.
017 */
018public abstract class sRgbUtil {
019        
020        // specs according to official sRGB standard:
021        static final double s = 12.92;
022        static final double a0 = 0.0031308;
023        static final double b0 = s * a0;        // 0.040449936
024        static final double d = 0.055;
025        static final double gamma = 2.4;
026        
027    public static double gammaFwd(double lc) {  // input: linear RGB component value in [0,1]
028                return (lc <= a0) ?
029                        (lc * s) :
030                        ((1 + d) * Math.pow(lc, 1 / gamma) - d);
031    }
032    
033    public static double gammaInv(double nc) {  // input: nonlinear sRGB component value in [0,1]
034        return (nc <= b0) ?
035                (nc / s) :
036                        Math.pow((nc + d) / (1 + d), gamma);
037    }
038    
039        public static float[] sRgbToRgb(float[] srgb) { // all components in [0,1]
040                float R = (float) sRgbUtil.gammaInv(srgb[0]);
041                float G = (float) sRgbUtil.gammaInv(srgb[1]);
042                float B = (float) sRgbUtil.gammaInv(srgb[2]);
043                return new float[] { R, G, B };
044        }
045
046        public static float[] rgbToSrgb(float[] rgb) { // all components in [0,1]
047                float sR = (float) sRgbUtil.gammaFwd(rgb[0]);
048                float sG = (float) sRgbUtil.gammaFwd(rgb[1]);
049                float sB = (float) sRgbUtil.gammaFwd(rgb[2]);
050                return new float[] { sR, sG, sB };
051        }
052    
053    
054        public static void main(String[] args) {
055                for (int i = 0; i < 20; i++) {
056                        double lc = Math.random();
057                        double nc = gammaFwd(lc);
058                        System.out.format("lc = %.8f,  nc = %.8f, check = %.8f\n", lc, nc, lc-gammaInv(nc));
059                }
060                System.out.println("" + (s * a0));
061
062        }
063    
064}