bit_map.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  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. #include "core/variant/typed_array.h"
  33. void BitMap::create(const Size2i &p_size) {
  34. ERR_FAIL_COND(p_size.width < 1);
  35. ERR_FAIL_COND(p_size.height < 1);
  36. ERR_FAIL_COND(static_cast<int64_t>(p_size.width) * static_cast<int64_t>(p_size.height) > INT32_MAX);
  37. Error err = bitmask.resize(Math::division_round_up(p_size.width * p_size.height, 8));
  38. ERR_FAIL_COND(err != OK);
  39. width = p_size.width;
  40. height = p_size.height;
  41. memset(bitmask.ptrw(), 0, bitmask.size());
  42. }
  43. void BitMap::create_from_image_alpha(const Ref<Image> &p_image, float p_threshold) {
  44. ERR_FAIL_COND(p_image.is_null() || p_image->is_empty());
  45. Ref<Image> img = p_image->duplicate();
  46. img->convert(Image::FORMAT_LA8);
  47. ERR_FAIL_COND(img->get_format() != Image::FORMAT_LA8);
  48. create(Size2i(img->get_width(), img->get_height()));
  49. const uint8_t *r = img->get_data().ptr();
  50. uint8_t *w = bitmask.ptrw();
  51. for (int i = 0; i < width * height; i++) {
  52. int bbyte = i / 8;
  53. int bbit = i % 8;
  54. if (r[i * 2 + 1] / 255.0 > p_threshold) {
  55. w[bbyte] |= (1 << bbit);
  56. }
  57. }
  58. }
  59. void BitMap::set_bit_rect(const Rect2i &p_rect, bool p_value) {
  60. Rect2i current = Rect2i(0, 0, width, height).intersection(p_rect);
  61. uint8_t *data = bitmask.ptrw();
  62. for (int i = current.position.x; i < current.position.x + current.size.x; i++) {
  63. for (int j = current.position.y; j < current.position.y + current.size.y; j++) {
  64. int ofs = width * j + i;
  65. int bbyte = ofs / 8;
  66. int bbit = ofs % 8;
  67. uint8_t b = data[bbyte];
  68. if (p_value) {
  69. b |= (1 << bbit);
  70. } else {
  71. b &= ~(1 << bbit);
  72. }
  73. data[bbyte] = b;
  74. }
  75. }
  76. }
  77. int BitMap::get_true_bit_count() const {
  78. int ds = bitmask.size();
  79. const uint8_t *d = bitmask.ptr();
  80. int c = 0;
  81. // Fast, almost branchless version.
  82. for (int i = 0; i < ds; i++) {
  83. c += (d[i] & (1 << 7)) >> 7;
  84. c += (d[i] & (1 << 6)) >> 6;
  85. c += (d[i] & (1 << 5)) >> 5;
  86. c += (d[i] & (1 << 4)) >> 4;
  87. c += (d[i] & (1 << 3)) >> 3;
  88. c += (d[i] & (1 << 2)) >> 2;
  89. c += (d[i] & (1 << 1)) >> 1;
  90. c += d[i] & 1;
  91. }
  92. return c;
  93. }
  94. void BitMap::set_bitv(const Point2i &p_pos, bool p_value) {
  95. set_bit(p_pos.x, p_pos.y, p_value);
  96. }
  97. void BitMap::set_bit(int p_x, int p_y, bool p_value) {
  98. ERR_FAIL_INDEX(p_x, width);
  99. ERR_FAIL_INDEX(p_y, height);
  100. int ofs = width * p_y + p_x;
  101. int bbyte = ofs / 8;
  102. int bbit = ofs % 8;
  103. uint8_t b = bitmask[bbyte];
  104. if (p_value) {
  105. b |= (1 << bbit);
  106. } else {
  107. b &= ~(1 << bbit);
  108. }
  109. bitmask.write[bbyte] = b;
  110. }
  111. bool BitMap::get_bitv(const Point2i &p_pos) const {
  112. return get_bit(p_pos.x, p_pos.y);
  113. }
  114. bool BitMap::get_bit(int p_x, int p_y) const {
  115. ERR_FAIL_INDEX_V(p_x, width, false);
  116. ERR_FAIL_INDEX_V(p_y, height, false);
  117. int ofs = width * p_y + p_x;
  118. int bbyte = ofs / 8;
  119. int bbit = ofs % 8;
  120. return (bitmask[bbyte] & (1 << bbit)) != 0;
  121. }
  122. Size2i BitMap::get_size() const {
  123. return Size2i(width, height);
  124. }
  125. void BitMap::_set_data(const Dictionary &p_d) {
  126. ERR_FAIL_COND(!p_d.has("size"));
  127. ERR_FAIL_COND(!p_d.has("data"));
  128. create(p_d["size"]);
  129. bitmask = p_d["data"];
  130. }
  131. Dictionary BitMap::_get_data() const {
  132. Dictionary d;
  133. d["size"] = get_size();
  134. d["data"] = bitmask;
  135. return d;
  136. }
  137. Vector<Vector<Vector2>> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_start) const {
  138. int stepx = 0;
  139. int stepy = 0;
  140. int prevx = 0;
  141. int prevy = 0;
  142. int startx = p_start.x;
  143. int starty = p_start.y;
  144. int curx = startx;
  145. int cury = starty;
  146. unsigned int count = 0;
  147. HashMap<Point2i, int> cross_map;
  148. Vector<Vector2> _points;
  149. int points_size = 0;
  150. Vector<Vector<Vector2>> ret;
  151. // Add starting entry at start of return.
  152. ret.resize(1);
  153. do {
  154. int sv = 0;
  155. { // Square value
  156. /*
  157. checking the 2x2 pixel grid, assigning these values to each pixel, if not transparent
  158. +---+---+
  159. | 1 | 2 |
  160. +---+---+
  161. | 4 | 8 | <- current pixel (curx,cury)
  162. +---+---+
  163. */
  164. Point2i tl = Point2i(curx - 1, cury - 1);
  165. sv += (p_rect.has_point(tl) && get_bitv(tl)) ? 1 : 0;
  166. Point2i tr = Point2i(curx, cury - 1);
  167. sv += (p_rect.has_point(tr) && get_bitv(tr)) ? 2 : 0;
  168. Point2i bl = Point2i(curx - 1, cury);
  169. sv += (p_rect.has_point(bl) && get_bitv(bl)) ? 4 : 0;
  170. Point2i br = Point2i(curx, cury);
  171. sv += (p_rect.has_point(br) && get_bitv(br)) ? 8 : 0;
  172. ERR_FAIL_COND_V(sv == 0 || sv == 15, Vector<Vector<Vector2>>());
  173. }
  174. switch (sv) {
  175. case 1:
  176. case 5:
  177. case 13:
  178. /* going UP with these cases:
  179. 1 5 13
  180. +---+---+ +---+---+ +---+---+
  181. | 1 | | | 1 | | | 1 | |
  182. +---+---+ +---+---+ +---+---+
  183. | | | | 4 | | | 4 | 8 |
  184. +---+---+ +---+---+ +---+---+
  185. */
  186. stepx = 0;
  187. stepy = -1;
  188. break;
  189. case 8:
  190. case 10:
  191. case 11:
  192. /* going DOWN with these cases:
  193. 8 10 11
  194. +---+---+ +---+---+ +---+---+
  195. | | | | | 2 | | 1 | 2 |
  196. +---+---+ +---+---+ +---+---+
  197. | | 8 | | | 8 | | | 8 |
  198. +---+---+ +---+---+ +---+---+
  199. */
  200. stepx = 0;
  201. stepy = 1;
  202. break;
  203. case 4:
  204. case 12:
  205. case 14:
  206. /* going LEFT with these cases:
  207. 4 12 14
  208. +---+---+ +---+---+ +---+---+
  209. | | | | | | | | 2 |
  210. +---+---+ +---+---+ +---+---+
  211. | 4 | | | 4 | 8 | | 4 | 8 |
  212. +---+---+ +---+---+ +---+---+
  213. */
  214. stepx = -1;
  215. stepy = 0;
  216. break;
  217. case 2:
  218. case 3:
  219. case 7:
  220. /* going RIGHT with these cases:
  221. 2 3 7
  222. +---+---+ +---+---+ +---+---+
  223. | | 2 | | 1 | 2 | | 1 | 2 |
  224. +---+---+ +---+---+ +---+---+
  225. | | | | | | | 4 | |
  226. +---+---+ +---+---+ +---+---+
  227. */
  228. stepx = 1;
  229. stepy = 0;
  230. break;
  231. case 9:
  232. /* Going DOWN if coming from the LEFT, otherwise go UP.
  233. 9
  234. +---+---+
  235. | 1 | |
  236. +---+---+
  237. | | 8 |
  238. +---+---+
  239. */
  240. if (prevx == 1) {
  241. stepx = 0;
  242. stepy = 1;
  243. } else {
  244. stepx = 0;
  245. stepy = -1;
  246. }
  247. break;
  248. case 6:
  249. /* Going RIGHT if coming from BELOW, otherwise go LEFT.
  250. 6
  251. +---+---+
  252. | | 2 |
  253. +---+---+
  254. | 4 | |
  255. +---+---+
  256. */
  257. if (prevy == -1) {
  258. stepx = 1;
  259. stepy = 0;
  260. } else {
  261. stepx = -1;
  262. stepy = 0;
  263. }
  264. break;
  265. default:
  266. ERR_PRINT("this shouldn't happen.");
  267. }
  268. // Handle crossing points.
  269. if (sv == 6 || sv == 9) {
  270. const Point2i cur_pos(curx, cury);
  271. // Find if this point has occurred before.
  272. if (HashMap<Point2i, int>::Iterator found = cross_map.find(cur_pos)) {
  273. // Add points after the previous crossing to the result.
  274. ret.push_back(_points.slice(found->value + 1, points_size));
  275. // Remove points after crossing point.
  276. points_size = found->value + 1;
  277. // Erase trailing map elements.
  278. while (cross_map.last() != found) {
  279. cross_map.remove(cross_map.last());
  280. }
  281. cross_map.erase(cur_pos);
  282. } else {
  283. // Add crossing point to map.
  284. cross_map.insert(cur_pos, points_size - 1);
  285. }
  286. }
  287. // Small optimization:
  288. // If the previous direction is same as the current direction,
  289. // then we should modify the last vector to current.
  290. curx += stepx;
  291. cury += stepy;
  292. if (stepx == prevx && stepy == prevy) {
  293. _points.set(points_size - 1, Vector2(curx, cury) - p_rect.position);
  294. } else {
  295. _points.resize(MAX(points_size + 1, _points.size()));
  296. _points.set(points_size, Vector2(curx, cury) - p_rect.position);
  297. points_size++;
  298. }
  299. count++;
  300. prevx = stepx;
  301. prevy = stepy;
  302. ERR_FAIL_COND_V((int)count > 2 * (width * height + 1), Vector<Vector<Vector2>>());
  303. } while (curx != startx || cury != starty);
  304. // Add remaining points to result.
  305. _points.resize(points_size);
  306. ret.set(0, _points);
  307. return ret;
  308. }
  309. static float perpendicular_distance(const Vector2 &i, const Vector2 &start, const Vector2 &end) {
  310. float res;
  311. float slope;
  312. float intercept;
  313. if (start.x == end.x) {
  314. res = Math::absf(i.x - end.x);
  315. } else if (start.y == end.y) {
  316. res = Math::absf(i.y - end.y);
  317. } else {
  318. slope = (end.y - start.y) / (end.x - start.x);
  319. intercept = start.y - (slope * start.x);
  320. res = Math::absf(slope * i.x - i.y + intercept) / Math::sqrt(Math::pow(slope, 2.0f) + 1.0);
  321. }
  322. return res;
  323. }
  324. static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) {
  325. if (v.size() < 3) {
  326. return v;
  327. }
  328. int index = -1;
  329. float dist = 0.0;
  330. // Not looping first and last point.
  331. for (size_t i = 1, size = v.size(); i < size - 1; ++i) {
  332. float cdist = perpendicular_distance(v[i], v[0], v[v.size() - 1]);
  333. if (cdist > dist) {
  334. dist = cdist;
  335. index = static_cast<int>(i);
  336. }
  337. }
  338. if (dist > optimization) {
  339. Vector<Vector2> left, right;
  340. left.resize(index);
  341. for (int i = 0; i < index; i++) {
  342. left.write[i] = v[i];
  343. }
  344. right.resize(v.size() - index);
  345. for (int i = 0; i < right.size(); i++) {
  346. right.write[i] = v[index + i];
  347. }
  348. Vector<Vector2> r1 = rdp(left, optimization);
  349. Vector<Vector2> r2 = rdp(right, optimization);
  350. int middle = r1.size();
  351. r1.resize(r1.size() + r2.size());
  352. for (int i = 0; i < r2.size(); i++) {
  353. r1.write[middle + i] = r2[i];
  354. }
  355. return r1;
  356. } else {
  357. Vector<Vector2> ret;
  358. ret.push_back(v[0]);
  359. ret.push_back(v[v.size() - 1]);
  360. return ret;
  361. }
  362. }
  363. static Vector<Vector2> reduce(const Vector<Vector2> &points, const Rect2i &rect, float epsilon) {
  364. int size = points.size();
  365. // If there are less than 3 points, then we have nothing.
  366. ERR_FAIL_COND_V(size < 3, Vector<Vector2>());
  367. // If there are less than 9 points (but more than 3), then we don't need to reduce it.
  368. if (size < 9) {
  369. return points;
  370. }
  371. float maxEp = MIN(rect.size.width, rect.size.height);
  372. float ep = CLAMP(epsilon, 0.0, maxEp / 2);
  373. Vector<Vector2> result = rdp(points, ep);
  374. Vector2 last = result[result.size() - 1];
  375. if (last.y > result[0].y && last.distance_to(result[0]) < ep * 0.5f) {
  376. result.write[0].y = last.y;
  377. result.resize(result.size() - 1);
  378. }
  379. return result;
  380. }
  381. struct FillBitsStackEntry {
  382. Point2i pos;
  383. int i = 0;
  384. int j = 0;
  385. };
  386. static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_pos, const Rect2i &rect) {
  387. // Using a custom stack to work iteratively to avoid stack overflow on big bitmaps.
  388. Vector<FillBitsStackEntry> stack;
  389. // Tracking size since we won't be shrinking the stack vector.
  390. int stack_size = 0;
  391. Point2i pos = p_pos;
  392. int next_i = 0;
  393. int next_j = 0;
  394. bool reenter = true;
  395. bool popped = false;
  396. do {
  397. if (reenter) {
  398. next_i = pos.x - 1;
  399. next_j = pos.y - 1;
  400. reenter = false;
  401. }
  402. for (int i = next_i; i <= pos.x + 1; i++) {
  403. for (int j = next_j; j <= pos.y + 1; j++) {
  404. if (popped) {
  405. // The next loop over j must start normally.
  406. next_j = pos.y - 1;
  407. popped = false;
  408. // Skip because an iteration was already executed with current counter values.
  409. continue;
  410. }
  411. if (i < rect.position.x || i >= rect.position.x + rect.size.x) {
  412. continue;
  413. }
  414. if (j < rect.position.y || j >= rect.position.y + rect.size.y) {
  415. continue;
  416. }
  417. if (p_map->get_bit(i, j)) {
  418. continue;
  419. } else if (p_src->get_bit(i, j)) {
  420. p_map->set_bit(i, j, true);
  421. FillBitsStackEntry se = { pos, i, j };
  422. stack.resize(MAX(stack_size + 1, stack.size()));
  423. stack.set(stack_size, se);
  424. stack_size++;
  425. pos = Point2i(i, j);
  426. reenter = true;
  427. break;
  428. }
  429. }
  430. if (reenter) {
  431. break;
  432. }
  433. }
  434. if (!reenter) {
  435. if (stack_size) {
  436. FillBitsStackEntry se = stack.get(stack_size - 1);
  437. stack_size--;
  438. pos = se.pos;
  439. next_i = se.i;
  440. next_j = se.j;
  441. popped = true;
  442. }
  443. }
  444. } while (reenter || popped);
  445. }
  446. Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2i &p_rect, float p_epsilon) const {
  447. Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect);
  448. Point2i from;
  449. Ref<BitMap> fill;
  450. fill.instantiate();
  451. fill->create(get_size());
  452. Vector<Vector<Vector2>> polygons;
  453. for (int i = r.position.y; i < r.position.y + r.size.height; i++) {
  454. for (int j = r.position.x; j < r.position.x + r.size.width; j++) {
  455. if (!fill->get_bit(j, i) && get_bit(j, i)) {
  456. fill_bits(this, fill, Point2i(j, i), r);
  457. for (Vector<Vector2> polygon : _march_square(r, Point2i(j, i))) {
  458. polygon = reduce(polygon, r, p_epsilon);
  459. if (polygon.size() < 3) {
  460. print_verbose("Invalid polygon, skipped");
  461. continue;
  462. }
  463. polygons.push_back(polygon);
  464. }
  465. }
  466. }
  467. }
  468. return polygons;
  469. }
  470. void BitMap::grow_mask(int p_pixels, const Rect2i &p_rect) {
  471. if (p_pixels == 0) {
  472. return;
  473. }
  474. bool bit_value = p_pixels > 0;
  475. p_pixels = Math::abs(p_pixels);
  476. const int pixels2 = p_pixels * p_pixels;
  477. Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect);
  478. Ref<BitMap> copy;
  479. copy.instantiate();
  480. copy->create(get_size());
  481. copy->bitmask = bitmask;
  482. for (int i = r.position.y; i < r.position.y + r.size.height; i++) {
  483. for (int j = r.position.x; j < r.position.x + r.size.width; j++) {
  484. if (bit_value == get_bit(j, i)) {
  485. continue;
  486. }
  487. bool found = false;
  488. for (int y = i - p_pixels; y <= i + p_pixels; y++) {
  489. for (int x = j - p_pixels; x <= j + p_pixels; x++) {
  490. bool outside = false;
  491. 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)) {
  492. // Outside of rectangle counts as bit not set.
  493. if (!bit_value) {
  494. outside = true;
  495. } else {
  496. continue;
  497. }
  498. }
  499. float d = Point2(j, i).distance_squared_to(Point2(x, y)) - CMP_EPSILON2;
  500. if (d > pixels2) {
  501. continue;
  502. }
  503. if (outside || (bit_value == copy->get_bit(x, y))) {
  504. found = true;
  505. break;
  506. }
  507. }
  508. if (found) {
  509. break;
  510. }
  511. }
  512. if (found) {
  513. set_bit(j, i, bit_value);
  514. }
  515. }
  516. }
  517. }
  518. void BitMap::shrink_mask(int p_pixels, const Rect2i &p_rect) {
  519. grow_mask(-p_pixels, p_rect);
  520. }
  521. TypedArray<PackedVector2Array> BitMap::_opaque_to_polygons_bind(const Rect2i &p_rect, float p_epsilon) const {
  522. Vector<Vector<Vector2>> result = clip_opaque_to_polygons(p_rect, p_epsilon);
  523. // Convert result to bindable types.
  524. TypedArray<PackedVector2Array> result_array;
  525. result_array.resize(result.size());
  526. for (int i = 0; i < result.size(); i++) {
  527. const Vector<Vector2> &polygon = result[i];
  528. PackedVector2Array polygon_array;
  529. polygon_array.resize(polygon.size());
  530. {
  531. Vector2 *w = polygon_array.ptrw();
  532. for (int j = 0; j < polygon.size(); j++) {
  533. w[j] = polygon[j];
  534. }
  535. }
  536. result_array[i] = polygon_array;
  537. }
  538. return result_array;
  539. }
  540. void BitMap::resize(const Size2i &p_new_size) {
  541. ERR_FAIL_COND(p_new_size.width < 0 || p_new_size.height < 0);
  542. if (p_new_size == get_size()) {
  543. return;
  544. }
  545. Ref<BitMap> new_bitmap;
  546. new_bitmap.instantiate();
  547. new_bitmap->create(p_new_size);
  548. // also allow for upscaling
  549. int lw = (width == 0) ? 0 : p_new_size.width;
  550. int lh = (height == 0) ? 0 : p_new_size.height;
  551. float scale_x = ((float)width / p_new_size.width);
  552. float scale_y = ((float)height / p_new_size.height);
  553. for (int x = 0; x < lw; x++) {
  554. for (int y = 0; y < lh; y++) {
  555. bool new_bit = get_bit(x * scale_x, y * scale_y);
  556. new_bitmap->set_bit(x, y, new_bit);
  557. }
  558. }
  559. width = new_bitmap->width;
  560. height = new_bitmap->height;
  561. bitmask = new_bitmap->bitmask;
  562. }
  563. Ref<Image> BitMap::convert_to_image() const {
  564. Ref<Image> image = Image::create_empty(width, height, false, Image::FORMAT_L8);
  565. for (int i = 0; i < width; i++) {
  566. for (int j = 0; j < height; j++) {
  567. image->set_pixel(i, j, get_bit(i, j) ? Color(1, 1, 1) : Color(0, 0, 0));
  568. }
  569. }
  570. return image;
  571. }
  572. void BitMap::blit(const Vector2i &p_pos, const Ref<BitMap> &p_bitmap) {
  573. ERR_FAIL_COND_MSG(p_bitmap.is_null(), "It's not a reference to a valid BitMap object.");
  574. int x = p_pos.x;
  575. int y = p_pos.y;
  576. int w = p_bitmap->get_size().width;
  577. int h = p_bitmap->get_size().height;
  578. for (int i = 0; i < w; i++) {
  579. for (int j = 0; j < h; j++) {
  580. int px = x + i;
  581. int py = y + j;
  582. if (px < 0 || px >= width) {
  583. continue;
  584. }
  585. if (py < 0 || py >= height) {
  586. continue;
  587. }
  588. if (p_bitmap->get_bit(i, j)) {
  589. set_bit(px, py, true);
  590. }
  591. }
  592. }
  593. }
  594. void BitMap::_bind_methods() {
  595. ClassDB::bind_method(D_METHOD("create", "size"), &BitMap::create);
  596. ClassDB::bind_method(D_METHOD("create_from_image_alpha", "image", "threshold"), &BitMap::create_from_image_alpha, DEFVAL(0.1));
  597. ClassDB::bind_method(D_METHOD("set_bitv", "position", "bit"), &BitMap::set_bitv);
  598. ClassDB::bind_method(D_METHOD("set_bit", "x", "y", "bit"), &BitMap::set_bit);
  599. ClassDB::bind_method(D_METHOD("get_bitv", "position"), &BitMap::get_bitv);
  600. ClassDB::bind_method(D_METHOD("get_bit", "x", "y"), &BitMap::get_bit);
  601. ClassDB::bind_method(D_METHOD("set_bit_rect", "rect", "bit"), &BitMap::set_bit_rect);
  602. ClassDB::bind_method(D_METHOD("get_true_bit_count"), &BitMap::get_true_bit_count);
  603. ClassDB::bind_method(D_METHOD("get_size"), &BitMap::get_size);
  604. ClassDB::bind_method(D_METHOD("resize", "new_size"), &BitMap::resize);
  605. ClassDB::bind_method(D_METHOD("_set_data", "data"), &BitMap::_set_data);
  606. ClassDB::bind_method(D_METHOD("_get_data"), &BitMap::_get_data);
  607. ClassDB::bind_method(D_METHOD("grow_mask", "pixels", "rect"), &BitMap::grow_mask);
  608. ClassDB::bind_method(D_METHOD("convert_to_image"), &BitMap::convert_to_image);
  609. ClassDB::bind_method(D_METHOD("opaque_to_polygons", "rect", "epsilon"), &BitMap::_opaque_to_polygons_bind, DEFVAL(2.0));
  610. ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data");
  611. }
  612. BitMap::BitMap() {}