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 }