001    /*
002    *
003    
004    Licensed under the Apache License, Version 2.0 (the "License");
005    you may not use this file except in compliance with the License.
006    You may obtain a copy of the License at
007    
008       http://www.apache.org/licenses/LICENSE-2.0
009    
010    Unless required by applicable law or agreed to in writing, software
011    distributed under the License is distributed on an "AS IS" BASIS,
012    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013    See the License for the specific language governing permissions and
014    limitations under the License.
015    */
016    
017    package railo.runtime.img.filter;
018    
019    /**
020     * An image histogram.
021     */
022    public class Histogram {
023    
024            public static final int RED = 0;
025            public static final int GREEN = 1;
026            public static final int BLUE = 2;
027            public static final int GRAY = 3;
028    
029            protected int[][] histogram;
030            protected int numSamples;
031            protected int[] minValue;
032            protected int[] maxValue;
033            protected int[] minFrequency;
034            protected int[] maxFrequency;
035            protected float[] mean;
036            protected boolean isGray;
037    
038            public Histogram() {
039                    histogram = null;
040                    numSamples = 0;
041                    isGray = true;
042                    minValue = null;
043                    maxValue = null;
044                    minFrequency = null;
045                    maxFrequency = null;
046                    mean = null;
047            }
048    
049            public Histogram(int[] pixels, int w, int h, int offset, int stride) {
050                    histogram = new int[3][256];
051                    minValue = new int[4];
052                    maxValue = new int[4];
053                    minFrequency = new int[3];
054                    maxFrequency = new int[3];
055                    mean = new float[3];
056    
057                    numSamples = w*h;
058                    isGray = true;
059    
060                    int index = 0;
061                    for (int y = 0; y < h; y++) {
062                            index = offset+y*stride;
063                            for (int x = 0; x < w; x++) {
064                                    int rgb = pixels[index++];
065                                    int r = (rgb >> 16) & 0xff;
066                                    int g = (rgb >> 8) & 0xff;
067                                    int b = rgb & 0xff;
068                                    histogram[RED][r]++;
069                                    histogram[GREEN][g]++;
070                                    histogram[BLUE][b]++;
071                            }
072                    }
073    
074                    for (int i = 0; i < 256; i++) {
075                            if (histogram[RED][i] != histogram[GREEN][i] || histogram[GREEN][i] != histogram[BLUE][i]) {
076                                    isGray = false;
077                                    break;
078                            }
079                    }
080    
081                    for (int i = 0; i < 3; i++) {
082                            for (int j = 0; j < 256; j++) {
083                                    if (histogram[i][j] > 0) {
084                                            minValue[i] = j;
085                                            break;
086                                    }
087                            }
088    
089                            for (int j = 255; j >= 0; j--) {
090                                    if (histogram[i][j] > 0) {
091                                            maxValue[i] = j;
092                                            break;
093                                    }
094                            }
095    
096                            minFrequency[i] = Integer.MAX_VALUE;
097                            maxFrequency[i] = 0;
098                            for (int j = 0; j < 256; j++) {
099                                    minFrequency[i] = Math.min(minFrequency[i], histogram[i][j]);
100                                    maxFrequency[i] = Math.max(maxFrequency[i], histogram[i][j]);
101                                    mean[i] += (j*histogram[i][j]);
102                            }
103                            mean[i] /= numSamples;
104                    }
105                    minValue[GRAY] = Math.min(Math.min(minValue[RED], minValue[GREEN]), minValue[BLUE]);
106                    maxValue[GRAY] = Math.max(Math.max(maxValue[RED], maxValue[GREEN]), maxValue[BLUE]);
107            }
108    
109            public boolean isGray() {
110                    return isGray;
111            }
112    
113            public int getNumSamples() {
114                    return numSamples;
115            }
116    
117            public int getFrequency(int value) {
118                    if (numSamples > 0 && isGray && value >= 0 && value <= 255)
119                            return histogram[0][value];
120                    return -1;
121            }
122    
123            public int getFrequency(int channel, int value) {
124                    if (numSamples < 1 || channel < 0 || channel > 2 ||
125                     value < 0 || value > 255)
126                            return -1;
127                    return histogram[channel][value];
128            }
129    
130            public int getMinFrequency() {
131                    if (numSamples > 0 && isGray)
132                            return minFrequency[0];
133                    return -1;
134            }
135    
136            public int getMinFrequency(int channel) {
137                    if (numSamples < 1 || channel < 0 || channel > 2)
138                            return -1;
139                    return minFrequency[channel];
140            }
141    
142    
143            public int getMaxFrequency() {
144                    if (numSamples > 0 && isGray)
145                            return maxFrequency[0];
146                    return -1;
147            }
148    
149            public int getMaxFrequency(int channel) {
150                    if (numSamples < 1 || channel < 0 || channel > 2)
151                            return -1;
152                    return maxFrequency[channel];
153            }
154    
155    
156            public int getMinValue() {
157                    if (numSamples > 0 && isGray)
158                            return minValue[0];
159                    return -1;
160            }
161    
162            public int getMinValue(int channel) {
163                    return minValue[channel];
164            }
165    
166            public int getMaxValue() {
167                    if (numSamples > 0 && isGray)
168                            return maxValue[0];
169                    return -1;
170            }
171    
172            public int getMaxValue(int channel) {
173                    return maxValue[channel];
174            }
175    
176            public float getMeanValue() {
177                    if (numSamples > 0 && isGray)
178                            return mean[0];
179                    return -1.0F;
180            }
181    
182            public float getMeanValue(int channel) {
183                    if (numSamples > 0 && RED <= channel && channel <= BLUE)
184                            return mean[channel];
185                    return -1.0F;
186            }
187    
188    
189    }