bit_map.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. /**************************************************************************/
  2. /* bit_map.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "bit_map.h"
  31. #include "core/io/image_loader.h"
  32. void BitMap::create(const Size2 &p_size) {
  33. ERR_FAIL_COND(p_size.width < 1);
  34. ERR_FAIL_COND(p_size.height < 1);
  35. width = p_size.width;
  36. height = p_size.height;
  37. bitmask.resize((((width * height) - 1) / 8) + 1);
  38. memset(bitmask.ptrw(), 0, bitmask.size());
  39. }
  40. void BitMap::create_from_image_alpha(const Ref<Image> &p_image, float p_threshold) {
  41. ERR_FAIL_COND(p_image.is_null() || p_image->empty());
  42. Ref<Image> img = p_image->duplicate();
  43. img->convert(Image::FORMAT_LA8);
  44. ERR_FAIL_COND(img->get_format() != Image::FORMAT_LA8);
  45. create(Size2(img->get_width(), img->get_height()));
  46. PoolVector<uint8_t>::Read r = img->get_data().read();
  47. uint8_t *w = bitmask.ptrw();
  48. for (int i = 0; i < width * height; i++) {
  49. int bbyte = i / 8;
  50. int bbit = i % 8;
  51. if (r[i * 2 + 1] / 255.0 > p_threshold) {
  52. w[bbyte] |= (1 << bbit);
  53. }
  54. }
  55. }
  56. void BitMap::set_bit_rect(const Rect2 &p_rect, bool p_value) {
  57. Rect2i current = Rect2i(0, 0, width, height).clip(p_rect);
  58. uint8_t *data = bitmask.ptrw();
  59. for (int i = current.position.x; i < current.position.x + current.size.x; i++) {
  60. for (int j = current.position.y; j < current.position.y + current.size.y; j++) {
  61. int ofs = width * j + i;
  62. int bbyte = ofs / 8;
  63. int bbit = ofs % 8;
  64. uint8_t b = data[bbyte];
  65. if (p_value) {
  66. b |= (1 << bbit);
  67. } else {
  68. b &= ~(1 << bbit);
  69. }
  70. data[bbyte] = b;
  71. }
  72. }
  73. }
  74. int BitMap::get_true_bit_count() const {
  75. int ds = bitmask.size();
  76. const uint8_t *d = bitmask.ptr();
  77. int c = 0;
  78. //fast, almost branchless version
  79. for (int i = 0; i < ds; i++) {
  80. c += (d[i] & (1 << 7)) >> 7;
  81. c += (d[i] & (1 << 6)) >> 6;
  82. c += (d[i] & (1 << 5)) >> 5;
  83. c += (d[i] & (1 << 4)) >> 4;
  84. c += (d[i] & (1 << 3)) >> 3;
  85. c += (d[i] & (1 << 2)) >> 2;
  86. c += (d[i] & (1 << 1)) >> 1;
  87. c += d[i] & 1;
  88. }
  89. return c;
  90. }
  91. void BitMap::set_bit(const Point2 &p_pos, bool p_value) {
  92. int x = p_pos.x;
  93. int y = p_pos.y;
  94. ERR_FAIL_INDEX(x, width);
  95. ERR_FAIL_INDEX(y, height);
  96. int ofs = width * y + x;
  97. int bbyte = ofs / 8;
  98. int bbit = ofs % 8;
  99. uint8_t b = bitmask[bbyte];
  100. if (p_value) {
  101. b |= (1 << bbit);
  102. } else {
  103. b &= ~(1 << bbit);
  104. }
  105. bitmask.write[bbyte] = b;
  106. }
  107. bool BitMap::get_bit(const Point2 &p_pos) const {
  108. int x = Math::fast_ftoi(p_pos.x);
  109. int y = Math::fast_ftoi(p_pos.y);
  110. ERR_FAIL_INDEX_V(x, width, false);
  111. ERR_FAIL_INDEX_V(y, height, false);
  112. int ofs = width * y + x;
  113. int bbyte = ofs / 8;
  114. int bbit = ofs % 8;
  115. return (bitmask[bbyte] & (1 << bbit)) != 0;
  116. }
  117. Size2 BitMap::get_size() const {
  118. return Size2(width, height);
  119. }
  120. void BitMap::_set_data(const Dictionary &p_d) {
  121. ERR_FAIL_COND(!p_d.has("size"));
  122. ERR_FAIL_COND(!p_d.has("data"));
  123. create(p_d["size"]);
  124. bitmask = p_d["data"];
  125. }
  126. Dictionary BitMap::_get_data() const {
  127. Dictionary d;
  128. d["size"] = get_size();
  129. d["data"] = bitmask;
  130. return d;
  131. }
  132. Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) const {
  133. int stepx = 0;
  134. int stepy = 0;
  135. int prevx = 0;
  136. int prevy = 0;
  137. int startx = start.x;
  138. int starty = start.y;
  139. int curx = startx;
  140. int cury = starty;
  141. unsigned int count = 0;
  142. Set<Point2i> case9s;
  143. Set<Point2i> case6s;
  144. Vector<Vector2> _points;
  145. do {
  146. int sv = 0;
  147. { //square value
  148. /*
  149. checking the 2x2 pixel grid, assigning these values to each pixel, if not transparent
  150. +---+---+
  151. | 1 | 2 |
  152. +---+---+
  153. | 4 | 8 | <- current pixel (curx,cury)
  154. +---+---+
  155. */
  156. Point2i tl = Point2i(curx - 1, cury - 1);
  157. sv += (rect.has_point(tl) && get_bit(tl)) ? 1 : 0;
  158. Point2i tr = Point2i(curx, cury - 1);
  159. sv += (rect.has_point(tr) && get_bit(tr)) ? 2 : 0;
  160. Point2i bl = Point2i(curx - 1, cury);
  161. sv += (rect.has_point(bl) && get_bit(bl)) ? 4 : 0;
  162. Point2i br = Point2i(curx, cury);
  163. sv += (rect.has_point(br) && get_bit(br)) ? 8 : 0;
  164. ERR_FAIL_COND_V(sv == 0 || sv == 15, Vector<Vector2>());
  165. }
  166. switch (sv) {
  167. case 1:
  168. case 5:
  169. case 13:
  170. /* going UP with these cases:
  171. 1 5 13
  172. +---+---+ +---+---+ +---+---+
  173. | 1 | | | 1 | | | 1 | |
  174. +---+---+ +---+---+ +---+---+
  175. | | | | 4 | | | 4 | 8 |
  176. +---+---+ +---+---+ +---+---+
  177. */
  178. stepx = 0;
  179. stepy = -1;
  180. break;
  181. case 8:
  182. case 10:
  183. case 11:
  184. /* going DOWN with these cases:
  185. 8 10 11
  186. +---+---+ +---+---+ +---+---+
  187. | | | | | 2 | | 1 | 2 |
  188. +---+---+ +---+---+ +---+---+
  189. | | 8 | | | 8 | | | 8 |
  190. +---+---+ +---+---+ +---+---+
  191. */
  192. stepx = 0;
  193. stepy = 1;
  194. break;
  195. case 4:
  196. case 12:
  197. case 14:
  198. /* going LEFT with these cases:
  199. 4 12 14
  200. +---+---+ +---+---+ +---+---+
  201. | | | | | | | | 2 |
  202. +---+---+ +---+---+ +---+---+
  203. | 4 | | | 4 | 8 | | 4 | 8 |
  204. +---+---+ +---+---+ +---+---+
  205. */
  206. stepx = -1;
  207. stepy = 0;
  208. break;
  209. case 2:
  210. case 3:
  211. case 7:
  212. /* going RIGHT with these cases:
  213. 2 3 7
  214. +---+---+ +---+---+ +---+---+
  215. | | 2 | | 1 | 2 | | 1 | 2 |
  216. +---+---+ +---+---+ +---+---+
  217. | | | | | | | 4 | |
  218. +---+---+ +---+---+ +---+---+
  219. */
  220. stepx = 1;
  221. stepy = 0;
  222. break;
  223. case 9:
  224. /*
  225. +---+---+
  226. | 1 | |
  227. +---+---+
  228. | | 8 |
  229. +---+---+
  230. this should normally go UP, but if we already been here, we go down
  231. */
  232. if (case9s.has(Point2i(curx, cury))) {
  233. //found, so we go down, and delete from case9s;
  234. stepx = 0;
  235. stepy = 1;
  236. case9s.erase(Point2i(curx, cury));
  237. } else {
  238. //not found, we go up, and add to case9s;
  239. stepx = 0;
  240. stepy = -1;
  241. case9s.insert(Point2i(curx, cury));
  242. }
  243. break;
  244. case 6:
  245. /*
  246. 6
  247. +---+---+
  248. | | 2 |
  249. +---+---+
  250. | 4 | |
  251. +---+---+
  252. this normally go RIGHT, but if its coming from RIGHT, it should go LEFT
  253. */
  254. if (case6s.has(Point2i(curx, cury))) {
  255. //found, so we go left, and delete from case6s;
  256. stepx = -1;
  257. stepy = 0;
  258. case6s.erase(Point2i(curx, cury));
  259. } else {
  260. //not found, we go right, and add to case6s;
  261. stepx = 1;
  262. stepy = 0;
  263. case6s.insert(Point2i(curx, cury));
  264. }
  265. break;
  266. default:
  267. ERR_PRINT("this shouldn't happen.");
  268. }
  269. //little optimization
  270. // if previous direction is same as current direction,
  271. // then we should modify the last vec to current
  272. curx += stepx;
  273. cury += stepy;
  274. if (stepx == prevx && stepy == prevy) {
  275. _points.write[_points.size() - 1].x = (float)(curx - rect.position.x);
  276. _points.write[_points.size() - 1].y = (float)(cury + rect.position.y);
  277. } else {
  278. _points.push_back(Vector2((float)(curx - rect.position.x), (float)(cury + rect.position.y)));
  279. }
  280. count++;
  281. prevx = stepx;
  282. prevy = stepy;
  283. ERR_FAIL_COND_V((int)count > 2 * (width * height + 1), _points);
  284. } while (curx != startx || cury != starty);
  285. return _points;
  286. }
  287. static float perpendicular_distance(const Vector2 &i, const Vector2 &start, const Vector2 &end) {
  288. float res;
  289. float slope;
  290. float intercept;
  291. if (start.x == end.x) {
  292. res = Math::absf(i.x - end.x);
  293. } else if (start.y == end.y) {
  294. res = Math::absf(i.y - end.y);
  295. } else {
  296. slope = (end.y - start.y) / (end.x - start.x);
  297. intercept = start.y - (slope * start.x);
  298. res = Math::absf(slope * i.x - i.y + intercept) / Math::sqrt(Math::pow(slope, 2.0f) + 1.0);
  299. }
  300. return res;
  301. }
  302. static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) {
  303. if (v.size() < 3) {
  304. return v;
  305. }
  306. int index = -1;
  307. float dist = 0;
  308. //not looping first and last point
  309. for (size_t i = 1, size = v.size(); i < size - 1; ++i) {
  310. float cdist = perpendicular_distance(v[i], v[0], v[v.size() - 1]);
  311. if (cdist > dist) {
  312. dist = cdist;
  313. index = static_cast<int>(i);
  314. }
  315. }
  316. if (dist > optimization) {
  317. Vector<Vector2> left, right;
  318. left.resize(index);
  319. for (int i = 0; i < index; i++) {
  320. left.write[i] = v[i];
  321. }
  322. right.resize(v.size() - index);
  323. for (int i = 0; i < right.size(); i++) {
  324. right.write[i] = v[index + i];
  325. }
  326. Vector<Vector2> r1 = rdp(left, optimization);
  327. Vector<Vector2> r2 = rdp(right, optimization);
  328. int middle = r1.size();
  329. r1.resize(r1.size() + r2.size());
  330. for (int i = 0; i < r2.size(); i++) {
  331. r1.write[middle + i] = r2[i];
  332. }
  333. return r1;
  334. } else {
  335. Vector<Vector2> ret;
  336. ret.push_back(v[0]);
  337. ret.push_back(v[v.size() - 1]);
  338. return ret;
  339. }
  340. }
  341. static Vector<Vector2> reduce(const Vector<Vector2> &points, const Rect2i &rect, float epsilon) {
  342. int size = points.size();
  343. // if there are less than 3 points, then we have nothing
  344. ERR_FAIL_COND_V(size < 3, Vector<Vector2>());
  345. // if there are less than 9 points (but more than 3), then we don't need to reduce it
  346. if (size < 9) {
  347. return points;
  348. }
  349. float maxEp = MIN(rect.size.width, rect.size.height);
  350. float ep = CLAMP(epsilon, 0.0, maxEp / 2);
  351. Vector<Vector2> result = rdp(points, ep);
  352. Vector2 last = result[result.size() - 1];
  353. if (last.y > result[0].y && last.distance_to(result[0]) < ep * 0.5f) {
  354. result.write[0].y = last.y;
  355. result.resize(result.size() - 1);
  356. }
  357. return result;
  358. }
  359. struct FillBitsStackEntry {
  360. Point2i pos;
  361. int i;
  362. int j;
  363. };
  364. static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_pos, const Rect2i &rect) {
  365. // Using a custom stack to work iteratively to avoid stack overflow on big bitmaps
  366. PoolVector<FillBitsStackEntry> stack;
  367. // Tracking size since we won't be shrinking the stack vector
  368. int stack_size = 0;
  369. Point2i pos = p_pos;
  370. int next_i = 0;
  371. int next_j = 0;
  372. bool reenter = true;
  373. bool popped = false;
  374. do {
  375. if (reenter) {
  376. next_i = pos.x - 1;
  377. next_j = pos.y - 1;
  378. reenter = false;
  379. }
  380. for (int i = next_i; i <= pos.x + 1; i++) {
  381. for (int j = next_j; j <= pos.y + 1; j++) {
  382. if (popped) {
  383. // The next loop over j must start normally
  384. next_j = pos.y;
  385. popped = false;
  386. // Skip because an iteration was already executed with current counter values
  387. continue;
  388. }
  389. if (i < rect.position.x || i >= rect.position.x + rect.size.x) {
  390. continue;
  391. }
  392. if (j < rect.position.y || j >= rect.position.y + rect.size.y) {
  393. continue;
  394. }
  395. if (p_map->get_bit(Vector2(i, j))) {
  396. continue;
  397. } else if (p_src->get_bit(Vector2(i, j))) {
  398. p_map->set_bit(Vector2(i, j), true);
  399. FillBitsStackEntry se = { pos, i, j };
  400. stack.resize(MAX(stack_size + 1, stack.size()));
  401. stack.set(stack_size, se);
  402. stack_size++;
  403. pos = Point2i(i, j);
  404. reenter = true;
  405. break;
  406. }
  407. }
  408. if (reenter) {
  409. break;
  410. }
  411. }
  412. if (!reenter) {
  413. if (stack_size) {
  414. FillBitsStackEntry se = stack.get(stack_size - 1);
  415. stack_size--;
  416. pos = se.pos;
  417. next_i = se.i;
  418. next_j = se.j;
  419. popped = true;
  420. }
  421. }
  422. } while (reenter || popped);
  423. print_verbose("BitMap: Max stack size: " + itos(stack.size()));
  424. }
  425. Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon) const {
  426. Rect2i r = Rect2i(0, 0, width, height).clip(p_rect);
  427. print_verbose("BitMap: Rect: " + r);
  428. Point2i from;
  429. Ref<BitMap> fill;
  430. fill.instance();
  431. fill->create(get_size());
  432. Vector<Vector<Vector2>> polygons;
  433. for (int i = r.position.y; i < r.position.y + r.size.height; i++) {
  434. for (int j = r.position.x; j < r.position.x + r.size.width; j++) {
  435. if (!fill->get_bit(Point2(j, i)) && get_bit(Point2(j, i))) {
  436. fill_bits(this, fill, Point2i(j, i), r);
  437. Vector<Vector2> polygon = _march_square(r, Point2i(j, i));
  438. print_verbose("BitMap: Pre reduce: " + itos(polygon.size()));
  439. polygon = reduce(polygon, r, p_epsilon);
  440. print_verbose("BitMap: Post reduce: " + itos(polygon.size()));
  441. if (polygon.size() < 3) {
  442. print_verbose("Invalid polygon, skipped");
  443. continue;
  444. }
  445. polygons.push_back(polygon);
  446. }
  447. }
  448. }
  449. return polygons;
  450. }
  451. void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) {
  452. if (p_pixels == 0) {
  453. return;
  454. }
  455. bool bit_value = p_pixels > 0;
  456. p_pixels = Math::abs(p_pixels);
  457. Rect2i r = Rect2i(0, 0, width, height).clip(p_rect);
  458. Ref<BitMap> copy;
  459. copy.instance();
  460. copy->create(get_size());
  461. copy->bitmask = bitmask;
  462. for (int i = r.position.y; i < r.position.y + r.size.height; i++) {
  463. for (int j = r.position.x; j < r.position.x + r.size.width; j++) {
  464. if (bit_value == get_bit(Point2(j, i))) {
  465. continue;
  466. }
  467. bool found = false;
  468. for (int y = i - p_pixels; y <= i + p_pixels; y++) {
  469. for (int x = j - p_pixels; x <= j + p_pixels; x++) {
  470. bool outside = false;
  471. if ((x < p_rect.position.x) || (x >= p_rect.position.x + p_rect.size.x) || (y < p_rect.position.y) || (y >= p_rect.position.y + p_rect.size.y)) {
  472. // outside of rectangle counts as bit not set
  473. if (!bit_value) {
  474. outside = true;
  475. } else {
  476. continue;
  477. }
  478. }
  479. float d = Point2(j, i).distance_to(Point2(x, y)) - CMP_EPSILON;
  480. if (d > p_pixels) {
  481. continue;
  482. }
  483. if (outside || (bit_value == copy->get_bit(Point2(x, y)))) {
  484. found = true;
  485. break;
  486. }
  487. }
  488. if (found) {
  489. break;
  490. }
  491. }
  492. if (found) {
  493. set_bit(Point2(j, i), bit_value);
  494. }
  495. }
  496. }
  497. }
  498. void BitMap::shrink_mask(int p_pixels, const Rect2 &p_rect) {
  499. grow_mask(-p_pixels, p_rect);
  500. }
  501. Array BitMap::_opaque_to_polygons_bind(const Rect2 &p_rect, float p_epsilon) const {
  502. Vector<Vector<Vector2>> result = clip_opaque_to_polygons(p_rect, p_epsilon);
  503. // Convert result to bindable types
  504. Array result_array;
  505. result_array.resize(result.size());
  506. for (int i = 0; i < result.size(); i++) {
  507. const Vector<Vector2> &polygon = result[i];
  508. PoolVector2Array polygon_array;
  509. polygon_array.resize(polygon.size());
  510. {
  511. PoolVector2Array::Write w = polygon_array.write();
  512. for (int j = 0; j < polygon.size(); j++) {
  513. w[j] = polygon[j];
  514. }
  515. }
  516. result_array[i] = polygon_array;
  517. }
  518. return result_array;
  519. }
  520. void BitMap::resize(const Size2 &p_new_size) {
  521. Ref<BitMap> new_bitmap;
  522. new_bitmap.instance();
  523. new_bitmap->create(p_new_size);
  524. int lw = MIN(width, new_bitmap->width);
  525. int lh = MIN(height, new_bitmap->height);
  526. for (int x = 0; x < lw; x++) {
  527. for (int y = 0; y < lh; y++) {
  528. new_bitmap->set_bit(Vector2(x, y), get_bit(Vector2(x, y)));
  529. }
  530. }
  531. width = new_bitmap->width;
  532. height = new_bitmap->height;
  533. bitmask = new_bitmap->bitmask;
  534. }
  535. Ref<Image> BitMap::convert_to_image() const {
  536. Ref<Image> image;
  537. image.instance();
  538. image->create(width, height, false, Image::FORMAT_L8);
  539. image->lock();
  540. for (int i = 0; i < width; i++) {
  541. for (int j = 0; j < height; j++) {
  542. image->set_pixel(i, j, get_bit(Point2(i, j)) ? Color(1, 1, 1) : Color(0, 0, 0));
  543. }
  544. }
  545. image->unlock();
  546. return image;
  547. }
  548. void BitMap::blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap) {
  549. int x = p_pos.x;
  550. int y = p_pos.y;
  551. int w = p_bitmap->get_size().width;
  552. int h = p_bitmap->get_size().height;
  553. for (int i = 0; i < w; i++) {
  554. for (int j = 0; j < h; j++) {
  555. int px = x + i;
  556. int py = y + j;
  557. if (px < 0 || px >= width) {
  558. continue;
  559. }
  560. if (py < 0 || py >= height) {
  561. continue;
  562. }
  563. if (p_bitmap->get_bit(Vector2(i, j))) {
  564. set_bit(Vector2(x, y), true);
  565. }
  566. }
  567. }
  568. }
  569. void BitMap::_bind_methods() {
  570. ClassDB::bind_method(D_METHOD("create", "size"), &BitMap::create);
  571. ClassDB::bind_method(D_METHOD("create_from_image_alpha", "image", "threshold"), &BitMap::create_from_image_alpha, DEFVAL(0.1));
  572. ClassDB::bind_method(D_METHOD("set_bit", "position", "bit"), &BitMap::set_bit);
  573. ClassDB::bind_method(D_METHOD("get_bit", "position"), &BitMap::get_bit);
  574. ClassDB::bind_method(D_METHOD("set_bit_rect", "rect", "bit"), &BitMap::set_bit_rect);
  575. ClassDB::bind_method(D_METHOD("get_true_bit_count"), &BitMap::get_true_bit_count);
  576. ClassDB::bind_method(D_METHOD("get_size"), &BitMap::get_size);
  577. ClassDB::bind_method(D_METHOD("resize", "new_size"), &BitMap::resize);
  578. ClassDB::bind_method(D_METHOD("_set_data"), &BitMap::_set_data);
  579. ClassDB::bind_method(D_METHOD("_get_data"), &BitMap::_get_data);
  580. ClassDB::bind_method(D_METHOD("grow_mask", "pixels", "rect"), &BitMap::grow_mask);
  581. ClassDB::bind_method(D_METHOD("convert_to_image"), &BitMap::convert_to_image);
  582. ClassDB::bind_method(D_METHOD("opaque_to_polygons", "rect", "epsilon"), &BitMap::_opaque_to_polygons_bind, DEFVAL(2.0));
  583. ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data");
  584. }
  585. BitMap::BitMap() {
  586. width = 0;
  587. height = 0;
  588. }
  589. //////////////////////////////////////