1 /*
2 Scan Tailor - Interactive post-processing tool for scanned pages.
3 Copyright (C) 2007-2008 Joseph Artsimovich <joseph_a@mail.ru>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <QImage>
20 #include <algorithm>
21 #include <boost/test/auto_unit_test.hpp>
22 #include <list>
23 #include "BWColor.h"
24 #include "BinaryImage.h"
25 #include "ConnComp.h"
26 #include "ConnCompEraserExt.h"
27 #include "RasterOp.h"
28 #include "Utils.h"
29
30 namespace imageproc {
31 namespace tests {
32 using namespace utils;
33
34 BOOST_AUTO_TEST_SUITE(ConnCompEraserExtTestSuite);
35
BOOST_AUTO_TEST_CASE(test_null_image)36 BOOST_AUTO_TEST_CASE(test_null_image) {
37 ConnCompEraser eraser(BinaryImage(), CONN4);
38 BOOST_CHECK(eraser.nextConnComp().isNull());
39 }
40
checkAlignedImage(const ConnCompEraserExt & eraser,const BinaryImage & nonaligned)41 static bool checkAlignedImage(const ConnCompEraserExt& eraser, const BinaryImage& nonaligned) {
42 const BinaryImage aligned(eraser.computeConnCompImageAligned());
43 const int pad = aligned.width() - nonaligned.width();
44 if (pad < 0) {
45 return false;
46 }
47
48 BinaryImage test1(nonaligned);
49 BinaryImage empty1(test1.size());
50 empty1.fill(WHITE);
51 rasterOp<RopXor<RopSrc, RopDst>>(test1, test1.rect(), aligned, QPoint(pad, 0));
52 if (test1 != empty1) {
53 return false;
54 }
55
56 if (pad > 0) {
57 // Check that padding is white.
58 BinaryImage test2(pad, nonaligned.height());
59 BinaryImage empty2(test2.size());
60 empty2.fill(WHITE);
61 rasterOp<RopSrc>(test2, test2.rect(), aligned, QPoint(0, 0));
62 if (test2 != empty2) {
63 return false;
64 }
65 }
66
67 return true;
68 }
69
BOOST_AUTO_TEST_CASE(test_small_image)70 BOOST_AUTO_TEST_CASE(test_small_image) {
71 static const int inp[]
72 = {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0,
73 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0};
74
75 std::list<BinaryImage> c4i;
76
77 static const int out4_1[] = {1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0};
78 c4i.push_back(makeBinaryImage(out4_1, 3, 6));
79
80 static const int out4_2[] = {1, 1};
81 c4i.push_back(makeBinaryImage(out4_2, 2, 1));
82
83 static const int out4_3[] = {0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1};
84 c4i.push_back(makeBinaryImage(out4_3, 7, 2));
85
86 static const int out4_4[] = {
87 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0,
88 };
89 c4i.push_back(makeBinaryImage(out4_4, 4, 3));
90
91 static const int out4_5[] = {1};
92 c4i.push_back(makeBinaryImage(out4_5, 1, 1));
93
94 static const int out4_6[] = {1};
95 c4i.push_back(makeBinaryImage(out4_6, 1, 1));
96
97 std::list<BinaryImage> c8i;
98
99 static const int out8_1[] = {
100 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1,
101 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0,
102 };
103 c8i.push_back(makeBinaryImage(out8_1, 9, 6));
104
105 static const int out8_2[] = {
106 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
107 };
108 c8i.push_back(makeBinaryImage(out8_2, 8, 2));
109
110 BinaryImage img(makeBinaryImage(inp, 9, 8));
111
112 ConnComp cc;
113 ConnCompEraserExt eraser4(img, CONN4);
114 while (!(cc = eraser4.nextConnComp()).isNull()) {
115 const BinaryImage cc_img(eraser4.computeConnCompImage());
116 const auto it(std::find(c4i.begin(), c4i.end(), cc_img));
117 if (it != c4i.end()) {
118 BOOST_CHECK(checkAlignedImage(eraser4, cc_img));
119 c4i.erase(it);
120 } else {
121 BOOST_ERROR("Incorrect 4-connected block found.");
122 }
123 }
124 BOOST_CHECK_MESSAGE(c4i.empty(), "Not all 4-connected blocks were found.");
125
126 ConnCompEraserExt eraser8(img, CONN8);
127 while (!(cc = eraser8.nextConnComp()).isNull()) {
128 const BinaryImage cc_img(eraser8.computeConnCompImage());
129 const auto it(std::find(c8i.begin(), c8i.end(), cc_img));
130 if (it != c8i.end()) {
131 BOOST_CHECK(checkAlignedImage(eraser8, cc_img));
132 c8i.erase(it);
133 } else {
134 BOOST_ERROR("Incorrect 8-connected block found.");
135 }
136 }
137 BOOST_CHECK_MESSAGE(c8i.empty(), "Not all 8-connected blocks were found.");
138 }
139
140 BOOST_AUTO_TEST_SUITE_END();
141 } // namespace tests
142 } // namespace imageproc