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
15 #include "mat.h"
16
17 #include <ctype.h>
18
19 #include "platform.h"
20
21 namespace ncnn {
22
23 #if NCNN_PIXEL_DRAWING
24
25 #include "mat_pixel_drawing_font.h"
26
draw_rectangle_c1(unsigned char * pixels,int w,int h,int rx,int ry,int rw,int rh,unsigned int color,int thickness)27 void draw_rectangle_c1(unsigned char* pixels, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
28 {
29 return draw_rectangle_c1(pixels, w, h, w, rx, ry, rw, rh, color, thickness);
30 }
31
draw_rectangle_c2(unsigned char * pixels,int w,int h,int rx,int ry,int rw,int rh,unsigned int color,int thickness)32 void draw_rectangle_c2(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_c2(pixels, w, h, w * 2, rx, ry, rw, rh, color, thickness);
35 }
36
draw_rectangle_c3(unsigned char * pixels,int w,int h,int rx,int ry,int rw,int rh,unsigned int color,int thickness)37 void draw_rectangle_c3(unsigned char* pixels, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
38 {
39 return draw_rectangle_c3(pixels, w, h, w * 3, rx, ry, rw, rh, color, thickness);
40 }
41
draw_rectangle_c4(unsigned char * pixels,int w,int h,int rx,int ry,int rw,int rh,unsigned int color,int thickness)42 void draw_rectangle_c4(unsigned char* pixels, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
43 {
44 return draw_rectangle_c4(pixels, w, h, w * 4, rx, ry, rw, rh, color, thickness);
45 }
46
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)47 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)
48 {
49 const unsigned char* pen_color = (const unsigned char*)&color;
50
51 if (thickness == -1)
52 {
53 // filled
54 for (int y = ry; y < ry + rh; y++)
55 {
56 if (y < 0)
57 continue;
58
59 if (y >= h)
60 break;
61
62 unsigned char* p = pixels + stride * y;
63
64 for (int x = rx; x < rx + rw; x++)
65 {
66 if (x < 0)
67 continue;
68
69 if (x >= w)
70 break;
71
72 p[x] = pen_color[0];
73 }
74 }
75
76 return;
77 }
78
79 const int t0 = thickness / 2;
80 const int t1 = thickness - t0;
81
82 // draw top
83 {
84 for (int y = ry - t0; y < ry + t1; y++)
85 {
86 if (y < 0)
87 continue;
88
89 if (y >= h)
90 break;
91
92 unsigned char* p = pixels + stride * y;
93
94 for (int x = rx - t0; x < rx + rw + t1; x++)
95 {
96 if (x < 0)
97 continue;
98
99 if (x >= w)
100 break;
101
102 p[x] = pen_color[0];
103 }
104 }
105 }
106
107 // draw bottom
108 {
109 for (int y = ry + rh - t0; y < ry + rh + t1; y++)
110 {
111 if (y < 0)
112 continue;
113
114 if (y >= h)
115 break;
116
117 unsigned char* p = pixels + stride * y;
118
119 for (int x = rx - t0; x < rx + rw + t1; x++)
120 {
121 if (x < 0)
122 continue;
123
124 if (x >= w)
125 break;
126
127 p[x] = pen_color[0];
128 }
129 }
130 }
131
132 // draw left
133 for (int x = rx - t0; x < rx + t1; x++)
134 {
135 if (x < 0)
136 continue;
137
138 if (x >= w)
139 break;
140
141 for (int y = ry + t1; y < ry + rh - t0; y++)
142 {
143 if (y < 0)
144 continue;
145
146 if (y >= h)
147 break;
148
149 unsigned char* p = pixels + stride * y;
150
151 p[x] = pen_color[0];
152 }
153 }
154
155 // draw right
156 for (int x = rx + rw - t0; x < rx + rw + t1; x++)
157 {
158 if (x < 0)
159 continue;
160
161 if (x >= w)
162 break;
163
164 for (int y = ry + t1; y < ry + rh - t0; y++)
165 {
166 if (y < 0)
167 continue;
168
169 if (y >= h)
170 break;
171
172 unsigned char* p = pixels + stride * y;
173
174 p[x] = pen_color[0];
175 }
176 }
177 }
178
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)179 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)
180 {
181 const unsigned char* pen_color = (const unsigned char*)&color;
182
183 if (thickness == -1)
184 {
185 // filled
186 for (int y = ry; y < ry + rh; y++)
187 {
188 if (y < 0)
189 continue;
190
191 if (y >= h)
192 break;
193
194 unsigned char* p = pixels + stride * y;
195
196 for (int x = rx; x < rx + rw; x++)
197 {
198 if (x < 0)
199 continue;
200
201 if (x >= w)
202 break;
203
204 p[x * 2 + 0] = pen_color[0];
205 p[x * 2 + 1] = pen_color[1];
206 }
207 }
208
209 return;
210 }
211
212 const int t0 = thickness / 2;
213 const int t1 = thickness - t0;
214
215 // draw top
216 {
217 for (int y = ry - t0; y < ry + t1; y++)
218 {
219 if (y < 0)
220 continue;
221
222 if (y >= h)
223 break;
224
225 unsigned char* p = pixels + stride * y;
226
227 for (int x = rx - t0; x < rx + rw + t1; x++)
228 {
229 if (x < 0)
230 continue;
231
232 if (x >= w)
233 break;
234
235 p[x * 2 + 0] = pen_color[0];
236 p[x * 2 + 1] = pen_color[1];
237 }
238 }
239 }
240
241 // draw bottom
242 {
243 for (int y = ry + rh - t0; y < ry + rh + t1; y++)
244 {
245 if (y < 0)
246 continue;
247
248 if (y >= h)
249 break;
250
251 unsigned char* p = pixels + stride * y;
252
253 for (int x = rx - t0; x < rx + rw + t1; x++)
254 {
255 if (x < 0)
256 continue;
257
258 if (x >= w)
259 break;
260
261 p[x * 2 + 0] = pen_color[0];
262 p[x * 2 + 1] = pen_color[1];
263 }
264 }
265 }
266
267 // draw left
268 for (int x = rx - t0; x < rx + t1; x++)
269 {
270 if (x < 0)
271 continue;
272
273 if (x >= w)
274 break;
275
276 for (int y = ry + t1; y < ry + rh - t0; y++)
277 {
278 if (y < 0)
279 continue;
280
281 if (y >= h)
282 break;
283
284 unsigned char* p = pixels + stride * y;
285
286 p[x * 2 + 0] = pen_color[0];
287 p[x * 2 + 1] = pen_color[1];
288 }
289 }
290
291 // draw right
292 for (int x = rx + rw - t0; x < rx + rw + t1; x++)
293 {
294 if (x < 0)
295 continue;
296
297 if (x >= w)
298 break;
299
300 for (int y = ry + t1; y < ry + rh - t0; y++)
301 {
302 if (y < 0)
303 continue;
304
305 if (y >= h)
306 break;
307
308 unsigned char* p = pixels + stride * y;
309
310 p[x * 2 + 0] = pen_color[0];
311 p[x * 2 + 1] = pen_color[1];
312 }
313 }
314 }
315
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)316 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)
317 {
318 const unsigned char* pen_color = (const unsigned char*)&color;
319
320 if (thickness == -1)
321 {
322 // filled
323 for (int y = ry; y < ry + rh; y++)
324 {
325 if (y < 0)
326 continue;
327
328 if (y >= h)
329 break;
330
331 unsigned char* p = pixels + stride * y;
332
333 for (int x = rx; x < rx + rw; x++)
334 {
335 if (x < 0)
336 continue;
337
338 if (x >= w)
339 break;
340
341 p[x * 3 + 0] = pen_color[0];
342 p[x * 3 + 1] = pen_color[1];
343 p[x * 3 + 2] = pen_color[2];
344 }
345 }
346
347 return;
348 }
349
350 const int t0 = thickness / 2;
351 const int t1 = thickness - t0;
352
353 // draw top
354 {
355 for (int y = ry - t0; y < ry + t1; y++)
356 {
357 if (y < 0)
358 continue;
359
360 if (y >= h)
361 break;
362
363 unsigned char* p = pixels + stride * y;
364
365 for (int x = rx - t0; x < rx + rw + t1; x++)
366 {
367 if (x < 0)
368 continue;
369
370 if (x >= w)
371 break;
372
373 p[x * 3 + 0] = pen_color[0];
374 p[x * 3 + 1] = pen_color[1];
375 p[x * 3 + 2] = pen_color[2];
376 }
377 }
378 }
379
380 // draw bottom
381 {
382 for (int y = ry + rh - t0; y < ry + rh + t1; y++)
383 {
384 if (y < 0)
385 continue;
386
387 if (y >= h)
388 break;
389
390 unsigned char* p = pixels + stride * y;
391
392 for (int x = rx - t0; x < rx + rw + t1; x++)
393 {
394 if (x < 0)
395 continue;
396
397 if (x >= w)
398 break;
399
400 p[x * 3 + 0] = pen_color[0];
401 p[x * 3 + 1] = pen_color[1];
402 p[x * 3 + 2] = pen_color[2];
403 }
404 }
405 }
406
407 // draw left
408 for (int x = rx - t0; x < rx + t1; x++)
409 {
410 if (x < 0)
411 continue;
412
413 if (x >= w)
414 break;
415
416 for (int y = ry + t1; y < ry + rh - t0; y++)
417 {
418 if (y < 0)
419 continue;
420
421 if (y >= h)
422 break;
423
424 unsigned char* p = pixels + stride * y;
425
426 p[x * 3 + 0] = pen_color[0];
427 p[x * 3 + 1] = pen_color[1];
428 p[x * 3 + 2] = pen_color[2];
429 }
430 }
431
432 // draw right
433 for (int x = rx + rw - t0; x < rx + rw + t1; x++)
434 {
435 if (x < 0)
436 continue;
437
438 if (x >= w)
439 break;
440
441 for (int y = ry + t1; y < ry + rh - t0; y++)
442 {
443 if (y < 0)
444 continue;
445
446 if (y >= h)
447 break;
448
449 unsigned char* p = pixels + stride * y;
450
451 p[x * 3 + 0] = pen_color[0];
452 p[x * 3 + 1] = pen_color[1];
453 p[x * 3 + 2] = pen_color[2];
454 }
455 }
456 }
457
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)458 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)
459 {
460 const unsigned char* pen_color = (const unsigned char*)&color;
461
462 if (thickness == -1)
463 {
464 // filled
465 for (int y = ry; y < ry + rh; y++)
466 {
467 if (y < 0)
468 continue;
469
470 if (y >= h)
471 break;
472
473 unsigned char* p = pixels + stride * y;
474
475 for (int x = rx; x < rx + rw; x++)
476 {
477 if (x < 0)
478 continue;
479
480 if (x >= w)
481 break;
482
483 p[x * 4 + 0] = pen_color[0];
484 p[x * 4 + 1] = pen_color[1];
485 p[x * 4 + 2] = pen_color[2];
486 p[x * 4 + 3] = pen_color[3];
487 }
488 }
489
490 return;
491 }
492
493 const int t0 = thickness / 2;
494 const int t1 = thickness - t0;
495
496 // draw top
497 {
498 for (int y = ry - t0; y < ry + t1; y++)
499 {
500 if (y < 0)
501 continue;
502
503 if (y >= h)
504 break;
505
506 unsigned char* p = pixels + stride * y;
507
508 for (int x = rx - t0; x < rx + rw + t1; x++)
509 {
510 if (x < 0)
511 continue;
512
513 if (x >= w)
514 break;
515
516 p[x * 4 + 0] = pen_color[0];
517 p[x * 4 + 1] = pen_color[1];
518 p[x * 4 + 2] = pen_color[2];
519 p[x * 4 + 3] = pen_color[3];
520 }
521 }
522 }
523
524 // draw bottom
525 {
526 for (int y = ry + rh - t0; y < ry + rh + t1; y++)
527 {
528 if (y < 0)
529 continue;
530
531 if (y >= h)
532 break;
533
534 unsigned char* p = pixels + stride * y;
535
536 for (int x = rx - t0; x < rx + rw + t1; x++)
537 {
538 if (x < 0)
539 continue;
540
541 if (x >= w)
542 break;
543
544 p[x * 4 + 0] = pen_color[0];
545 p[x * 4 + 1] = pen_color[1];
546 p[x * 4 + 2] = pen_color[2];
547 p[x * 4 + 3] = pen_color[3];
548 }
549 }
550 }
551
552 // draw left
553 for (int x = rx - t0; x < rx + t1; x++)
554 {
555 if (x < 0)
556 continue;
557
558 if (x >= w)
559 break;
560
561 for (int y = ry + t1; y < ry + rh - t0; y++)
562 {
563 if (y < 0)
564 continue;
565
566 if (y >= h)
567 break;
568
569 unsigned char* p = pixels + stride * y;
570
571 p[x * 4 + 0] = pen_color[0];
572 p[x * 4 + 1] = pen_color[1];
573 p[x * 4 + 2] = pen_color[2];
574 p[x * 4 + 3] = pen_color[3];
575 }
576 }
577
578 // draw right
579 for (int x = rx + rw - t0; x < rx + rw + t1; x++)
580 {
581 if (x < 0)
582 continue;
583
584 if (x >= w)
585 break;
586
587 for (int y = ry + t1; y < ry + rh - t0; y++)
588 {
589 if (y < 0)
590 continue;
591
592 if (y >= h)
593 break;
594
595 unsigned char* p = pixels + stride * y;
596
597 p[x * 4 + 0] = pen_color[0];
598 p[x * 4 + 1] = pen_color[1];
599 p[x * 4 + 2] = pen_color[2];
600 p[x * 4 + 3] = pen_color[3];
601 }
602 }
603 }
604
draw_rectangle_yuv420sp(unsigned char * yuv420sp,int w,int h,int rx,int ry,int rw,int rh,unsigned int color,int thickness)605 void draw_rectangle_yuv420sp(unsigned char* yuv420sp, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
606 {
607 // assert w % 2 == 0
608 // assert h % 2 == 0
609 // assert rx % 2 == 0
610 // assert ry % 2 == 0
611 // assert rw % 2 == 0
612 // assert rh % 2 == 0
613 // assert thickness % 2 == 0
614
615 const unsigned char* pen_color = (const unsigned char*)&color;
616
617 unsigned int v_y;
618 unsigned int v_uv;
619 unsigned char* pen_color_y = (unsigned char*)&v_y;
620 unsigned char* pen_color_uv = (unsigned char*)&v_uv;
621 pen_color_y[0] = pen_color[0];
622 pen_color_uv[0] = pen_color[1];
623 pen_color_uv[1] = pen_color[2];
624
625 unsigned char* Y = yuv420sp;
626 draw_rectangle_c1(Y, w, h, rx, ry, rw, rh, v_y, thickness);
627
628 unsigned char* UV = yuv420sp + w * h;
629 int thickness_uv = thickness == -1 ? thickness : std::max(thickness / 2, 1);
630 draw_rectangle_c2(UV, w / 2, h / 2, rx / 2, ry / 2, rw / 2, rh / 2, v_uv, thickness_uv);
631 }
632
distance_lessequal(int x0,int y0,int x1,int y1,float r)633 static inline bool distance_lessequal(int x0, int y0, int x1, int y1, float r)
634 {
635 int dx = x0 - x1;
636 int dy = y0 - y1;
637 int q = dx * dx + dy * dy;
638 return q <= r * r;
639 }
640
distance_inrange(int x0,int y0,int x1,int y1,float r0,float r1)641 static inline bool distance_inrange(int x0, int y0, int x1, int y1, float r0, float r1)
642 {
643 int dx = x0 - x1;
644 int dy = y0 - y1;
645 int q = dx * dx + dy * dy;
646 return q >= r0 * r0 && q < r1 * r1;
647 }
648
draw_circle_c1(unsigned char * pixels,int w,int h,int cx,int cy,int radius,unsigned int color,int thickness)649 void draw_circle_c1(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
650 {
651 return draw_circle_c1(pixels, w, h, w, cx, cy, radius, color, thickness);
652 }
653
draw_circle_c2(unsigned char * pixels,int w,int h,int cx,int cy,int radius,unsigned int color,int thickness)654 void draw_circle_c2(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
655 {
656 return draw_circle_c2(pixels, w, h, w * 2, cx, cy, radius, color, thickness);
657 }
658
draw_circle_c3(unsigned char * pixels,int w,int h,int cx,int cy,int radius,unsigned int color,int thickness)659 void draw_circle_c3(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
660 {
661 return draw_circle_c3(pixels, w, h, w * 3, cx, cy, radius, color, thickness);
662 }
663
draw_circle_c4(unsigned char * pixels,int w,int h,int cx,int cy,int radius,unsigned int color,int thickness)664 void draw_circle_c4(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
665 {
666 return draw_circle_c4(pixels, w, h, w * 4, cx, cy, radius, color, thickness);
667 }
668
draw_circle_c1(unsigned char * pixels,int w,int h,int stride,int cx,int cy,int radius,unsigned int color,int thickness)669 void draw_circle_c1(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
670 {
671 const unsigned char* pen_color = (const unsigned char*)&color;
672
673 if (thickness == -1)
674 {
675 // filled
676 for (int y = cy - (radius - 1); y < cy + radius; y++)
677 {
678 if (y < 0)
679 continue;
680
681 if (y >= h)
682 break;
683
684 unsigned char* p = pixels + stride * y;
685
686 for (int x = cx - (radius - 1); x < cx + radius; x++)
687 {
688 if (x < 0)
689 continue;
690
691 if (x >= w)
692 break;
693
694 // distance from cx cy
695 if (distance_lessequal(x, y, cx, cy, radius))
696 {
697 p[x] = pen_color[0];
698 }
699 }
700 }
701
702 return;
703 }
704
705 const float t0 = thickness / 2.f;
706 const float t1 = thickness - t0;
707
708 for (int y = cy - (radius - 1) - t0; y < cy + radius + t1; y++)
709 {
710 if (y < 0)
711 continue;
712
713 if (y >= h)
714 break;
715
716 unsigned char* p = pixels + stride * y;
717
718 for (int x = cx - (radius - 1) - t0; x < cx + radius + t1; x++)
719 {
720 if (x < 0)
721 continue;
722
723 if (x >= w)
724 break;
725
726 // distance from cx cy
727 if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
728 {
729 p[x] = pen_color[0];
730 }
731 }
732 }
733 }
734
draw_circle_c2(unsigned char * pixels,int w,int h,int stride,int cx,int cy,int radius,unsigned int color,int thickness)735 void draw_circle_c2(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
736 {
737 const unsigned char* pen_color = (const unsigned char*)&color;
738
739 if (thickness == -1)
740 {
741 // filled
742 for (int y = cy - (radius - 1); y < cy + radius; y++)
743 {
744 if (y < 0)
745 continue;
746
747 if (y >= h)
748 break;
749
750 unsigned char* p = pixels + stride * y;
751
752 for (int x = cx - (radius - 1); x < cx + radius; x++)
753 {
754 if (x < 0)
755 continue;
756
757 if (x >= w)
758 break;
759
760 // distance from cx cy
761 if (distance_lessequal(x, y, cx, cy, radius))
762 {
763 p[x * 2 + 0] = pen_color[0];
764 p[x * 2 + 1] = pen_color[1];
765 }
766 }
767 }
768
769 return;
770 }
771
772 const float t0 = thickness / 2.f;
773 const float t1 = thickness - t0;
774
775 for (int y = cy - radius - t0; y < cy + radius + t1; y++)
776 {
777 if (y < 0)
778 continue;
779
780 if (y >= h)
781 break;
782
783 unsigned char* p = pixels + stride * y;
784
785 for (int x = cx - radius - t0; x < cx + radius + t1; x++)
786 {
787 if (x < 0)
788 continue;
789
790 if (x >= w)
791 break;
792
793 // distance from cx cy
794 if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
795 {
796 p[x * 2 + 0] = pen_color[0];
797 p[x * 2 + 1] = pen_color[1];
798 }
799 }
800 }
801 }
802
draw_circle_c3(unsigned char * pixels,int w,int h,int stride,int cx,int cy,int radius,unsigned int color,int thickness)803 void draw_circle_c3(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
804 {
805 const unsigned char* pen_color = (const unsigned char*)&color;
806
807 if (thickness == -1)
808 {
809 // filled
810 for (int y = cy - (radius - 1); y < cy + radius; y++)
811 {
812 if (y < 0)
813 continue;
814
815 if (y >= h)
816 break;
817
818 unsigned char* p = pixels + stride * y;
819
820 for (int x = cx - (radius - 1); x < cx + radius; x++)
821 {
822 if (x < 0)
823 continue;
824
825 if (x >= w)
826 break;
827
828 // distance from cx cy
829 if (distance_lessequal(x, y, cx, cy, radius))
830 {
831 p[x * 3 + 0] = pen_color[0];
832 p[x * 3 + 1] = pen_color[1];
833 p[x * 3 + 2] = pen_color[2];
834 }
835 }
836 }
837
838 return;
839 }
840
841 const float t0 = thickness / 2.f;
842 const float t1 = thickness - t0;
843
844 for (int y = cy - radius - t0; y < cy + radius + t1; y++)
845 {
846 if (y < 0)
847 continue;
848
849 if (y >= h)
850 break;
851
852 unsigned char* p = pixels + stride * y;
853
854 for (int x = cx - radius - t0; x < cx + radius + t1; x++)
855 {
856 if (x < 0)
857 continue;
858
859 if (x >= w)
860 break;
861
862 // distance from cx cy
863 if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
864 {
865 p[x * 3 + 0] = pen_color[0];
866 p[x * 3 + 1] = pen_color[1];
867 p[x * 3 + 2] = pen_color[2];
868 }
869 }
870 }
871 }
872
draw_circle_c4(unsigned char * pixels,int w,int h,int stride,int cx,int cy,int radius,unsigned int color,int thickness)873 void draw_circle_c4(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
874 {
875 const unsigned char* pen_color = (const unsigned char*)&color;
876
877 if (thickness == -1)
878 {
879 // filled
880 for (int y = cy - (radius - 1); y < cy + radius; y++)
881 {
882 if (y < 0)
883 continue;
884
885 if (y >= h)
886 break;
887
888 unsigned char* p = pixels + stride * y;
889
890 for (int x = cx - (radius - 1); x < cx + radius; x++)
891 {
892 if (x < 0)
893 continue;
894
895 if (x >= w)
896 break;
897
898 // distance from cx cy
899 if (distance_lessequal(x, y, cx, cy, radius))
900 {
901 p[x * 4 + 0] = pen_color[0];
902 p[x * 4 + 1] = pen_color[1];
903 p[x * 4 + 2] = pen_color[2];
904 p[x * 4 + 3] = pen_color[3];
905 }
906 }
907 }
908
909 return;
910 }
911
912 const float t0 = thickness / 2.f;
913 const float t1 = thickness - t0;
914
915 for (int y = cy - (radius - 1) - t0; y < cy + radius + t1; y++)
916 {
917 if (y < 0)
918 continue;
919
920 if (y >= h)
921 break;
922
923 unsigned char* p = pixels + stride * y;
924
925 for (int x = cx - (radius - 1) - t0; x < cx + radius + t1; x++)
926 {
927 if (x < 0)
928 continue;
929
930 if (x >= w)
931 break;
932
933 // distance from cx cy
934 if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
935 {
936 p[x * 4 + 0] = pen_color[0];
937 p[x * 4 + 1] = pen_color[1];
938 p[x * 4 + 2] = pen_color[2];
939 p[x * 4 + 3] = pen_color[3];
940 }
941 }
942 }
943 }
944
draw_circle_yuv420sp(unsigned char * yuv420sp,int w,int h,int cx,int cy,int radius,unsigned int color,int thickness)945 void draw_circle_yuv420sp(unsigned char* yuv420sp, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
946 {
947 // assert w % 2 == 0
948 // assert h % 2 == 0
949 // assert cx % 2 == 0
950 // assert cy % 2 == 0
951 // assert radius % 2 == 0
952 // assert thickness % 2 == 0
953
954 const unsigned char* pen_color = (const unsigned char*)&color;
955
956 unsigned int v_y;
957 unsigned int v_uv;
958 unsigned char* pen_color_y = (unsigned char*)&v_y;
959 unsigned char* pen_color_uv = (unsigned char*)&v_uv;
960 pen_color_y[0] = pen_color[0];
961 pen_color_uv[0] = pen_color[1];
962 pen_color_uv[1] = pen_color[2];
963
964 unsigned char* Y = yuv420sp;
965 draw_circle_c1(Y, w, h, cx, cy, radius, v_y, thickness);
966
967 unsigned char* UV = yuv420sp + w * h;
968 int thickness_uv = thickness == -1 ? thickness : std::max(thickness / 2, 1);
969 draw_circle_c2(UV, w / 2, h / 2, cx / 2, cy / 2, radius / 2, v_uv, thickness_uv);
970 }
971
distance_lessthan(int x,int y,int x0,int y0,int x1,int y1,float t)972 static inline bool distance_lessthan(int x, int y, int x0, int y0, int x1, int y1, float t)
973 {
974 int dx01 = x1 - x0;
975 int dy01 = y1 - y0;
976 int dx0 = x - x0;
977 int dy0 = y - y0;
978
979 float r = (float)(dx0 * dx01 + dy0 * dy01) / (dx01 * dx01 + dy01 * dy01);
980
981 if (r < 0 || r > 1)
982 return false;
983
984 float px = x0 + dx01 * r;
985 float py = y0 + dy01 * r;
986 float dx = x - px;
987 float dy = y - py;
988 float p = dx * dx + dy * dy;
989 return p < t;
990 }
991
draw_line_c1(unsigned char * pixels,int w,int h,int x0,int y0,int x1,int y1,unsigned int color,int thickness)992 void draw_line_c1(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
993 {
994 draw_line_c1(pixels, w, h, w, x0, y0, x1, y1, color, thickness);
995 }
996
draw_line_c2(unsigned char * pixels,int w,int h,int x0,int y0,int x1,int y1,unsigned int color,int thickness)997 void draw_line_c2(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
998 {
999 draw_line_c2(pixels, w, h, w * 2, x0, y0, x1, y1, color, thickness);
1000 }
1001
draw_line_c3(unsigned char * pixels,int w,int h,int x0,int y0,int x1,int y1,unsigned int color,int thickness)1002 void draw_line_c3(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
1003 {
1004 draw_line_c3(pixels, w, h, w * 3, x0, y0, x1, y1, color, thickness);
1005 }
1006
draw_line_c4(unsigned char * pixels,int w,int h,int x0,int y0,int x1,int y1,unsigned int color,int thickness)1007 void draw_line_c4(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
1008 {
1009 draw_line_c4(pixels, w, h, w * 4, x0, y0, x1, y1, color, thickness);
1010 }
1011
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)1012 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)
1013 {
1014 const unsigned char* pen_color = (const unsigned char*)&color;
1015
1016 const float t0 = thickness / 2.f;
1017 const float t1 = thickness - t0;
1018
1019 int x_min = std::min(x0, x1);
1020 int x_max = std::max(x0, x1);
1021 int y_min = std::min(y0, y1);
1022 int y_max = std::max(y0, y1);
1023
1024 for (int y = y_min - t0; y < y_max + t1; y++)
1025 {
1026 if (y < 0)
1027 continue;
1028
1029 if (y >= h)
1030 break;
1031
1032 unsigned char* p = pixels + stride * y;
1033
1034 for (int x = x_min - t0; x < x_max + t1; x++)
1035 {
1036 if (x < 0)
1037 continue;
1038
1039 if (x >= w)
1040 break;
1041
1042 // distance from line
1043 if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
1044 {
1045 p[x] = pen_color[0];
1046 }
1047 }
1048 }
1049 }
1050
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)1051 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)
1052 {
1053 const unsigned char* pen_color = (const unsigned char*)&color;
1054
1055 const float t0 = thickness / 2.f;
1056 const float t1 = thickness - t0;
1057
1058 int x_min = std::min(x0, x1);
1059 int x_max = std::max(x0, x1);
1060 int y_min = std::min(y0, y1);
1061 int y_max = std::max(y0, y1);
1062
1063 for (int y = y_min - t0; y < y_max + t1; y++)
1064 {
1065 if (y < 0)
1066 continue;
1067
1068 if (y >= h)
1069 break;
1070
1071 unsigned char* p = pixels + stride * y;
1072
1073 for (int x = x_min - t0; x < x_max + t1; x++)
1074 {
1075 if (x < 0)
1076 continue;
1077
1078 if (x >= w)
1079 break;
1080
1081 // distance from line
1082 if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
1083 {
1084 p[x * 2 + 0] = pen_color[0];
1085 p[x * 2 + 1] = pen_color[1];
1086 }
1087 }
1088 }
1089 }
1090
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)1091 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)
1092 {
1093 const unsigned char* pen_color = (const unsigned char*)&color;
1094
1095 const float t0 = thickness / 2.f;
1096 const float t1 = thickness - t0;
1097
1098 int x_min = std::min(x0, x1);
1099 int x_max = std::max(x0, x1);
1100 int y_min = std::min(y0, y1);
1101 int y_max = std::max(y0, y1);
1102
1103 for (int y = y_min - t0; y < y_max + t1; y++)
1104 {
1105 if (y < 0)
1106 continue;
1107
1108 if (y >= h)
1109 break;
1110
1111 unsigned char* p = pixels + stride * y;
1112
1113 for (int x = x_min - t0; x < x_max + t1; x++)
1114 {
1115 if (x < 0)
1116 continue;
1117
1118 if (x >= w)
1119 break;
1120
1121 // distance from line
1122 if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
1123 {
1124 p[x * 3 + 0] = pen_color[0];
1125 p[x * 3 + 1] = pen_color[1];
1126 p[x * 3 + 2] = pen_color[2];
1127 }
1128 }
1129 }
1130 }
1131
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)1132 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)
1133 {
1134 const unsigned char* pen_color = (const unsigned char*)&color;
1135
1136 const float t0 = thickness / 2.f;
1137 const float t1 = thickness - t0;
1138
1139 int x_min = std::min(x0, x1);
1140 int x_max = std::max(x0, x1);
1141 int y_min = std::min(y0, y1);
1142 int y_max = std::max(y0, y1);
1143
1144 for (int y = y_min - t0; y < y_max + t1; y++)
1145 {
1146 if (y < 0)
1147 continue;
1148
1149 if (y >= h)
1150 break;
1151
1152 unsigned char* p = pixels + stride * y;
1153
1154 for (int x = x_min - t0; x < x_max + t1; x++)
1155 {
1156 if (x < 0)
1157 continue;
1158
1159 if (x >= w)
1160 break;
1161
1162 // distance from line
1163 if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
1164 {
1165 p[x * 4 + 0] = pen_color[0];
1166 p[x * 4 + 1] = pen_color[1];
1167 p[x * 4 + 2] = pen_color[2];
1168 p[x * 4 + 3] = pen_color[3];
1169 }
1170 }
1171 }
1172 }
1173
draw_line_yuv420sp(unsigned char * yuv420sp,int w,int h,int x0,int y0,int x1,int y1,unsigned int color,int thickness)1174 void draw_line_yuv420sp(unsigned char* yuv420sp, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
1175 {
1176 // assert w % 2 == 0
1177 // assert h % 2 == 0
1178 // assert x0 % 2 == 0
1179 // assert y0 % 2 == 0
1180 // assert x1 % 2 == 0
1181 // assert y1 % 2 == 0
1182 // assert thickness % 2 == 0
1183
1184 const unsigned char* pen_color = (const unsigned char*)&color;
1185
1186 unsigned int v_y;
1187 unsigned int v_uv;
1188 unsigned char* pen_color_y = (unsigned char*)&v_y;
1189 unsigned char* pen_color_uv = (unsigned char*)&v_uv;
1190 pen_color_y[0] = pen_color[0];
1191 pen_color_uv[0] = pen_color[1];
1192 pen_color_uv[1] = pen_color[2];
1193
1194 unsigned char* Y = yuv420sp;
1195 draw_line_c1(Y, w, h, x0, y0, x1, y1, v_y, thickness);
1196
1197 unsigned char* UV = yuv420sp + w * h;
1198 int thickness_uv = thickness == -1 ? thickness : std::max(thickness / 2, 1);
1199 draw_line_c2(UV, w / 2, h / 2, x0 / 2, y0 / 2, x1 / 2, y1 / 2, v_uv, thickness_uv);
1200 }
1201
get_text_drawing_size(const char * text,int fontpixelsize,int * w,int * h)1202 void get_text_drawing_size(const char* text, int fontpixelsize, int* w, int* h)
1203 {
1204 *w = 0;
1205 *h = 0;
1206
1207 const int n = strlen(text);
1208
1209 int line_w = 0;
1210 for (int i = 0; i < n; i++)
1211 {
1212 char ch = text[i];
1213
1214 if (ch == '\n')
1215 {
1216 // newline
1217 *w = std::max(*w, line_w);
1218 *h += fontpixelsize * 2;
1219 line_w = 0;
1220 }
1221
1222 if (isprint(ch) != 0)
1223 {
1224 line_w += fontpixelsize;
1225 }
1226 }
1227
1228 *w = std::max(*w, line_w);
1229 *h += fontpixelsize * 2;
1230 }
1231
draw_text_c1(unsigned char * pixels,int w,int h,const char * text,int x,int y,int fontpixelsize,unsigned int color)1232 void draw_text_c1(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
1233 {
1234 return draw_text_c1(pixels, w, h, w, text, x, y, fontpixelsize, color);
1235 }
1236
draw_text_c2(unsigned char * pixels,int w,int h,const char * text,int x,int y,int fontpixelsize,unsigned int color)1237 void draw_text_c2(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
1238 {
1239 return draw_text_c2(pixels, w, h, w * 2, text, x, y, fontpixelsize, color);
1240 }
1241
draw_text_c3(unsigned char * pixels,int w,int h,const char * text,int x,int y,int fontpixelsize,unsigned int color)1242 void draw_text_c3(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
1243 {
1244 return draw_text_c3(pixels, w, h, w * 3, text, x, y, fontpixelsize, color);
1245 }
1246
draw_text_c4(unsigned char * pixels,int w,int h,const char * text,int x,int y,int fontpixelsize,unsigned int color)1247 void draw_text_c4(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
1248 {
1249 return draw_text_c4(pixels, w, h, w * 4, text, x, y, fontpixelsize, color);
1250 }
1251
draw_text_c1(unsigned char * pixels,int w,int h,int stride,const char * text,int x,int y,int fontpixelsize,unsigned int color)1252 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)
1253 {
1254 const unsigned char* pen_color = (const unsigned char*)&color;
1255
1256 unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
1257
1258 const int n = strlen(text);
1259
1260 int cursor_x = x;
1261 int cursor_y = y;
1262 for (int i = 0; i < n; i++)
1263 {
1264 char ch = text[i];
1265
1266 if (ch == '\n')
1267 {
1268 // newline
1269 cursor_x = x;
1270 cursor_y += fontpixelsize * 2;
1271 }
1272
1273 if (isprint(ch) != 0)
1274 {
1275 const unsigned char* font_bitmap = mono_font_data[ch - ' '];
1276
1277 // draw resized character
1278 resize_bilinear_c1(font_bitmap, 20, 40, resized_font_bitmap, fontpixelsize, fontpixelsize * 2);
1279
1280 for (int j = cursor_y; j < cursor_y + fontpixelsize * 2; j++)
1281 {
1282 if (j < 0)
1283 continue;
1284
1285 if (j >= h)
1286 break;
1287
1288 const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize;
1289 unsigned char* p = pixels + stride * j;
1290
1291 for (int k = cursor_x; k < cursor_x + fontpixelsize; k++)
1292 {
1293 if (k < 0)
1294 continue;
1295
1296 if (k >= w)
1297 break;
1298
1299 unsigned char alpha = palpha[k - cursor_x];
1300
1301 p[k] = (p[k] * (255 - alpha) + pen_color[0] * alpha) / 255;
1302 }
1303 }
1304
1305 cursor_x += fontpixelsize;
1306 }
1307 }
1308
1309 delete[] resized_font_bitmap;
1310 }
1311
draw_text_c2(unsigned char * pixels,int w,int h,int stride,const char * text,int x,int y,int fontpixelsize,unsigned int color)1312 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)
1313 {
1314 const unsigned char* pen_color = (const unsigned char*)&color;
1315
1316 unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
1317
1318 const int n = strlen(text);
1319
1320 int cursor_x = x;
1321 int cursor_y = y;
1322 for (int i = 0; i < n; i++)
1323 {
1324 char ch = text[i];
1325
1326 if (ch == '\n')
1327 {
1328 // newline
1329 cursor_x = x;
1330 cursor_y += fontpixelsize * 2;
1331 }
1332
1333 if (isprint(ch) != 0)
1334 {
1335 int font_bitmap_index = ch - ' ';
1336 const unsigned char* font_bitmap = mono_font_data[font_bitmap_index];
1337
1338 // draw resized character
1339 resize_bilinear_c1(font_bitmap, 20, 40, resized_font_bitmap, fontpixelsize, fontpixelsize * 2);
1340
1341 for (int j = cursor_y; j < cursor_y + fontpixelsize * 2; j++)
1342 {
1343 if (j < 0)
1344 continue;
1345
1346 if (j >= h)
1347 break;
1348
1349 const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize;
1350 unsigned char* p = pixels + stride * j;
1351
1352 for (int k = cursor_x; k < cursor_x + fontpixelsize; k++)
1353 {
1354 if (k < 0)
1355 continue;
1356
1357 if (k >= w)
1358 break;
1359
1360 unsigned char alpha = palpha[k - cursor_x];
1361
1362 p[k * 2 + 0] = (p[k * 2 + 0] * (255 - alpha) + pen_color[0] * alpha) / 255;
1363 p[k * 2 + 1] = (p[k * 2 + 1] * (255 - alpha) + pen_color[1] * alpha) / 255;
1364 }
1365 }
1366
1367 cursor_x += fontpixelsize;
1368 }
1369 }
1370
1371 delete[] resized_font_bitmap;
1372 }
1373
draw_text_c3(unsigned char * pixels,int w,int h,int stride,const char * text,int x,int y,int fontpixelsize,unsigned int color)1374 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)
1375 {
1376 const unsigned char* pen_color = (const unsigned char*)&color;
1377
1378 unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
1379
1380 const int n = strlen(text);
1381
1382 int cursor_x = x;
1383 int cursor_y = y;
1384 for (int i = 0; i < n; i++)
1385 {
1386 char ch = text[i];
1387
1388 if (ch == '\n')
1389 {
1390 // newline
1391 cursor_x = x;
1392 cursor_y += fontpixelsize * 2;
1393 }
1394
1395 if (isprint(ch) != 0)
1396 {
1397 int font_bitmap_index = ch - ' ';
1398 const unsigned char* font_bitmap = mono_font_data[font_bitmap_index];
1399
1400 // draw resized character
1401 resize_bilinear_c1(font_bitmap, 20, 40, resized_font_bitmap, fontpixelsize, fontpixelsize * 2);
1402
1403 for (int j = cursor_y; j < cursor_y + fontpixelsize * 2; j++)
1404 {
1405 if (j < 0)
1406 continue;
1407
1408 if (j >= h)
1409 break;
1410
1411 const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize;
1412 unsigned char* p = pixels + stride * j;
1413
1414 for (int k = cursor_x; k < cursor_x + fontpixelsize; k++)
1415 {
1416 if (k < 0)
1417 continue;
1418
1419 if (k >= w)
1420 break;
1421
1422 unsigned char alpha = palpha[k - cursor_x];
1423
1424 p[k * 3 + 0] = (p[k * 3 + 0] * (255 - alpha) + pen_color[0] * alpha) / 255;
1425 p[k * 3 + 1] = (p[k * 3 + 1] * (255 - alpha) + pen_color[1] * alpha) / 255;
1426 p[k * 3 + 2] = (p[k * 3 + 2] * (255 - alpha) + pen_color[2] * alpha) / 255;
1427 }
1428 }
1429
1430 cursor_x += fontpixelsize;
1431 }
1432 }
1433
1434 delete[] resized_font_bitmap;
1435 }
1436
draw_text_c4(unsigned char * pixels,int w,int h,int stride,const char * text,int x,int y,int fontpixelsize,unsigned int color)1437 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)
1438 {
1439 const unsigned char* pen_color = (const unsigned char*)&color;
1440
1441 unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
1442
1443 const int n = strlen(text);
1444
1445 int cursor_x = x;
1446 int cursor_y = y;
1447 for (int i = 0; i < n; i++)
1448 {
1449 char ch = text[i];
1450
1451 if (ch == '\n')
1452 {
1453 // newline
1454 cursor_x = x;
1455 cursor_y += fontpixelsize * 2;
1456 }
1457
1458 if (isprint(ch) != 0)
1459 {
1460 const unsigned char* font_bitmap = mono_font_data[ch - ' '];
1461
1462 // draw resized character
1463 resize_bilinear_c1(font_bitmap, 20, 40, resized_font_bitmap, fontpixelsize, fontpixelsize * 2);
1464
1465 for (int j = cursor_y; j < cursor_y + fontpixelsize * 2; j++)
1466 {
1467 if (j < 0)
1468 continue;
1469
1470 if (j >= h)
1471 break;
1472
1473 const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize;
1474 unsigned char* p = pixels + stride * j;
1475
1476 for (int k = cursor_x; k < cursor_x + fontpixelsize; k++)
1477 {
1478 if (k < 0)
1479 continue;
1480
1481 if (k >= w)
1482 break;
1483
1484 unsigned char alpha = palpha[k - cursor_x];
1485
1486 p[k * 4 + 0] = (p[k * 4 + 0] * (255 - alpha) + pen_color[0] * alpha) / 255;
1487 p[k * 4 + 1] = (p[k * 4 + 1] * (255 - alpha) + pen_color[1] * alpha) / 255;
1488 p[k * 4 + 2] = (p[k * 4 + 2] * (255 - alpha) + pen_color[2] * alpha) / 255;
1489 p[k * 4 + 3] = (p[k * 4 + 3] * (255 - alpha) + pen_color[3] * alpha) / 255;
1490 }
1491 }
1492
1493 cursor_x += fontpixelsize;
1494 }
1495 }
1496
1497 delete[] resized_font_bitmap;
1498 }
1499
draw_text_yuv420sp(unsigned char * yuv420sp,int w,int h,const char * text,int x,int y,int fontpixelsize,unsigned int color)1500 void draw_text_yuv420sp(unsigned char* yuv420sp, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
1501 {
1502 // assert w % 2 == 0
1503 // assert h % 2 == 0
1504 // assert x % 2 == 0
1505 // assert y % 2 == 0
1506 // assert fontpixelsize % 2 == 0
1507
1508 const unsigned char* pen_color = (const unsigned char*)&color;
1509
1510 unsigned int v_y;
1511 unsigned int v_uv;
1512 unsigned char* pen_color_y = (unsigned char*)&v_y;
1513 unsigned char* pen_color_uv = (unsigned char*)&v_uv;
1514 pen_color_y[0] = pen_color[0];
1515 pen_color_uv[0] = pen_color[1];
1516 pen_color_uv[1] = pen_color[2];
1517
1518 unsigned char* Y = yuv420sp;
1519 draw_text_c1(Y, w, h, text, x, y, fontpixelsize, v_y);
1520
1521 unsigned char* UV = yuv420sp + w * h;
1522 draw_text_c2(UV, w / 2, h / 2, text, x / 2, y / 2, std::max(fontpixelsize / 2, 1), v_uv);
1523 }
1524
1525 #endif // NCNN_PIXEL_DRAWING
1526
1527 } // namespace ncnn
1528