You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

mat_pixel_drawing.cpp 40 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527
  1. // Tencent is pleased to support the open source community by making ncnn available.
  2. //
  3. // Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
  4. //
  5. // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // https://opensource.org/licenses/BSD-3-Clause
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed
  11. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  12. // CONDITIONS OF ANY KIND, either express or implied. See the License for the
  13. // specific language governing permissions and limitations under the License.
  14. #include "mat.h"
  15. #include <ctype.h>
  16. #include "platform.h"
  17. namespace ncnn {
  18. #if NCNN_PIXEL_DRAWING
  19. #include "mat_pixel_drawing_font.h"
  20. void draw_rectangle_c1(unsigned char* pixels, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
  21. {
  22. return draw_rectangle_c1(pixels, w, h, w, rx, ry, rw, rh, color, thickness);
  23. }
  24. void draw_rectangle_c2(unsigned char* pixels, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
  25. {
  26. return draw_rectangle_c2(pixels, w, h, w * 2, rx, ry, rw, rh, color, thickness);
  27. }
  28. void draw_rectangle_c3(unsigned char* pixels, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
  29. {
  30. return draw_rectangle_c3(pixels, w, h, w * 3, rx, ry, rw, rh, color, thickness);
  31. }
  32. void draw_rectangle_c4(unsigned char* pixels, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
  33. {
  34. return draw_rectangle_c4(pixels, w, h, w * 4, rx, ry, rw, rh, color, thickness);
  35. }
  36. void draw_rectangle_c1(unsigned char* pixels, int w, int h, int stride, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
  37. {
  38. const unsigned char* pen_color = (const unsigned char*)&color;
  39. if (thickness == -1)
  40. {
  41. // filled
  42. for (int y = ry; y < ry + rh; y++)
  43. {
  44. if (y < 0)
  45. continue;
  46. if (y >= h)
  47. break;
  48. unsigned char* p = pixels + stride * y;
  49. for (int x = rx; x < rx + rw; x++)
  50. {
  51. if (x < 0)
  52. continue;
  53. if (x >= w)
  54. break;
  55. p[x] = pen_color[0];
  56. }
  57. }
  58. return;
  59. }
  60. const int t0 = thickness / 2;
  61. const int t1 = thickness - t0;
  62. // draw top
  63. {
  64. for (int y = ry - t0; y < ry + t1; y++)
  65. {
  66. if (y < 0)
  67. continue;
  68. if (y >= h)
  69. break;
  70. unsigned char* p = pixels + stride * y;
  71. for (int x = rx - t0; x < rx + rw + t1; x++)
  72. {
  73. if (x < 0)
  74. continue;
  75. if (x >= w)
  76. break;
  77. p[x] = pen_color[0];
  78. }
  79. }
  80. }
  81. // draw bottom
  82. {
  83. for (int y = ry + rh - t0; y < ry + rh + t1; y++)
  84. {
  85. if (y < 0)
  86. continue;
  87. if (y >= h)
  88. break;
  89. unsigned char* p = pixels + stride * y;
  90. for (int x = rx - t0; x < rx + rw + t1; x++)
  91. {
  92. if (x < 0)
  93. continue;
  94. if (x >= w)
  95. break;
  96. p[x] = pen_color[0];
  97. }
  98. }
  99. }
  100. // draw left
  101. for (int x = rx - t0; x < rx + t1; x++)
  102. {
  103. if (x < 0)
  104. continue;
  105. if (x >= w)
  106. break;
  107. for (int y = ry + t1; y < ry + rh - t0; y++)
  108. {
  109. if (y < 0)
  110. continue;
  111. if (y >= h)
  112. break;
  113. unsigned char* p = pixels + stride * y;
  114. p[x] = pen_color[0];
  115. }
  116. }
  117. // draw right
  118. for (int x = rx + rw - t0; x < rx + rw + t1; x++)
  119. {
  120. if (x < 0)
  121. continue;
  122. if (x >= w)
  123. break;
  124. for (int y = ry + t1; y < ry + rh - t0; y++)
  125. {
  126. if (y < 0)
  127. continue;
  128. if (y >= h)
  129. break;
  130. unsigned char* p = pixels + stride * y;
  131. p[x] = pen_color[0];
  132. }
  133. }
  134. }
  135. void draw_rectangle_c2(unsigned char* pixels, int w, int h, int stride, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
  136. {
  137. const unsigned char* pen_color = (const unsigned char*)&color;
  138. if (thickness == -1)
  139. {
  140. // filled
  141. for (int y = ry; y < ry + rh; y++)
  142. {
  143. if (y < 0)
  144. continue;
  145. if (y >= h)
  146. break;
  147. unsigned char* p = pixels + stride * y;
  148. for (int x = rx; x < rx + rw; x++)
  149. {
  150. if (x < 0)
  151. continue;
  152. if (x >= w)
  153. break;
  154. p[x * 2 + 0] = pen_color[0];
  155. p[x * 2 + 1] = pen_color[1];
  156. }
  157. }
  158. return;
  159. }
  160. const int t0 = thickness / 2;
  161. const int t1 = thickness - t0;
  162. // draw top
  163. {
  164. for (int y = ry - t0; y < ry + t1; y++)
  165. {
  166. if (y < 0)
  167. continue;
  168. if (y >= h)
  169. break;
  170. unsigned char* p = pixels + stride * y;
  171. for (int x = rx - t0; x < rx + rw + t1; x++)
  172. {
  173. if (x < 0)
  174. continue;
  175. if (x >= w)
  176. break;
  177. p[x * 2 + 0] = pen_color[0];
  178. p[x * 2 + 1] = pen_color[1];
  179. }
  180. }
  181. }
  182. // draw bottom
  183. {
  184. for (int y = ry + rh - t0; y < ry + rh + t1; y++)
  185. {
  186. if (y < 0)
  187. continue;
  188. if (y >= h)
  189. break;
  190. unsigned char* p = pixels + stride * y;
  191. for (int x = rx - t0; x < rx + rw + t1; x++)
  192. {
  193. if (x < 0)
  194. continue;
  195. if (x >= w)
  196. break;
  197. p[x * 2 + 0] = pen_color[0];
  198. p[x * 2 + 1] = pen_color[1];
  199. }
  200. }
  201. }
  202. // draw left
  203. for (int x = rx - t0; x < rx + t1; x++)
  204. {
  205. if (x < 0)
  206. continue;
  207. if (x >= w)
  208. break;
  209. for (int y = ry + t1; y < ry + rh - t0; y++)
  210. {
  211. if (y < 0)
  212. continue;
  213. if (y >= h)
  214. break;
  215. unsigned char* p = pixels + stride * y;
  216. p[x * 2 + 0] = pen_color[0];
  217. p[x * 2 + 1] = pen_color[1];
  218. }
  219. }
  220. // draw right
  221. for (int x = rx + rw - t0; x < rx + rw + t1; x++)
  222. {
  223. if (x < 0)
  224. continue;
  225. if (x >= w)
  226. break;
  227. for (int y = ry + t1; y < ry + rh - t0; y++)
  228. {
  229. if (y < 0)
  230. continue;
  231. if (y >= h)
  232. break;
  233. unsigned char* p = pixels + stride * y;
  234. p[x * 2 + 0] = pen_color[0];
  235. p[x * 2 + 1] = pen_color[1];
  236. }
  237. }
  238. }
  239. void draw_rectangle_c3(unsigned char* pixels, int w, int h, int stride, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
  240. {
  241. const unsigned char* pen_color = (const unsigned char*)&color;
  242. if (thickness == -1)
  243. {
  244. // filled
  245. for (int y = ry; y < ry + rh; y++)
  246. {
  247. if (y < 0)
  248. continue;
  249. if (y >= h)
  250. break;
  251. unsigned char* p = pixels + stride * y;
  252. for (int x = rx; x < rx + rw; x++)
  253. {
  254. if (x < 0)
  255. continue;
  256. if (x >= w)
  257. break;
  258. p[x * 3 + 0] = pen_color[0];
  259. p[x * 3 + 1] = pen_color[1];
  260. p[x * 3 + 2] = pen_color[2];
  261. }
  262. }
  263. return;
  264. }
  265. const int t0 = thickness / 2;
  266. const int t1 = thickness - t0;
  267. // draw top
  268. {
  269. for (int y = ry - t0; y < ry + t1; y++)
  270. {
  271. if (y < 0)
  272. continue;
  273. if (y >= h)
  274. break;
  275. unsigned char* p = pixels + stride * y;
  276. for (int x = rx - t0; x < rx + rw + t1; x++)
  277. {
  278. if (x < 0)
  279. continue;
  280. if (x >= w)
  281. break;
  282. p[x * 3 + 0] = pen_color[0];
  283. p[x * 3 + 1] = pen_color[1];
  284. p[x * 3 + 2] = pen_color[2];
  285. }
  286. }
  287. }
  288. // draw bottom
  289. {
  290. for (int y = ry + rh - t0; y < ry + rh + t1; y++)
  291. {
  292. if (y < 0)
  293. continue;
  294. if (y >= h)
  295. break;
  296. unsigned char* p = pixels + stride * y;
  297. for (int x = rx - t0; x < rx + rw + t1; x++)
  298. {
  299. if (x < 0)
  300. continue;
  301. if (x >= w)
  302. break;
  303. p[x * 3 + 0] = pen_color[0];
  304. p[x * 3 + 1] = pen_color[1];
  305. p[x * 3 + 2] = pen_color[2];
  306. }
  307. }
  308. }
  309. // draw left
  310. for (int x = rx - t0; x < rx + t1; x++)
  311. {
  312. if (x < 0)
  313. continue;
  314. if (x >= w)
  315. break;
  316. for (int y = ry + t1; y < ry + rh - t0; y++)
  317. {
  318. if (y < 0)
  319. continue;
  320. if (y >= h)
  321. break;
  322. unsigned char* p = pixels + stride * y;
  323. p[x * 3 + 0] = pen_color[0];
  324. p[x * 3 + 1] = pen_color[1];
  325. p[x * 3 + 2] = pen_color[2];
  326. }
  327. }
  328. // draw right
  329. for (int x = rx + rw - t0; x < rx + rw + t1; x++)
  330. {
  331. if (x < 0)
  332. continue;
  333. if (x >= w)
  334. break;
  335. for (int y = ry + t1; y < ry + rh - t0; y++)
  336. {
  337. if (y < 0)
  338. continue;
  339. if (y >= h)
  340. break;
  341. unsigned char* p = pixels + stride * y;
  342. p[x * 3 + 0] = pen_color[0];
  343. p[x * 3 + 1] = pen_color[1];
  344. p[x * 3 + 2] = pen_color[2];
  345. }
  346. }
  347. }
  348. void draw_rectangle_c4(unsigned char* pixels, int w, int h, int stride, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
  349. {
  350. const unsigned char* pen_color = (const unsigned char*)&color;
  351. if (thickness == -1)
  352. {
  353. // filled
  354. for (int y = ry; y < ry + rh; y++)
  355. {
  356. if (y < 0)
  357. continue;
  358. if (y >= h)
  359. break;
  360. unsigned char* p = pixels + stride * y;
  361. for (int x = rx; x < rx + rw; x++)
  362. {
  363. if (x < 0)
  364. continue;
  365. if (x >= w)
  366. break;
  367. p[x * 4 + 0] = pen_color[0];
  368. p[x * 4 + 1] = pen_color[1];
  369. p[x * 4 + 2] = pen_color[2];
  370. p[x * 4 + 3] = pen_color[3];
  371. }
  372. }
  373. return;
  374. }
  375. const int t0 = thickness / 2;
  376. const int t1 = thickness - t0;
  377. // draw top
  378. {
  379. for (int y = ry - t0; y < ry + t1; y++)
  380. {
  381. if (y < 0)
  382. continue;
  383. if (y >= h)
  384. break;
  385. unsigned char* p = pixels + stride * y;
  386. for (int x = rx - t0; x < rx + rw + t1; x++)
  387. {
  388. if (x < 0)
  389. continue;
  390. if (x >= w)
  391. break;
  392. p[x * 4 + 0] = pen_color[0];
  393. p[x * 4 + 1] = pen_color[1];
  394. p[x * 4 + 2] = pen_color[2];
  395. p[x * 4 + 3] = pen_color[3];
  396. }
  397. }
  398. }
  399. // draw bottom
  400. {
  401. for (int y = ry + rh - t0; y < ry + rh + t1; y++)
  402. {
  403. if (y < 0)
  404. continue;
  405. if (y >= h)
  406. break;
  407. unsigned char* p = pixels + stride * y;
  408. for (int x = rx - t0; x < rx + rw + t1; x++)
  409. {
  410. if (x < 0)
  411. continue;
  412. if (x >= w)
  413. break;
  414. p[x * 4 + 0] = pen_color[0];
  415. p[x * 4 + 1] = pen_color[1];
  416. p[x * 4 + 2] = pen_color[2];
  417. p[x * 4 + 3] = pen_color[3];
  418. }
  419. }
  420. }
  421. // draw left
  422. for (int x = rx - t0; x < rx + t1; x++)
  423. {
  424. if (x < 0)
  425. continue;
  426. if (x >= w)
  427. break;
  428. for (int y = ry + t1; y < ry + rh - t0; y++)
  429. {
  430. if (y < 0)
  431. continue;
  432. if (y >= h)
  433. break;
  434. unsigned char* p = pixels + stride * y;
  435. p[x * 4 + 0] = pen_color[0];
  436. p[x * 4 + 1] = pen_color[1];
  437. p[x * 4 + 2] = pen_color[2];
  438. p[x * 4 + 3] = pen_color[3];
  439. }
  440. }
  441. // draw right
  442. for (int x = rx + rw - t0; x < rx + rw + t1; x++)
  443. {
  444. if (x < 0)
  445. continue;
  446. if (x >= w)
  447. break;
  448. for (int y = ry + t1; y < ry + rh - t0; y++)
  449. {
  450. if (y < 0)
  451. continue;
  452. if (y >= h)
  453. break;
  454. unsigned char* p = pixels + stride * y;
  455. p[x * 4 + 0] = pen_color[0];
  456. p[x * 4 + 1] = pen_color[1];
  457. p[x * 4 + 2] = pen_color[2];
  458. p[x * 4 + 3] = pen_color[3];
  459. }
  460. }
  461. }
  462. void draw_rectangle_yuv420sp(unsigned char* yuv420sp, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
  463. {
  464. // assert w % 2 == 0
  465. // assert h % 2 == 0
  466. // assert rx % 2 == 0
  467. // assert ry % 2 == 0
  468. // assert rw % 2 == 0
  469. // assert rh % 2 == 0
  470. // assert thickness % 2 == 0
  471. const unsigned char* pen_color = (const unsigned char*)&color;
  472. unsigned int v_y;
  473. unsigned int v_uv;
  474. unsigned char* pen_color_y = (unsigned char*)&v_y;
  475. unsigned char* pen_color_uv = (unsigned char*)&v_uv;
  476. pen_color_y[0] = pen_color[0];
  477. pen_color_uv[0] = pen_color[1];
  478. pen_color_uv[1] = pen_color[2];
  479. unsigned char* Y = yuv420sp;
  480. draw_rectangle_c1(Y, w, h, rx, ry, rw, rh, v_y, thickness);
  481. unsigned char* UV = yuv420sp + w * h;
  482. int thickness_uv = thickness == -1 ? thickness : std::max(thickness / 2, 1);
  483. draw_rectangle_c2(UV, w / 2, h / 2, rx / 2, ry / 2, rw / 2, rh / 2, v_uv, thickness_uv);
  484. }
  485. static inline bool distance_lessequal(int x0, int y0, int x1, int y1, float r)
  486. {
  487. int dx = x0 - x1;
  488. int dy = y0 - y1;
  489. int q = dx * dx + dy * dy;
  490. return q <= r * r;
  491. }
  492. static inline bool distance_inrange(int x0, int y0, int x1, int y1, float r0, float r1)
  493. {
  494. int dx = x0 - x1;
  495. int dy = y0 - y1;
  496. int q = dx * dx + dy * dy;
  497. return q >= r0 * r0 && q < r1 * r1;
  498. }
  499. void draw_circle_c1(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
  500. {
  501. return draw_circle_c1(pixels, w, h, w, cx, cy, radius, color, thickness);
  502. }
  503. void draw_circle_c2(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
  504. {
  505. return draw_circle_c2(pixels, w, h, w * 2, cx, cy, radius, color, thickness);
  506. }
  507. void draw_circle_c3(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
  508. {
  509. return draw_circle_c3(pixels, w, h, w * 3, cx, cy, radius, color, thickness);
  510. }
  511. void draw_circle_c4(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
  512. {
  513. return draw_circle_c4(pixels, w, h, w * 4, cx, cy, radius, color, thickness);
  514. }
  515. void draw_circle_c1(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
  516. {
  517. const unsigned char* pen_color = (const unsigned char*)&color;
  518. if (thickness == -1)
  519. {
  520. // filled
  521. for (int y = cy - (radius - 1); y < cy + radius; y++)
  522. {
  523. if (y < 0)
  524. continue;
  525. if (y >= h)
  526. break;
  527. unsigned char* p = pixels + stride * y;
  528. for (int x = cx - (radius - 1); x < cx + radius; x++)
  529. {
  530. if (x < 0)
  531. continue;
  532. if (x >= w)
  533. break;
  534. // distance from cx cy
  535. if (distance_lessequal(x, y, cx, cy, radius))
  536. {
  537. p[x] = pen_color[0];
  538. }
  539. }
  540. }
  541. return;
  542. }
  543. const float t0 = thickness / 2.f;
  544. const float t1 = thickness - t0;
  545. for (int y = cy - (radius - 1) - t0; y < cy + radius + t1; y++)
  546. {
  547. if (y < 0)
  548. continue;
  549. if (y >= h)
  550. break;
  551. unsigned char* p = pixels + stride * y;
  552. for (int x = cx - (radius - 1) - t0; x < cx + radius + t1; x++)
  553. {
  554. if (x < 0)
  555. continue;
  556. if (x >= w)
  557. break;
  558. // distance from cx cy
  559. if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
  560. {
  561. p[x] = pen_color[0];
  562. }
  563. }
  564. }
  565. }
  566. void draw_circle_c2(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
  567. {
  568. const unsigned char* pen_color = (const unsigned char*)&color;
  569. if (thickness == -1)
  570. {
  571. // filled
  572. for (int y = cy - (radius - 1); y < cy + radius; y++)
  573. {
  574. if (y < 0)
  575. continue;
  576. if (y >= h)
  577. break;
  578. unsigned char* p = pixels + stride * y;
  579. for (int x = cx - (radius - 1); x < cx + radius; x++)
  580. {
  581. if (x < 0)
  582. continue;
  583. if (x >= w)
  584. break;
  585. // distance from cx cy
  586. if (distance_lessequal(x, y, cx, cy, radius))
  587. {
  588. p[x * 2 + 0] = pen_color[0];
  589. p[x * 2 + 1] = pen_color[1];
  590. }
  591. }
  592. }
  593. return;
  594. }
  595. const float t0 = thickness / 2.f;
  596. const float t1 = thickness - t0;
  597. for (int y = cy - radius - t0; y < cy + radius + t1; y++)
  598. {
  599. if (y < 0)
  600. continue;
  601. if (y >= h)
  602. break;
  603. unsigned char* p = pixels + stride * y;
  604. for (int x = cx - radius - t0; x < cx + radius + t1; x++)
  605. {
  606. if (x < 0)
  607. continue;
  608. if (x >= w)
  609. break;
  610. // distance from cx cy
  611. if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
  612. {
  613. p[x * 2 + 0] = pen_color[0];
  614. p[x * 2 + 1] = pen_color[1];
  615. }
  616. }
  617. }
  618. }
  619. void draw_circle_c3(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
  620. {
  621. const unsigned char* pen_color = (const unsigned char*)&color;
  622. if (thickness == -1)
  623. {
  624. // filled
  625. for (int y = cy - (radius - 1); y < cy + radius; y++)
  626. {
  627. if (y < 0)
  628. continue;
  629. if (y >= h)
  630. break;
  631. unsigned char* p = pixels + stride * y;
  632. for (int x = cx - (radius - 1); x < cx + radius; x++)
  633. {
  634. if (x < 0)
  635. continue;
  636. if (x >= w)
  637. break;
  638. // distance from cx cy
  639. if (distance_lessequal(x, y, cx, cy, radius))
  640. {
  641. p[x * 3 + 0] = pen_color[0];
  642. p[x * 3 + 1] = pen_color[1];
  643. p[x * 3 + 2] = pen_color[2];
  644. }
  645. }
  646. }
  647. return;
  648. }
  649. const float t0 = thickness / 2.f;
  650. const float t1 = thickness - t0;
  651. for (int y = cy - radius - t0; y < cy + radius + t1; y++)
  652. {
  653. if (y < 0)
  654. continue;
  655. if (y >= h)
  656. break;
  657. unsigned char* p = pixels + stride * y;
  658. for (int x = cx - radius - t0; x < cx + radius + t1; x++)
  659. {
  660. if (x < 0)
  661. continue;
  662. if (x >= w)
  663. break;
  664. // distance from cx cy
  665. if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
  666. {
  667. p[x * 3 + 0] = pen_color[0];
  668. p[x * 3 + 1] = pen_color[1];
  669. p[x * 3 + 2] = pen_color[2];
  670. }
  671. }
  672. }
  673. }
  674. void draw_circle_c4(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
  675. {
  676. const unsigned char* pen_color = (const unsigned char*)&color;
  677. if (thickness == -1)
  678. {
  679. // filled
  680. for (int y = cy - (radius - 1); y < cy + radius; y++)
  681. {
  682. if (y < 0)
  683. continue;
  684. if (y >= h)
  685. break;
  686. unsigned char* p = pixels + stride * y;
  687. for (int x = cx - (radius - 1); x < cx + radius; x++)
  688. {
  689. if (x < 0)
  690. continue;
  691. if (x >= w)
  692. break;
  693. // distance from cx cy
  694. if (distance_lessequal(x, y, cx, cy, radius))
  695. {
  696. p[x * 4 + 0] = pen_color[0];
  697. p[x * 4 + 1] = pen_color[1];
  698. p[x * 4 + 2] = pen_color[2];
  699. p[x * 4 + 3] = pen_color[3];
  700. }
  701. }
  702. }
  703. return;
  704. }
  705. const float t0 = thickness / 2.f;
  706. const float t1 = thickness - t0;
  707. for (int y = cy - (radius - 1) - t0; y < cy + radius + t1; y++)
  708. {
  709. if (y < 0)
  710. continue;
  711. if (y >= h)
  712. break;
  713. unsigned char* p = pixels + stride * y;
  714. for (int x = cx - (radius - 1) - t0; x < cx + radius + t1; x++)
  715. {
  716. if (x < 0)
  717. continue;
  718. if (x >= w)
  719. break;
  720. // distance from cx cy
  721. if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
  722. {
  723. p[x * 4 + 0] = pen_color[0];
  724. p[x * 4 + 1] = pen_color[1];
  725. p[x * 4 + 2] = pen_color[2];
  726. p[x * 4 + 3] = pen_color[3];
  727. }
  728. }
  729. }
  730. }
  731. void draw_circle_yuv420sp(unsigned char* yuv420sp, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
  732. {
  733. // assert w % 2 == 0
  734. // assert h % 2 == 0
  735. // assert cx % 2 == 0
  736. // assert cy % 2 == 0
  737. // assert radius % 2 == 0
  738. // assert thickness % 2 == 0
  739. const unsigned char* pen_color = (const unsigned char*)&color;
  740. unsigned int v_y;
  741. unsigned int v_uv;
  742. unsigned char* pen_color_y = (unsigned char*)&v_y;
  743. unsigned char* pen_color_uv = (unsigned char*)&v_uv;
  744. pen_color_y[0] = pen_color[0];
  745. pen_color_uv[0] = pen_color[1];
  746. pen_color_uv[1] = pen_color[2];
  747. unsigned char* Y = yuv420sp;
  748. draw_circle_c1(Y, w, h, cx, cy, radius, v_y, thickness);
  749. unsigned char* UV = yuv420sp + w * h;
  750. int thickness_uv = thickness == -1 ? thickness : std::max(thickness / 2, 1);
  751. draw_circle_c2(UV, w / 2, h / 2, cx / 2, cy / 2, radius / 2, v_uv, thickness_uv);
  752. }
  753. static inline bool distance_lessthan(int x, int y, int x0, int y0, int x1, int y1, float t)
  754. {
  755. int dx01 = x1 - x0;
  756. int dy01 = y1 - y0;
  757. int dx0 = x - x0;
  758. int dy0 = y - y0;
  759. float r = (float)(dx0 * dx01 + dy0 * dy01) / (dx01 * dx01 + dy01 * dy01);
  760. if (r < 0 || r > 1)
  761. return false;
  762. float px = x0 + dx01 * r;
  763. float py = y0 + dy01 * r;
  764. float dx = x - px;
  765. float dy = y - py;
  766. float p = dx * dx + dy * dy;
  767. return p < t;
  768. }
  769. void draw_line_c1(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
  770. {
  771. draw_line_c1(pixels, w, h, w, x0, y0, x1, y1, color, thickness);
  772. }
  773. void draw_line_c2(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
  774. {
  775. draw_line_c2(pixels, w, h, w * 2, x0, y0, x1, y1, color, thickness);
  776. }
  777. void draw_line_c3(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
  778. {
  779. draw_line_c3(pixels, w, h, w * 3, x0, y0, x1, y1, color, thickness);
  780. }
  781. void draw_line_c4(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
  782. {
  783. draw_line_c4(pixels, w, h, w * 4, x0, y0, x1, y1, color, thickness);
  784. }
  785. void draw_line_c1(unsigned char* pixels, int w, int h, int stride, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
  786. {
  787. const unsigned char* pen_color = (const unsigned char*)&color;
  788. const float t0 = thickness / 2.f;
  789. const float t1 = thickness - t0;
  790. int x_min = std::min(x0, x1);
  791. int x_max = std::max(x0, x1);
  792. int y_min = std::min(y0, y1);
  793. int y_max = std::max(y0, y1);
  794. for (int y = y_min - t0; y < y_max + t1; y++)
  795. {
  796. if (y < 0)
  797. continue;
  798. if (y >= h)
  799. break;
  800. unsigned char* p = pixels + stride * y;
  801. for (int x = x_min - t0; x < x_max + t1; x++)
  802. {
  803. if (x < 0)
  804. continue;
  805. if (x >= w)
  806. break;
  807. // distance from line
  808. if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
  809. {
  810. p[x] = pen_color[0];
  811. }
  812. }
  813. }
  814. }
  815. void draw_line_c2(unsigned char* pixels, int w, int h, int stride, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
  816. {
  817. const unsigned char* pen_color = (const unsigned char*)&color;
  818. const float t0 = thickness / 2.f;
  819. const float t1 = thickness - t0;
  820. int x_min = std::min(x0, x1);
  821. int x_max = std::max(x0, x1);
  822. int y_min = std::min(y0, y1);
  823. int y_max = std::max(y0, y1);
  824. for (int y = y_min - t0; y < y_max + t1; y++)
  825. {
  826. if (y < 0)
  827. continue;
  828. if (y >= h)
  829. break;
  830. unsigned char* p = pixels + stride * y;
  831. for (int x = x_min - t0; x < x_max + t1; x++)
  832. {
  833. if (x < 0)
  834. continue;
  835. if (x >= w)
  836. break;
  837. // distance from line
  838. if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
  839. {
  840. p[x * 2 + 0] = pen_color[0];
  841. p[x * 2 + 1] = pen_color[1];
  842. }
  843. }
  844. }
  845. }
  846. void draw_line_c3(unsigned char* pixels, int w, int h, int stride, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
  847. {
  848. const unsigned char* pen_color = (const unsigned char*)&color;
  849. const float t0 = thickness / 2.f;
  850. const float t1 = thickness - t0;
  851. int x_min = std::min(x0, x1);
  852. int x_max = std::max(x0, x1);
  853. int y_min = std::min(y0, y1);
  854. int y_max = std::max(y0, y1);
  855. for (int y = y_min - t0; y < y_max + t1; y++)
  856. {
  857. if (y < 0)
  858. continue;
  859. if (y >= h)
  860. break;
  861. unsigned char* p = pixels + stride * y;
  862. for (int x = x_min - t0; x < x_max + t1; x++)
  863. {
  864. if (x < 0)
  865. continue;
  866. if (x >= w)
  867. break;
  868. // distance from line
  869. if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
  870. {
  871. p[x * 3 + 0] = pen_color[0];
  872. p[x * 3 + 1] = pen_color[1];
  873. p[x * 3 + 2] = pen_color[2];
  874. }
  875. }
  876. }
  877. }
  878. void draw_line_c4(unsigned char* pixels, int w, int h, int stride, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
  879. {
  880. const unsigned char* pen_color = (const unsigned char*)&color;
  881. const float t0 = thickness / 2.f;
  882. const float t1 = thickness - t0;
  883. int x_min = std::min(x0, x1);
  884. int x_max = std::max(x0, x1);
  885. int y_min = std::min(y0, y1);
  886. int y_max = std::max(y0, y1);
  887. for (int y = y_min - t0; y < y_max + t1; y++)
  888. {
  889. if (y < 0)
  890. continue;
  891. if (y >= h)
  892. break;
  893. unsigned char* p = pixels + stride * y;
  894. for (int x = x_min - t0; x < x_max + t1; x++)
  895. {
  896. if (x < 0)
  897. continue;
  898. if (x >= w)
  899. break;
  900. // distance from line
  901. if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
  902. {
  903. p[x * 4 + 0] = pen_color[0];
  904. p[x * 4 + 1] = pen_color[1];
  905. p[x * 4 + 2] = pen_color[2];
  906. p[x * 4 + 3] = pen_color[3];
  907. }
  908. }
  909. }
  910. }
  911. void draw_line_yuv420sp(unsigned char* yuv420sp, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
  912. {
  913. // assert w % 2 == 0
  914. // assert h % 2 == 0
  915. // assert x0 % 2 == 0
  916. // assert y0 % 2 == 0
  917. // assert x1 % 2 == 0
  918. // assert y1 % 2 == 0
  919. // assert thickness % 2 == 0
  920. const unsigned char* pen_color = (const unsigned char*)&color;
  921. unsigned int v_y;
  922. unsigned int v_uv;
  923. unsigned char* pen_color_y = (unsigned char*)&v_y;
  924. unsigned char* pen_color_uv = (unsigned char*)&v_uv;
  925. pen_color_y[0] = pen_color[0];
  926. pen_color_uv[0] = pen_color[1];
  927. pen_color_uv[1] = pen_color[2];
  928. unsigned char* Y = yuv420sp;
  929. draw_line_c1(Y, w, h, x0, y0, x1, y1, v_y, thickness);
  930. unsigned char* UV = yuv420sp + w * h;
  931. int thickness_uv = thickness == -1 ? thickness : std::max(thickness / 2, 1);
  932. draw_line_c2(UV, w / 2, h / 2, x0 / 2, y0 / 2, x1 / 2, y1 / 2, v_uv, thickness_uv);
  933. }
  934. void get_text_drawing_size(const char* text, int fontpixelsize, int* w, int* h)
  935. {
  936. *w = 0;
  937. *h = 0;
  938. const int n = strlen(text);
  939. int line_w = 0;
  940. for (int i = 0; i < n; i++)
  941. {
  942. char ch = text[i];
  943. if (ch == '\n')
  944. {
  945. // newline
  946. *w = std::max(*w, line_w);
  947. *h += fontpixelsize * 2;
  948. line_w = 0;
  949. }
  950. if (isprint(ch) != 0)
  951. {
  952. line_w += fontpixelsize;
  953. }
  954. }
  955. *w = std::max(*w, line_w);
  956. *h += fontpixelsize * 2;
  957. }
  958. void draw_text_c1(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
  959. {
  960. return draw_text_c1(pixels, w, h, w, text, x, y, fontpixelsize, color);
  961. }
  962. void draw_text_c2(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
  963. {
  964. return draw_text_c2(pixels, w, h, w * 2, text, x, y, fontpixelsize, color);
  965. }
  966. void draw_text_c3(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
  967. {
  968. return draw_text_c3(pixels, w, h, w * 3, text, x, y, fontpixelsize, color);
  969. }
  970. void draw_text_c4(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
  971. {
  972. return draw_text_c4(pixels, w, h, w * 4, text, x, y, fontpixelsize, color);
  973. }
  974. void draw_text_c1(unsigned char* pixels, int w, int h, int stride, const char* text, int x, int y, int fontpixelsize, unsigned int color)
  975. {
  976. const unsigned char* pen_color = (const unsigned char*)&color;
  977. unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
  978. const int n = strlen(text);
  979. int cursor_x = x;
  980. int cursor_y = y;
  981. for (int i = 0; i < n; i++)
  982. {
  983. char ch = text[i];
  984. if (ch == '\n')
  985. {
  986. // newline
  987. cursor_x = x;
  988. cursor_y += fontpixelsize * 2;
  989. }
  990. if (isprint(ch) != 0)
  991. {
  992. const unsigned char* font_bitmap = mono_font_data[ch - ' '];
  993. // draw resized character
  994. resize_bilinear_c1(font_bitmap, 20, 40, resized_font_bitmap, fontpixelsize, fontpixelsize * 2);
  995. for (int j = cursor_y; j < cursor_y + fontpixelsize * 2; j++)
  996. {
  997. if (j < 0)
  998. continue;
  999. if (j >= h)
  1000. break;
  1001. const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize;
  1002. unsigned char* p = pixels + stride * j;
  1003. for (int k = cursor_x; k < cursor_x + fontpixelsize; k++)
  1004. {
  1005. if (k < 0)
  1006. continue;
  1007. if (k >= w)
  1008. break;
  1009. unsigned char alpha = palpha[k - cursor_x];
  1010. p[k] = (p[k] * (255 - alpha) + pen_color[0] * alpha) / 255;
  1011. }
  1012. }
  1013. cursor_x += fontpixelsize;
  1014. }
  1015. }
  1016. delete[] resized_font_bitmap;
  1017. }
  1018. void draw_text_c2(unsigned char* pixels, int w, int h, int stride, const char* text, int x, int y, int fontpixelsize, unsigned int color)
  1019. {
  1020. const unsigned char* pen_color = (const unsigned char*)&color;
  1021. unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
  1022. const int n = strlen(text);
  1023. int cursor_x = x;
  1024. int cursor_y = y;
  1025. for (int i = 0; i < n; i++)
  1026. {
  1027. char ch = text[i];
  1028. if (ch == '\n')
  1029. {
  1030. // newline
  1031. cursor_x = x;
  1032. cursor_y += fontpixelsize * 2;
  1033. }
  1034. if (isprint(ch) != 0)
  1035. {
  1036. int font_bitmap_index = ch - ' ';
  1037. const unsigned char* font_bitmap = mono_font_data[font_bitmap_index];
  1038. // draw resized character
  1039. resize_bilinear_c1(font_bitmap, 20, 40, resized_font_bitmap, fontpixelsize, fontpixelsize * 2);
  1040. for (int j = cursor_y; j < cursor_y + fontpixelsize * 2; j++)
  1041. {
  1042. if (j < 0)
  1043. continue;
  1044. if (j >= h)
  1045. break;
  1046. const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize;
  1047. unsigned char* p = pixels + stride * j;
  1048. for (int k = cursor_x; k < cursor_x + fontpixelsize; k++)
  1049. {
  1050. if (k < 0)
  1051. continue;
  1052. if (k >= w)
  1053. break;
  1054. unsigned char alpha = palpha[k - cursor_x];
  1055. p[k * 2 + 0] = (p[k * 2 + 0] * (255 - alpha) + pen_color[0] * alpha) / 255;
  1056. p[k * 2 + 1] = (p[k * 2 + 1] * (255 - alpha) + pen_color[1] * alpha) / 255;
  1057. }
  1058. }
  1059. cursor_x += fontpixelsize;
  1060. }
  1061. }
  1062. delete[] resized_font_bitmap;
  1063. }
  1064. void draw_text_c3(unsigned char* pixels, int w, int h, int stride, const char* text, int x, int y, int fontpixelsize, unsigned int color)
  1065. {
  1066. const unsigned char* pen_color = (const unsigned char*)&color;
  1067. unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
  1068. const int n = strlen(text);
  1069. int cursor_x = x;
  1070. int cursor_y = y;
  1071. for (int i = 0; i < n; i++)
  1072. {
  1073. char ch = text[i];
  1074. if (ch == '\n')
  1075. {
  1076. // newline
  1077. cursor_x = x;
  1078. cursor_y += fontpixelsize * 2;
  1079. }
  1080. if (isprint(ch) != 0)
  1081. {
  1082. int font_bitmap_index = ch - ' ';
  1083. const unsigned char* font_bitmap = mono_font_data[font_bitmap_index];
  1084. // draw resized character
  1085. resize_bilinear_c1(font_bitmap, 20, 40, resized_font_bitmap, fontpixelsize, fontpixelsize * 2);
  1086. for (int j = cursor_y; j < cursor_y + fontpixelsize * 2; j++)
  1087. {
  1088. if (j < 0)
  1089. continue;
  1090. if (j >= h)
  1091. break;
  1092. const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize;
  1093. unsigned char* p = pixels + stride * j;
  1094. for (int k = cursor_x; k < cursor_x + fontpixelsize; k++)
  1095. {
  1096. if (k < 0)
  1097. continue;
  1098. if (k >= w)
  1099. break;
  1100. unsigned char alpha = palpha[k - cursor_x];
  1101. p[k * 3 + 0] = (p[k * 3 + 0] * (255 - alpha) + pen_color[0] * alpha) / 255;
  1102. p[k * 3 + 1] = (p[k * 3 + 1] * (255 - alpha) + pen_color[1] * alpha) / 255;
  1103. p[k * 3 + 2] = (p[k * 3 + 2] * (255 - alpha) + pen_color[2] * alpha) / 255;
  1104. }
  1105. }
  1106. cursor_x += fontpixelsize;
  1107. }
  1108. }
  1109. delete[] resized_font_bitmap;
  1110. }
  1111. void draw_text_c4(unsigned char* pixels, int w, int h, int stride, const char* text, int x, int y, int fontpixelsize, unsigned int color)
  1112. {
  1113. const unsigned char* pen_color = (const unsigned char*)&color;
  1114. unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
  1115. const int n = strlen(text);
  1116. int cursor_x = x;
  1117. int cursor_y = y;
  1118. for (int i = 0; i < n; i++)
  1119. {
  1120. char ch = text[i];
  1121. if (ch == '\n')
  1122. {
  1123. // newline
  1124. cursor_x = x;
  1125. cursor_y += fontpixelsize * 2;
  1126. }
  1127. if (isprint(ch) != 0)
  1128. {
  1129. const unsigned char* font_bitmap = mono_font_data[ch - ' '];
  1130. // draw resized character
  1131. resize_bilinear_c1(font_bitmap, 20, 40, resized_font_bitmap, fontpixelsize, fontpixelsize * 2);
  1132. for (int j = cursor_y; j < cursor_y + fontpixelsize * 2; j++)
  1133. {
  1134. if (j < 0)
  1135. continue;
  1136. if (j >= h)
  1137. break;
  1138. const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize;
  1139. unsigned char* p = pixels + stride * j;
  1140. for (int k = cursor_x; k < cursor_x + fontpixelsize; k++)
  1141. {
  1142. if (k < 0)
  1143. continue;
  1144. if (k >= w)
  1145. break;
  1146. unsigned char alpha = palpha[k - cursor_x];
  1147. p[k * 4 + 0] = (p[k * 4 + 0] * (255 - alpha) + pen_color[0] * alpha) / 255;
  1148. p[k * 4 + 1] = (p[k * 4 + 1] * (255 - alpha) + pen_color[1] * alpha) / 255;
  1149. p[k * 4 + 2] = (p[k * 4 + 2] * (255 - alpha) + pen_color[2] * alpha) / 255;
  1150. p[k * 4 + 3] = (p[k * 4 + 3] * (255 - alpha) + pen_color[3] * alpha) / 255;
  1151. }
  1152. }
  1153. cursor_x += fontpixelsize;
  1154. }
  1155. }
  1156. delete[] resized_font_bitmap;
  1157. }
  1158. void draw_text_yuv420sp(unsigned char* yuv420sp, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
  1159. {
  1160. // assert w % 2 == 0
  1161. // assert h % 2 == 0
  1162. // assert x % 2 == 0
  1163. // assert y % 2 == 0
  1164. // assert fontpixelsize % 2 == 0
  1165. const unsigned char* pen_color = (const unsigned char*)&color;
  1166. unsigned int v_y;
  1167. unsigned int v_uv;
  1168. unsigned char* pen_color_y = (unsigned char*)&v_y;
  1169. unsigned char* pen_color_uv = (unsigned char*)&v_uv;
  1170. pen_color_y[0] = pen_color[0];
  1171. pen_color_uv[0] = pen_color[1];
  1172. pen_color_uv[1] = pen_color[2];
  1173. unsigned char* Y = yuv420sp;
  1174. draw_text_c1(Y, w, h, text, x, y, fontpixelsize, v_y);
  1175. unsigned char* UV = yuv420sp + w * h;
  1176. draw_text_c2(UV, w / 2, h / 2, text, x / 2, y / 2, std::max(fontpixelsize / 2, 1), v_uv);
  1177. }
  1178. #endif // NCNN_PIXEL_DRAWING
  1179. } // namespace ncnn