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