OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
Mask.cpp
Go to the documentation of this file.
5
6#include <filesystem>
7#include <regex>
8
9namespace mslang {
11 const std::vector<bool>& pixels, std::vector<unsigned int>& cache,
12 unsigned int y) const {
13 const unsigned int M = cache.size();
14 unsigned int idx = y * M;
15 for (unsigned int x = 0; x < M; ++x, ++idx) {
16 if (pixels[idx]) {
17 ++cache[x];
18 } else {
19 cache[x] = 0;
20 }
21 }
22 }
23
24 unsigned int Mask::computeArea(const Mask::IntPoint& ll, const Mask::IntPoint& ur) const {
25 if ((ur.x_m > ll.x_m) && (ur.y_m > ll.y_m)) return (ur.x_m - ll.x_m) * (ur.y_m - ll.y_m);
26
27 return 0;
28 }
29
30 std::pair<Mask::IntPoint, Mask::IntPoint> Mask::findMaximalRectangle(
31 const std::vector<bool>& pixels, unsigned int N, /* height */
32 unsigned int M /* width */) const {
33 // This algorithm was presented in
34 // http://www.drdobbs.com/database/the-maximal-rectangle-problem/184410529
35 // by David Vandevoorde, April 01, 1998
36
37 unsigned int bestArea = 0;
38 IntPoint bestLL(0, 0), bestUR(0, 0);
39 std::vector<unsigned int> cache(M, 0);
40 std::stack<std::pair<unsigned int, unsigned int> > stack;
41 for (unsigned int y = N - 1; y + 1 > 0; --y) {
42 updateCache(pixels, cache, y);
43 unsigned int height = 0;
44 for (unsigned int x = 0; x < M; ++x) {
45 if (cache[x] > height) {
46 stack.push(std::make_pair(x, height));
47 height = cache[x];
48 } else if (cache[x] < height) {
49 std::pair<unsigned int, unsigned int> tmp;
50 do {
51 tmp = stack.top();
52 stack.pop();
53 if (x > tmp.first && height * (x - tmp.first) > bestArea) {
54 bestLL.x_m = tmp.first;
55 bestLL.y_m = y;
56 bestUR.x_m = x;
57 bestUR.y_m = y + height;
58 bestArea = height * (x - tmp.first);
59 }
60 height = tmp.second;
61 } while (!stack.empty() && cache[x] < height);
62 height = cache[x];
63 if (height != 0) {
64 stack.push(std::make_pair(tmp.first, height));
65 }
66 }
67 }
68
69 if (!stack.empty()) {
70 std::pair<unsigned int, unsigned int> tmp = stack.top();
71 stack.pop();
72 if (M > tmp.first && height * (M - tmp.first) > bestArea) {
73 bestLL.x_m = tmp.first;
74 bestLL.y_m = y;
75 bestUR.x_m = M;
76 bestUR.y_m = y + height;
77 bestArea = height * (M - tmp.first);
78 }
79 }
80 }
81
82 return std::make_pair(bestLL, bestUR);
83 }
84
85 std::vector<Mask::IntPixel_t> Mask::minimizeNumberOfRectangles(
86 std::vector<bool> pixels, unsigned int N, /* height */
87 unsigned int M /* width */) {
88 std::vector<IntPixel_t> rectangles;
89
90 unsigned int maxArea = 0;
91 while (true) {
92 IntPixel_t pix = findMaximalRectangle(pixels, N, M);
93 unsigned int area = computeArea(pix.first, pix.second);
94 if (area > maxArea) maxArea = area;
95 if (1000 * area < maxArea || area <= 1) {
96 break;
97 }
98
99 rectangles.push_back(pix);
100
101 for (int y = pix.first.y_m; y < pix.second.y_m; ++y) {
102 unsigned int idx = y * M + pix.first.x_m;
103 for (int x = pix.first.x_m; x < pix.second.x_m; ++x, ++idx) {
104 pixels[idx] = false;
105 }
106 }
107 }
108
109 unsigned int idx = 0;
110 for (unsigned int y = 0; y < N; ++y) {
111 for (unsigned int x = 0; x < M; ++x, ++idx) {
112 if (pixels[idx]) {
113 IntPoint ll(x, y);
114 IntPoint ur(x + 1, y + 1);
115 rectangles.push_back(IntPixel_t(ll, ur));
116 }
117 }
118 }
119
120 return rectangles;
121 }
122
123 bool Mask::parse_detail(iterator& it, const iterator& end, Function*& fun) {
124 Mask* pixmap = static_cast<Mask*>(fun);
125
126 ArgumentExtractor arguments(std::string(it, end));
127 std::string filename = arguments.get(0);
128 if (filename[0] == '\'' && filename.back() == '\'') {
129 filename = filename.substr(1, filename.length() - 2);
130 }
131
132 if (!std::filesystem::exists(filename)) {
133 *ippl::Error << "file '" << filename << "' doesn't exists" << endl;
134 return false;
135 }
136
137 PortableBitmapReader reader(filename);
138 unsigned int width = reader.getWidth();
139 unsigned int height = reader.getHeight();
140
141 double pixel_width;
142 double pixel_height;
143 try {
144 pixel_width = parseMathExpression(arguments.get(1)) / width;
145 pixel_height = parseMathExpression(arguments.get(2)) / height;
146 } catch (std::runtime_error& e) {
147 std::cout << e.what() << std::endl;
148 return false;
149 }
150
151 if (pixel_width < 0.0) {
152 std::cout << "Mask: a negative width provided '" << arguments.get(0) << " = "
153 << pixel_width * width << "'" << std::endl;
154 return false;
155 }
156
157 if (pixel_height < 0.0) {
158 std::cout << "Mask: a negative height provided '" << arguments.get(1) << " = "
159 << pixel_height * height << "'" << std::endl;
160 return false;
161 }
162
163 auto maxRect = pixmap->minimizeNumberOfRectangles(reader.getPixels(), height, width);
164
165 for (const IntPixel_t& pix : maxRect) {
166 const IntPoint& ll = pix.first;
167 const IntPoint& ur = pix.second;
168
169 Rectangle rect;
170 rect.width_m = (ur.x_m - ll.x_m) * pixel_width;
171 rect.height_m = (ur.y_m - ll.y_m) * pixel_height;
172
173 double midX = 0.5 * (ur.x_m + ll.x_m);
174 double midY = 0.5 * (ur.y_m + ll.y_m);
176 Vector_t<double, 3>(1, 0, (0.5 * width - midX) * pixel_width),
177 Vector_t<double, 3>(0, 1, (midY - 0.5 * height) * pixel_height));
178
179 pixmap->pixels_m.push_back(rect);
180 pixmap->pixels_m.back().computeBoundingBox();
181 }
182
183 it += (arguments.getLengthConsumed() + 1);
184
185 return true;
186 }
187
188 void Mask::print(int ident) {
189 for (auto pix : pixels_m)
190 pix.print(ident);
191 }
192
193 void Mask::apply(std::vector<std::shared_ptr<Base> >& bfuncs) {
194 for (auto pix : pixels_m)
195 pix.apply(bfuncs);
196 }
197} // namespace mslang
ippl::Vector< T, Dim > Vector_t
std::vector< bool > getPixels() const
unsigned int getWidth() const
unsigned int getHeight() const
double parseMathExpression(const std::string &str)
Definition matheval.cpp:4
std::string::iterator iterator
Definition MSLang.h:14
std::string get(unsigned int i) const
unsigned int getLengthConsumed() const
AffineTransformation trafo_m
Definition MSLang.h:38
virtual void apply(std::vector< std::shared_ptr< Base > > &bfuncs)
Definition Mask.cpp:193
virtual void print(int ident)
Definition Mask.cpp:188
std::vector< IntPixel_t > minimizeNumberOfRectangles(std::vector< bool > pixels, unsigned int height, unsigned int width)
Definition Mask.cpp:85
std::pair< IntPoint, IntPoint > findMaximalRectangle(const std::vector< bool > &pixels, unsigned int height, unsigned int width) const
Definition Mask.cpp:30
static bool parse_detail(iterator &it, const iterator &end, Function *&fun)
Definition Mask.cpp:123
unsigned int computeArea(const IntPoint &ll, const IntPoint &ur) const
Definition Mask.cpp:24
std::pair< IntPoint, IntPoint > IntPixel_t
Definition Mask.h:23
void updateCache(const std::vector< bool > &pixels, std::vector< unsigned int > &cache, unsigned int y) const
Definition Mask.cpp:10
std::vector< Rectangle > pixels_m
Definition Mask.h:13