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