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