-
Notifications
You must be signed in to change notification settings - Fork 2
/
normalize.cpp
100 lines (86 loc) · 3.34 KB
/
normalize.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*
* Simpledjvu-0.1
* Based on djvulibre (http://djvu.sourceforge.net/)
* Copyright 2012, Mikhail Dektyarev <[email protected]>
*
* This file is part of Simpledjvu.
*
* Simpledjvu is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Simpledjvu is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Simpledjvu. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <djvulibre.h>
#include <normalize.h>
#include <types.h>
#include <hystogram_splitter.h>
#include <algorithm>
// in usual case, we need threshold between white and black
const byte CANONICAL_BLACK_LEVEL = MAX_COLOR;
const byte CANONICAL_WHITE_LEVEL = MIN_COLOR;
/*
* hope, that black > white
* else it can show strange picture, crash, or destroy the Earth
*/
byte canonize_level(const byte raw, const byte black, const byte white) {
if (raw >= black) {
return CANONICAL_BLACK_LEVEL;
}
if (raw <= white) {
return CANONICAL_WHITE_LEVEL;
}
return (raw - white) * (CANONICAL_BLACK_LEVEL - CANONICAL_WHITE_LEVEL) / (black - white);
}
void normalize_parts(const GBitmap &image, const GBitmap &black, const GBitmap &white, GBitmap &result) {
int width = image.columns(), height = image.rows();
result.init(height, width);
result.set_grays(256);
int32 i, j;
for (i = 0; i < height; ++i) {
for (j = 0; j < width; ++j) {
result[i][j] = canonize_level(image[i][j], black[i][j], white[i][j]);
}
}
}
/*
* example from http://www.djvuzone.org/open/doc/GBitmapScaler.html
*/
void rescale_bitmap(const GBitmap &in, GBitmap &out) {
int w = in.columns(); // Get input width
int h = in.rows(); // Get output width
int nw = out.columns();
int nh = out.rows();
GP<GBitmapScaler> gscaler = GBitmapScaler::create(w, h, nw, nh); // Creates bitmap scaler
GRect desired(0, 0, nw, nh); // Desired output = complete bitmap
GRect provided(0, 0, w, h); // Provided input = complete bitmap
gscaler->scale(provided, in, desired, out); // Rescale
}
GP<GBitmap> get_norm_image(const GBitmap &image, const int iterations) {
GP<GBitmap> current = GBitmap::create(image);
GP<GBitmap> next = GBitmap::create();
for (int i = 0; i < iterations; ++i) {
GP<GBitmap> gblack_small = GBitmap::create();
GBitmap &black_small = *gblack_small;
GP<GBitmap> gwhite_small = GBitmap::create();
GBitmap &white_small = *gwhite_small;
get_image_parts(*current, black_small, white_small, CELL_SIZE);
GP<GBitmap> gblack = GBitmap::create(image.rows(), image.columns());
GBitmap &black = *gblack;
GP<GBitmap> gwhite = GBitmap::create(image.rows(), image.columns());
GBitmap &white = *gwhite;
rescale_bitmap(black_small, black);
rescale_bitmap(white_small, white);
normalize_parts(*current, black, white, *next);
std::swap(current, next);
}
return next;
}