| 173 | } |
| 174 | |
| 175 | void equalize(Image &img, bool per_channel) |
| 176 | { |
| 177 | for (int c = 0; c < (per_channel ? img.channels() : 1); c++) |
| 178 | { |
| 179 | if (c == 3) // Do not individual equalize alpha channel |
| 180 | break; |
| 181 | |
| 182 | const int nlevels = img.maxval() + 1; |
| 183 | size_t size = img.width() * img.height() * (per_channel ? 1 : img.channels()); |
| 184 | |
| 185 | // Init histogram buffer |
| 186 | int *histogram = new int[nlevels]; |
| 187 | for (int i = 0; i < nlevels; i++) |
| 188 | histogram[i] = 0; |
| 189 | |
| 190 | // Compute histogram |
| 191 | for (size_t px = 0; px < size; px++) |
| 192 | histogram[img.get(c, px)]++; |
| 193 | |
| 194 | // Cummulative histogram |
| 195 | int *cummulative_histogram = new int[nlevels]; |
| 196 | cummulative_histogram[0] = histogram[0]; |
| 197 | for (int i = 1; i < nlevels; i++) |
| 198 | cummulative_histogram[i] = histogram[i] + cummulative_histogram[i - 1]; |
| 199 | |
| 200 | // Scaling |
| 201 | int *scaling = new int[nlevels]; |
| 202 | for (int i = 0; i < nlevels; i++) |
| 203 | scaling[i] = round(cummulative_histogram[i] * (float(nlevels - 1) / size)); |
| 204 | |
| 205 | // Apply |
| 206 | for (size_t px = 0; px < size; px++) |
| 207 | img.set(c, px, img.clamp(scaling[img.get(c, px)])); |
| 208 | |
| 209 | // Cleanup |
| 210 | delete[] cummulative_histogram; |
| 211 | delete[] scaling; |
| 212 | delete[] histogram; |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | void normalize(Image &img) |
| 217 | { |
no test coverage detected