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.histogram;
011
012public class PiecewiseLinearCdf {
013        private int K;
014        private int[] iArr;
015        private double[] pArr;
016        
017        public PiecewiseLinearCdf(int K, int[] ik, double[] Pk) {
018                this.K = K; // number of intensity values (typ. 256)
019                int N = ik.length;
020                iArr = new int[N + 2];          // array of intensity values
021                pArr = new double[N + 2];       // array of cum. distribution values
022                iArr[0] = -1; 
023                pArr[0] = 0;
024                for (int i = 0; i < N; i++) {
025                        iArr[i + 1] = ik[i];
026                        pArr[i + 1] = Pk[i];
027                }
028                iArr[N + 1] = K - 1;
029                pArr[N + 1] = 1;
030        }
031        
032        double getCdf(int i) {
033                if (i < 0)
034                        return 0;
035                else if (i >= K - 1)
036                        return 1;
037                else {
038                        int s = 0, N = iArr.length - 1;
039                        for (int j = 0; j <= N; j++) { // find s (segment index)
040                                if (iArr[j] <= i)
041                                        s = j;
042                                else
043                                        break;
044                        }
045                        return pArr[s] + (i - iArr[s])
046                                        * ((pArr[s + 1] - pArr[s]) / (iArr[s + 1] - iArr[s]));
047                }
048        }
049        
050        int getInverseCdf(double z) {
051                if (z < getCdf(0))
052                        return 0;
053                else if (z >= 1)
054                        return K - 1;
055                else {
056                        int r = 0, N = iArr.length - 1;
057                        for (int j = 0; j <= N; j++) { // find r (segment index)
058                                if (pArr[j] <= z)
059                                        r = j;
060                                else
061                                        break;
062                        }
063                        return (int) Math.round(iArr[r] + (z - pArr[r])
064                                        * ((iArr[r + 1] - iArr[r]) / (pArr[r + 1] - pArr[r])));
065                }
066        }
067        
068        // for testing only:
069        public double[] getPdf() {      
070                double[] prob = new double[K];
071                prob[0] =  getCdf(0);
072                for (int i = 1; i < K; i++) {
073                        prob[i] =  getCdf(i) - getCdf(i-1);
074                }
075                return prob;
076        }
077        
078}