198 if (blockRadius < 0) {
199 std::cerr <<
"Error: blockRadius < 0!" << std::endl;
203 if (bins < 0 || bins > 256) {
204 std::cerr <<
"Error: (bins < 0 || bins > 256)!" << std::endl;
208 if ((
unsigned int)(2 * blockRadius + 1) > I1.
getWidth() || (
unsigned int)(2 * blockRadius + 1) > I1.
getHeight()) {
209 std::cerr <<
"Error: (unsigned int) (2*blockRadius+1) > I1.getWidth() || "
210 "(unsigned int) (2*blockRadius+1) > I1.getHeight()!"
218 int blockSize = 2 * blockRadius + 1;
219 int limit = (int)(slope * blockSize * blockSize / bins + 0.5);
226 int cm = I1.
getWidth() - nc * blockSize;
232 for (
int i = 0; i < nc; ++i) {
233 cs[i] = i * blockSize + blockRadius + 1;
239 for (
int i = 0; i < nc; ++i) {
240 cs[i] = i * blockSize + blockRadius + 1;
242 cs[nc] = I1.
getWidth() - blockRadius - 1;
247 cs[0] = blockRadius + 1;
248 for (
int i = 0; i < nc; ++i) {
249 cs[i + 1] = i * blockSize + blockRadius + 1 + cm / 2;
251 cs[nc + 1] = I1.
getWidth() - blockRadius - 1;
254 int rm = I1.
getHeight() - nr * blockSize;
259 rs.resize((
size_t)nr);
260 for (
int i = 0; i < nr; ++i) {
261 rs[i] = i * blockSize + blockRadius + 1;
266 rs.resize((
size_t)(nr + 1));
267 for (
int i = 0; i < nr; ++i) {
268 rs[i] = i * blockSize + blockRadius + 1;
270 rs[nr] = I1.
getHeight() - blockRadius - 1;
274 rs.resize((
size_t)(nr + 2));
275 rs[0] = blockRadius + 1;
276 for (
int i = 0; i < nr; ++i) {
277 rs[i + 1] = i * blockSize + blockRadius + 1 + rm / 2;
279 rs[nr + 1] = I1.
getHeight() - blockRadius - 1;
282 std::vector<int> hist((
size_t)(bins + 1));
283 std::vector<int> cdfs((
size_t)(bins + 1));
284 std::vector<float> tl;
285 std::vector<float> tr;
286 std::vector<float> br;
287 std::vector<float> bl;
289 for (
int r = 0; r <= (int)rs.size(); ++r) {
290 int r0 = std::max(0, r - 1);
291 int r1 = std::min((
int)rs.size() - 1, r);
292 int dr = rs[r1] - rs[r0];
294 createHistogram(blockRadius, bins, cs[0], rs[r0], I1, hist);
295 tr = createTransfer(hist, limit, cdfs);
300 createHistogram(blockRadius, bins, cs[0], rs[r1], I1, hist);
301 br = createTransfer(hist, limit, cdfs);
304 int yMin = (r == 0 ? 0 : rs[r0]);
305 int yMax = (r < (int)rs.size() ? rs[r1] : I1.
getHeight());
307 for (
int c = 0; c <= (int)cs.size(); ++c) {
308 int c0 = std::max(0, c - 1);
309 int c1 = std::min((
int)cs.size() - 1, c);
310 int dc = cs[c1] - cs[c0];
316 createHistogram(blockRadius, bins, cs[c1], rs[r0], I1, hist);
317 tr = createTransfer(hist, limit, cdfs);
322 createHistogram(blockRadius, bins, cs[c1], rs[r1], I1, hist);
323 br = createTransfer(hist, limit, cdfs);
327 int xMin = (c == 0 ? 0 : cs[c0]);
328 int xMax = (c < (int)cs.size() ? cs[c1] : I1.
getWidth());
329 for (
int y = yMin; y < yMax; ++y) {
330 float wy = (float)(rs[r1] - y) / dr;
332 for (
int x = xMin; x < xMax; ++x) {
333 float wx = (float)(cs[c1] - x) / dc;
334 int v = fastRound(I1[y][x] / 255.0f * bins);
339 float t0 = 0.0f, t1 = 0.0f;
346 t0 = wx * t00 + (1.0f - wx) * t01;
347 t1 = wx * t10 + (1.0f - wx) * t11;
350 float t = (r0 == r1) ? t0 : wy * t0 + (1.0f - wy) * t1;
351 I2[y][x] = std::max(0, std::min(255, fastRound(t * 255.0f)));
358 std::vector<int> hist(bins + 1), prev_hist(bins + 1);
359 std::vector<int> clippedHist(bins + 1);
363 int xMax0 = std::min((
int)I1.
getWidth(), blockRadius);
365 for (
int y = 0; y < (int)I1.
getHeight(); y++) {
366 int yMin = std::max(0, y - (
int)blockRadius);
367 int yMax = std::min((
int)I1.
getHeight(), y + blockRadius + 1);
371 std::fill(hist.begin(), hist.end(), 0);
373 for (
int yi = yMin; yi < yMax; yi++) {
374 for (
int xi = xMin0; xi < xMax0; xi++) {
375 ++hist[fastRound(I1[yi][xi] / 255.0f * bins)];
382 for (
int yi = yMin; yi < yMax; yi++) {
383 for (
int xi = xMin0; xi < xMax0; xi++) {
384 ++hist[fastRound(I1[yi][xi] / 255.0f * bins)];
392 int yMin1 = yMin - 1;
394 for (
int xi = xMin0; xi < xMax0; xi++) {
395 --hist[fastRound(I1[yMin1][xi] / 255.0f * bins)];
399 if (y + blockRadius < (
int)I1.
getHeight()) {
400 int yMax1 = yMax - 1;
402 for (
int xi = xMin0; xi < xMax0; xi++) {
403 ++hist[fastRound(I1[yMax1][xi] / 255.0f * bins)];
410 for (
int x = 0; x < (int)I1.
getWidth(); x++) {
411 int xMin = std::max(0, x - (
int)blockRadius);
412 int xMax = x + blockRadius + 1;
415 int xMin1 = xMin - 1;
417 for (
int yi = yMin; yi < yMax; yi++) {
418 --hist[fastRound(I1[yi][xMin1] / 255.0f * bins)];
423 int xMax1 = xMax - 1;
425 for (
int yi = yMin; yi < yMax; yi++) {
426 ++hist[fastRound(I1[yi][xMax1] / 255.0f * bins)];
430 int v = fastRound(I1[y][x] / 255.0f * bins);
431 int w = std::min((
int)I1.
getWidth(), xMax) - xMin;
433 int limit = (int)(slope * n / bins + 0.5f);
434 I2[y][x] = fastRound(transferValue(v, hist, clippedHist, limit) * 255.0f);