ncnn

Форк
0
/
mat_pixel_drawing.cpp 
1960 строк · 54.2 Кб
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
#include <limits.h>
19

20
#if __ARM_NEON
21
#include <arm_neon.h>
22
#endif // __ARM_NEON
23

24
#if __SSE2__
25
#include <emmintrin.h>
26
#endif
27

28
#include "platform.h"
29

30
namespace ncnn {
31

32
#if NCNN_PIXEL_DRAWING
33

34
#include "mat_pixel_drawing_font.h"
35

36
void draw_rectangle_c1(unsigned char* pixels, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
37
{
38
    return draw_rectangle_c1(pixels, w, h, w, rx, ry, rw, rh, color, thickness);
39
}
40

41
void draw_rectangle_c2(unsigned char* pixels, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
42
{
43
    return draw_rectangle_c2(pixels, w, h, w * 2, rx, ry, rw, rh, color, thickness);
44
}
45

46
void draw_rectangle_c3(unsigned char* pixels, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
47
{
48
    return draw_rectangle_c3(pixels, w, h, w * 3, rx, ry, rw, rh, color, thickness);
49
}
50

51
void draw_rectangle_c4(unsigned char* pixels, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
52
{
53
    return draw_rectangle_c4(pixels, w, h, w * 4, rx, ry, rw, rh, color, thickness);
54
}
55

56
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)
57
{
58
    const unsigned char* pen_color = (const unsigned char*)&color;
59

60
    if (thickness == -1)
61
    {
62
        // filled
63
        for (int y = ry; y < ry + rh; y++)
64
        {
65
            if (y < 0)
66
                continue;
67

68
            if (y >= h)
69
                break;
70

71
            unsigned char* p = pixels + stride * y;
72

73
            for (int x = rx; x < rx + rw; x++)
74
            {
75
                if (x < 0)
76
                    continue;
77

78
                if (x >= w)
79
                    break;
80

81
                p[x] = pen_color[0];
82
            }
83
        }
84

85
        return;
86
    }
87

88
    const int t0 = thickness / 2;
89
    const int t1 = thickness - t0;
90

91
    // draw top
92
    {
93
        for (int y = ry - t0; y < ry + t1; y++)
94
        {
95
            if (y < 0)
96
                continue;
97

98
            if (y >= h)
99
                break;
100

101
            unsigned char* p = pixels + stride * y;
102

103
            for (int x = rx - t0; x < rx + rw + t1; x++)
104
            {
105
                if (x < 0)
106
                    continue;
107

108
                if (x >= w)
109
                    break;
110

111
                p[x] = pen_color[0];
112
            }
113
        }
114
    }
115

116
    // draw bottom
117
    {
118
        for (int y = ry + rh - t0; y < ry + rh + t1; y++)
119
        {
120
            if (y < 0)
121
                continue;
122

123
            if (y >= h)
124
                break;
125

126
            unsigned char* p = pixels + stride * y;
127

128
            for (int x = rx - t0; x < rx + rw + t1; x++)
129
            {
130
                if (x < 0)
131
                    continue;
132

133
                if (x >= w)
134
                    break;
135

136
                p[x] = pen_color[0];
137
            }
138
        }
139
    }
140

141
    // draw left
142
    for (int x = rx - t0; x < rx + t1; x++)
143
    {
144
        if (x < 0)
145
            continue;
146

147
        if (x >= w)
148
            break;
149

150
        for (int y = ry + t1; y < ry + rh - t0; y++)
151
        {
152
            if (y < 0)
153
                continue;
154

155
            if (y >= h)
156
                break;
157

158
            unsigned char* p = pixels + stride * y;
159

160
            p[x] = pen_color[0];
161
        }
162
    }
163

164
    // draw right
165
    for (int x = rx + rw - t0; x < rx + rw + t1; x++)
166
    {
167
        if (x < 0)
168
            continue;
169

170
        if (x >= w)
171
            break;
172

173
        for (int y = ry + t1; y < ry + rh - t0; y++)
174
        {
175
            if (y < 0)
176
                continue;
177

178
            if (y >= h)
179
                break;
180

181
            unsigned char* p = pixels + stride * y;
182

183
            p[x] = pen_color[0];
184
        }
185
    }
186
}
187

188
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)
189
{
190
    const unsigned char* pen_color = (const unsigned char*)&color;
191

192
    if (thickness == -1)
193
    {
194
        // filled
195
        for (int y = ry; y < ry + rh; y++)
196
        {
197
            if (y < 0)
198
                continue;
199

200
            if (y >= h)
201
                break;
202

203
            unsigned char* p = pixels + stride * y;
204

205
            for (int x = rx; x < rx + rw; x++)
206
            {
207
                if (x < 0)
208
                    continue;
209

210
                if (x >= w)
211
                    break;
212

213
                p[x * 2 + 0] = pen_color[0];
214
                p[x * 2 + 1] = pen_color[1];
215
            }
216
        }
217

218
        return;
219
    }
220

221
    const int t0 = thickness / 2;
222
    const int t1 = thickness - t0;
223

224
    // draw top
225
    {
226
        for (int y = ry - t0; y < ry + t1; y++)
227
        {
228
            if (y < 0)
229
                continue;
230

231
            if (y >= h)
232
                break;
233

234
            unsigned char* p = pixels + stride * y;
235

236
            for (int x = rx - t0; x < rx + rw + t1; x++)
237
            {
238
                if (x < 0)
239
                    continue;
240

241
                if (x >= w)
242
                    break;
243

244
                p[x * 2 + 0] = pen_color[0];
245
                p[x * 2 + 1] = pen_color[1];
246
            }
247
        }
248
    }
249

250
    // draw bottom
251
    {
252
        for (int y = ry + rh - t0; y < ry + rh + t1; y++)
253
        {
254
            if (y < 0)
255
                continue;
256

257
            if (y >= h)
258
                break;
259

260
            unsigned char* p = pixels + stride * y;
261

262
            for (int x = rx - t0; x < rx + rw + t1; x++)
263
            {
264
                if (x < 0)
265
                    continue;
266

267
                if (x >= w)
268
                    break;
269

270
                p[x * 2 + 0] = pen_color[0];
271
                p[x * 2 + 1] = pen_color[1];
272
            }
273
        }
274
    }
275

276
    // draw left
277
    for (int x = rx - t0; x < rx + t1; x++)
278
    {
279
        if (x < 0)
280
            continue;
281

282
        if (x >= w)
283
            break;
284

285
        for (int y = ry + t1; y < ry + rh - t0; y++)
286
        {
287
            if (y < 0)
288
                continue;
289

290
            if (y >= h)
291
                break;
292

293
            unsigned char* p = pixels + stride * y;
294

295
            p[x * 2 + 0] = pen_color[0];
296
            p[x * 2 + 1] = pen_color[1];
297
        }
298
    }
299

300
    // draw right
301
    for (int x = rx + rw - t0; x < rx + rw + t1; x++)
302
    {
303
        if (x < 0)
304
            continue;
305

306
        if (x >= w)
307
            break;
308

309
        for (int y = ry + t1; y < ry + rh - t0; y++)
310
        {
311
            if (y < 0)
312
                continue;
313

314
            if (y >= h)
315
                break;
316

317
            unsigned char* p = pixels + stride * y;
318

319
            p[x * 2 + 0] = pen_color[0];
320
            p[x * 2 + 1] = pen_color[1];
321
        }
322
    }
323
}
324

325
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)
326
{
327
    const unsigned char* pen_color = (const unsigned char*)&color;
328

329
    if (thickness == -1)
330
    {
331
        // filled
332
        for (int y = ry; y < ry + rh; y++)
333
        {
334
            if (y < 0)
335
                continue;
336

337
            if (y >= h)
338
                break;
339

340
            unsigned char* p = pixels + stride * y;
341

342
            for (int x = rx; x < rx + rw; x++)
343
            {
344
                if (x < 0)
345
                    continue;
346

347
                if (x >= w)
348
                    break;
349

350
                p[x * 3 + 0] = pen_color[0];
351
                p[x * 3 + 1] = pen_color[1];
352
                p[x * 3 + 2] = pen_color[2];
353
            }
354
        }
355

356
        return;
357
    }
358

359
    const int t0 = thickness / 2;
360
    const int t1 = thickness - t0;
361

362
    // draw top
363
    {
364
        for (int y = ry - t0; y < ry + t1; y++)
365
        {
366
            if (y < 0)
367
                continue;
368

369
            if (y >= h)
370
                break;
371

372
            unsigned char* p = pixels + stride * y;
373

374
            for (int x = rx - t0; x < rx + rw + t1; x++)
375
            {
376
                if (x < 0)
377
                    continue;
378

379
                if (x >= w)
380
                    break;
381

382
                p[x * 3 + 0] = pen_color[0];
383
                p[x * 3 + 1] = pen_color[1];
384
                p[x * 3 + 2] = pen_color[2];
385
            }
386
        }
387
    }
388

389
    // draw bottom
390
    {
391
        for (int y = ry + rh - t0; y < ry + rh + t1; y++)
392
        {
393
            if (y < 0)
394
                continue;
395

396
            if (y >= h)
397
                break;
398

399
            unsigned char* p = pixels + stride * y;
400

401
            for (int x = rx - t0; x < rx + rw + t1; x++)
402
            {
403
                if (x < 0)
404
                    continue;
405

406
                if (x >= w)
407
                    break;
408

409
                p[x * 3 + 0] = pen_color[0];
410
                p[x * 3 + 1] = pen_color[1];
411
                p[x * 3 + 2] = pen_color[2];
412
            }
413
        }
414
    }
415

416
    // draw left
417
    for (int x = rx - t0; x < rx + t1; x++)
418
    {
419
        if (x < 0)
420
            continue;
421

422
        if (x >= w)
423
            break;
424

425
        for (int y = ry + t1; y < ry + rh - t0; y++)
426
        {
427
            if (y < 0)
428
                continue;
429

430
            if (y >= h)
431
                break;
432

433
            unsigned char* p = pixels + stride * y;
434

435
            p[x * 3 + 0] = pen_color[0];
436
            p[x * 3 + 1] = pen_color[1];
437
            p[x * 3 + 2] = pen_color[2];
438
        }
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

447
        if (x >= w)
448
            break;
449

450
        for (int y = ry + t1; y < ry + rh - t0; y++)
451
        {
452
            if (y < 0)
453
                continue;
454

455
            if (y >= h)
456
                break;
457

458
            unsigned char* p = pixels + stride * y;
459

460
            p[x * 3 + 0] = pen_color[0];
461
            p[x * 3 + 1] = pen_color[1];
462
            p[x * 3 + 2] = pen_color[2];
463
        }
464
    }
465
}
466

467
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)
468
{
469
    const unsigned char* pen_color = (const unsigned char*)&color;
470

471
    if (thickness == -1)
472
    {
473
        // filled
474
        for (int y = ry; y < ry + rh; y++)
475
        {
476
            if (y < 0)
477
                continue;
478

479
            if (y >= h)
480
                break;
481

482
            unsigned char* p = pixels + stride * y;
483

484
            for (int x = rx; x < rx + rw; x++)
485
            {
486
                if (x < 0)
487
                    continue;
488

489
                if (x >= w)
490
                    break;
491

492
                p[x * 4 + 0] = pen_color[0];
493
                p[x * 4 + 1] = pen_color[1];
494
                p[x * 4 + 2] = pen_color[2];
495
                p[x * 4 + 3] = pen_color[3];
496
            }
497
        }
498

499
        return;
500
    }
501

502
    const int t0 = thickness / 2;
503
    const int t1 = thickness - t0;
504

505
    // draw top
506
    {
507
        for (int y = ry - t0; y < ry + t1; y++)
508
        {
509
            if (y < 0)
510
                continue;
511

512
            if (y >= h)
513
                break;
514

515
            unsigned char* p = pixels + stride * y;
516

517
            for (int x = rx - t0; x < rx + rw + t1; x++)
518
            {
519
                if (x < 0)
520
                    continue;
521

522
                if (x >= w)
523
                    break;
524

525
                p[x * 4 + 0] = pen_color[0];
526
                p[x * 4 + 1] = pen_color[1];
527
                p[x * 4 + 2] = pen_color[2];
528
                p[x * 4 + 3] = pen_color[3];
529
            }
530
        }
531
    }
532

533
    // draw bottom
534
    {
535
        for (int y = ry + rh - t0; y < ry + rh + t1; y++)
536
        {
537
            if (y < 0)
538
                continue;
539

540
            if (y >= h)
541
                break;
542

543
            unsigned char* p = pixels + stride * y;
544

545
            for (int x = rx - t0; x < rx + rw + t1; x++)
546
            {
547
                if (x < 0)
548
                    continue;
549

550
                if (x >= w)
551
                    break;
552

553
                p[x * 4 + 0] = pen_color[0];
554
                p[x * 4 + 1] = pen_color[1];
555
                p[x * 4 + 2] = pen_color[2];
556
                p[x * 4 + 3] = pen_color[3];
557
            }
558
        }
559
    }
560

561
    // draw left
562
    for (int x = rx - t0; x < rx + t1; x++)
563
    {
564
        if (x < 0)
565
            continue;
566

567
        if (x >= w)
568
            break;
569

570
        for (int y = ry + t1; y < ry + rh - t0; y++)
571
        {
572
            if (y < 0)
573
                continue;
574

575
            if (y >= h)
576
                break;
577

578
            unsigned char* p = pixels + stride * y;
579

580
            p[x * 4 + 0] = pen_color[0];
581
            p[x * 4 + 1] = pen_color[1];
582
            p[x * 4 + 2] = pen_color[2];
583
            p[x * 4 + 3] = pen_color[3];
584
        }
585
    }
586

587
    // draw right
588
    for (int x = rx + rw - t0; x < rx + rw + t1; x++)
589
    {
590
        if (x < 0)
591
            continue;
592

593
        if (x >= w)
594
            break;
595

596
        for (int y = ry + t1; y < ry + rh - t0; y++)
597
        {
598
            if (y < 0)
599
                continue;
600

601
            if (y >= h)
602
                break;
603

604
            unsigned char* p = pixels + stride * y;
605

606
            p[x * 4 + 0] = pen_color[0];
607
            p[x * 4 + 1] = pen_color[1];
608
            p[x * 4 + 2] = pen_color[2];
609
            p[x * 4 + 3] = pen_color[3];
610
        }
611
    }
612
}
613

614
void draw_rectangle_yuv420sp(unsigned char* yuv420sp, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
615
{
616
    // assert w % 2 == 0
617
    // assert h % 2 == 0
618
    // assert rx % 2 == 0
619
    // assert ry % 2 == 0
620
    // assert rw % 2 == 0
621
    // assert rh % 2 == 0
622
    // assert thickness % 2 == 0
623

624
    const unsigned char* pen_color = (const unsigned char*)&color;
625

626
    unsigned int v_y;
627
    unsigned int v_uv;
628
    unsigned char* pen_color_y = (unsigned char*)&v_y;
629
    unsigned char* pen_color_uv = (unsigned char*)&v_uv;
630
    pen_color_y[0] = pen_color[0];
631
    pen_color_uv[0] = pen_color[1];
632
    pen_color_uv[1] = pen_color[2];
633

634
    unsigned char* Y = yuv420sp;
635
    draw_rectangle_c1(Y, w, h, rx, ry, rw, rh, v_y, thickness);
636

637
    unsigned char* UV = yuv420sp + w * h;
638
    int thickness_uv = thickness == -1 ? thickness : std::max(thickness / 2, 1);
639
    draw_rectangle_c2(UV, w / 2, h / 2, rx / 2, ry / 2, rw / 2, rh / 2, v_uv, thickness_uv);
640
}
641

642
static inline bool distance_lessequal(int x0, int y0, int x1, int y1, float r)
643
{
644
    int dx = x0 - x1;
645
    int dy = y0 - y1;
646
    int q = dx * dx + dy * dy;
647
    return q <= r * r;
648
}
649

650
static inline bool distance_inrange(int x0, int y0, int x1, int y1, float r0, float r1)
651
{
652
    int dx = x0 - x1;
653
    int dy = y0 - y1;
654
    int q = dx * dx + dy * dy;
655
    return q >= r0 * r0 && q < r1 * r1;
656
}
657

658
void draw_circle_c1(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
659
{
660
    return draw_circle_c1(pixels, w, h, w, cx, cy, radius, color, thickness);
661
}
662

663
void draw_circle_c2(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
664
{
665
    return draw_circle_c2(pixels, w, h, w * 2, cx, cy, radius, color, thickness);
666
}
667

668
void draw_circle_c3(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
669
{
670
    return draw_circle_c3(pixels, w, h, w * 3, cx, cy, radius, color, thickness);
671
}
672

673
void draw_circle_c4(unsigned char* pixels, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
674
{
675
    return draw_circle_c4(pixels, w, h, w * 4, cx, cy, radius, color, thickness);
676
}
677

678
void draw_circle_c1(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
679
{
680
    const unsigned char* pen_color = (const unsigned char*)&color;
681

682
    if (thickness == -1)
683
    {
684
        // filled
685
        for (int y = cy - (radius - 1); y < cy + radius; y++)
686
        {
687
            if (y < 0)
688
                continue;
689

690
            if (y >= h)
691
                break;
692

693
            unsigned char* p = pixels + stride * y;
694

695
            for (int x = cx - (radius - 1); x < cx + radius; x++)
696
            {
697
                if (x < 0)
698
                    continue;
699

700
                if (x >= w)
701
                    break;
702

703
                // distance from cx cy
704
                if (distance_lessequal(x, y, cx, cy, radius))
705
                {
706
                    p[x] = pen_color[0];
707
                }
708
            }
709
        }
710

711
        return;
712
    }
713

714
    const float t0 = thickness / 2.f;
715
    const float t1 = thickness - t0;
716

717
    for (int y = cy - (radius - 1) - t0; y < cy + radius + t1; y++)
718
    {
719
        if (y < 0)
720
            continue;
721

722
        if (y >= h)
723
            break;
724

725
        unsigned char* p = pixels + stride * y;
726

727
        for (int x = cx - (radius - 1) - t0; x < cx + radius + t1; x++)
728
        {
729
            if (x < 0)
730
                continue;
731

732
            if (x >= w)
733
                break;
734

735
            // distance from cx cy
736
            if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
737
            {
738
                p[x] = pen_color[0];
739
            }
740
        }
741
    }
742
}
743

744
void draw_circle_c2(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
745
{
746
    const unsigned char* pen_color = (const unsigned char*)&color;
747

748
    if (thickness == -1)
749
    {
750
        // filled
751
        for (int y = cy - (radius - 1); y < cy + radius; y++)
752
        {
753
            if (y < 0)
754
                continue;
755

756
            if (y >= h)
757
                break;
758

759
            unsigned char* p = pixels + stride * y;
760

761
            for (int x = cx - (radius - 1); x < cx + radius; x++)
762
            {
763
                if (x < 0)
764
                    continue;
765

766
                if (x >= w)
767
                    break;
768

769
                // distance from cx cy
770
                if (distance_lessequal(x, y, cx, cy, radius))
771
                {
772
                    p[x * 2 + 0] = pen_color[0];
773
                    p[x * 2 + 1] = pen_color[1];
774
                }
775
            }
776
        }
777

778
        return;
779
    }
780

781
    const float t0 = thickness / 2.f;
782
    const float t1 = thickness - t0;
783

784
    for (int y = cy - radius - t0; y < cy + radius + t1; y++)
785
    {
786
        if (y < 0)
787
            continue;
788

789
        if (y >= h)
790
            break;
791

792
        unsigned char* p = pixels + stride * y;
793

794
        for (int x = cx - radius - t0; x < cx + radius + t1; x++)
795
        {
796
            if (x < 0)
797
                continue;
798

799
            if (x >= w)
800
                break;
801

802
            // distance from cx cy
803
            if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
804
            {
805
                p[x * 2 + 0] = pen_color[0];
806
                p[x * 2 + 1] = pen_color[1];
807
            }
808
        }
809
    }
810
}
811

812
void draw_circle_c3(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
813
{
814
    const unsigned char* pen_color = (const unsigned char*)&color;
815

816
    if (thickness == -1)
817
    {
818
        // filled
819
        for (int y = cy - (radius - 1); y < cy + radius; y++)
820
        {
821
            if (y < 0)
822
                continue;
823

824
            if (y >= h)
825
                break;
826

827
            unsigned char* p = pixels + stride * y;
828

829
            for (int x = cx - (radius - 1); x < cx + radius; x++)
830
            {
831
                if (x < 0)
832
                    continue;
833

834
                if (x >= w)
835
                    break;
836

837
                // distance from cx cy
838
                if (distance_lessequal(x, y, cx, cy, radius))
839
                {
840
                    p[x * 3 + 0] = pen_color[0];
841
                    p[x * 3 + 1] = pen_color[1];
842
                    p[x * 3 + 2] = pen_color[2];
843
                }
844
            }
845
        }
846

847
        return;
848
    }
849

850
    const float t0 = thickness / 2.f;
851
    const float t1 = thickness - t0;
852

853
    for (int y = cy - radius - t0; y < cy + radius + t1; y++)
854
    {
855
        if (y < 0)
856
            continue;
857

858
        if (y >= h)
859
            break;
860

861
        unsigned char* p = pixels + stride * y;
862

863
        for (int x = cx - radius - t0; x < cx + radius + t1; x++)
864
        {
865
            if (x < 0)
866
                continue;
867

868
            if (x >= w)
869
                break;
870

871
            // distance from cx cy
872
            if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
873
            {
874
                p[x * 3 + 0] = pen_color[0];
875
                p[x * 3 + 1] = pen_color[1];
876
                p[x * 3 + 2] = pen_color[2];
877
            }
878
        }
879
    }
880
}
881

882
void draw_circle_c4(unsigned char* pixels, int w, int h, int stride, int cx, int cy, int radius, unsigned int color, int thickness)
883
{
884
    const unsigned char* pen_color = (const unsigned char*)&color;
885

886
    if (thickness == -1)
887
    {
888
        // filled
889
        for (int y = cy - (radius - 1); y < cy + radius; y++)
890
        {
891
            if (y < 0)
892
                continue;
893

894
            if (y >= h)
895
                break;
896

897
            unsigned char* p = pixels + stride * y;
898

899
            for (int x = cx - (radius - 1); x < cx + radius; x++)
900
            {
901
                if (x < 0)
902
                    continue;
903

904
                if (x >= w)
905
                    break;
906

907
                // distance from cx cy
908
                if (distance_lessequal(x, y, cx, cy, radius))
909
                {
910
                    p[x * 4 + 0] = pen_color[0];
911
                    p[x * 4 + 1] = pen_color[1];
912
                    p[x * 4 + 2] = pen_color[2];
913
                    p[x * 4 + 3] = pen_color[3];
914
                }
915
            }
916
        }
917

918
        return;
919
    }
920

921
    const float t0 = thickness / 2.f;
922
    const float t1 = thickness - t0;
923

924
    for (int y = cy - (radius - 1) - t0; y < cy + radius + t1; y++)
925
    {
926
        if (y < 0)
927
            continue;
928

929
        if (y >= h)
930
            break;
931

932
        unsigned char* p = pixels + stride * y;
933

934
        for (int x = cx - (radius - 1) - t0; x < cx + radius + t1; x++)
935
        {
936
            if (x < 0)
937
                continue;
938

939
            if (x >= w)
940
                break;
941

942
            // distance from cx cy
943
            if (distance_inrange(x, y, cx, cy, radius - t0, radius + t1))
944
            {
945
                p[x * 4 + 0] = pen_color[0];
946
                p[x * 4 + 1] = pen_color[1];
947
                p[x * 4 + 2] = pen_color[2];
948
                p[x * 4 + 3] = pen_color[3];
949
            }
950
        }
951
    }
952
}
953

954
void draw_circle_yuv420sp(unsigned char* yuv420sp, int w, int h, int cx, int cy, int radius, unsigned int color, int thickness)
955
{
956
    // assert w % 2 == 0
957
    // assert h % 2 == 0
958
    // assert cx % 2 == 0
959
    // assert cy % 2 == 0
960
    // assert radius % 2 == 0
961
    // assert thickness % 2 == 0
962

963
    const unsigned char* pen_color = (const unsigned char*)&color;
964

965
    unsigned int v_y;
966
    unsigned int v_uv;
967
    unsigned char* pen_color_y = (unsigned char*)&v_y;
968
    unsigned char* pen_color_uv = (unsigned char*)&v_uv;
969
    pen_color_y[0] = pen_color[0];
970
    pen_color_uv[0] = pen_color[1];
971
    pen_color_uv[1] = pen_color[2];
972

973
    unsigned char* Y = yuv420sp;
974
    draw_circle_c1(Y, w, h, cx, cy, radius, v_y, thickness);
975

976
    unsigned char* UV = yuv420sp + w * h;
977
    int thickness_uv = thickness == -1 ? thickness : std::max(thickness / 2, 1);
978
    draw_circle_c2(UV, w / 2, h / 2, cx / 2, cy / 2, radius / 2, v_uv, thickness_uv);
979
}
980

981
static inline bool distance_lessthan(int x, int y, int x0, int y0, int x1, int y1, float t)
982
{
983
    int dx01 = x1 - x0;
984
    int dy01 = y1 - y0;
985
    int dx0 = x - x0;
986
    int dy0 = y - y0;
987

988
    float r = (float)(dx0 * dx01 + dy0 * dy01) / (dx01 * dx01 + dy01 * dy01);
989

990
    if (r < 0 || r > 1)
991
        return false;
992

993
    float px = x0 + dx01 * r;
994
    float py = y0 + dy01 * r;
995
    float dx = x - px;
996
    float dy = y - py;
997
    float p = dx * dx + dy * dy;
998
    return p < t;
999
}
1000

1001
void draw_line_c1(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
1002
{
1003
    draw_line_c1(pixels, w, h, w, x0, y0, x1, y1, color, thickness);
1004
}
1005

1006
void draw_line_c2(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
1007
{
1008
    draw_line_c2(pixels, w, h, w * 2, x0, y0, x1, y1, color, thickness);
1009
}
1010

1011
void draw_line_c3(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
1012
{
1013
    draw_line_c3(pixels, w, h, w * 3, x0, y0, x1, y1, color, thickness);
1014
}
1015

1016
void draw_line_c4(unsigned char* pixels, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
1017
{
1018
    draw_line_c4(pixels, w, h, w * 4, x0, y0, x1, y1, color, thickness);
1019
}
1020

1021
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)
1022
{
1023
    const unsigned char* pen_color = (const unsigned char*)&color;
1024

1025
    const float t0 = thickness / 2.f;
1026
    const float t1 = thickness - t0;
1027

1028
    int x_min = std::min(x0, x1);
1029
    int x_max = std::max(x0, x1);
1030
    int y_min = std::min(y0, y1);
1031
    int y_max = std::max(y0, y1);
1032

1033
    for (int y = y_min - t0; y < y_max + t1; y++)
1034
    {
1035
        if (y < 0)
1036
            continue;
1037

1038
        if (y >= h)
1039
            break;
1040

1041
        unsigned char* p = pixels + stride * y;
1042

1043
        for (int x = x_min - t0; x < x_max + t1; x++)
1044
        {
1045
            if (x < 0)
1046
                continue;
1047

1048
            if (x >= w)
1049
                break;
1050

1051
            // distance from line
1052
            if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
1053
            {
1054
                p[x] = pen_color[0];
1055
            }
1056
        }
1057
    }
1058
}
1059

1060
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)
1061
{
1062
    const unsigned char* pen_color = (const unsigned char*)&color;
1063

1064
    const float t0 = thickness / 2.f;
1065
    const float t1 = thickness - t0;
1066

1067
    int x_min = std::min(x0, x1);
1068
    int x_max = std::max(x0, x1);
1069
    int y_min = std::min(y0, y1);
1070
    int y_max = std::max(y0, y1);
1071

1072
    for (int y = y_min - t0; y < y_max + t1; y++)
1073
    {
1074
        if (y < 0)
1075
            continue;
1076

1077
        if (y >= h)
1078
            break;
1079

1080
        unsigned char* p = pixels + stride * y;
1081

1082
        for (int x = x_min - t0; x < x_max + t1; x++)
1083
        {
1084
            if (x < 0)
1085
                continue;
1086

1087
            if (x >= w)
1088
                break;
1089

1090
            // distance from line
1091
            if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
1092
            {
1093
                p[x * 2 + 0] = pen_color[0];
1094
                p[x * 2 + 1] = pen_color[1];
1095
            }
1096
        }
1097
    }
1098
}
1099

1100
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)
1101
{
1102
    const unsigned char* pen_color = (const unsigned char*)&color;
1103

1104
    const float t0 = thickness / 2.f;
1105
    const float t1 = thickness - t0;
1106

1107
    int x_min = std::min(x0, x1);
1108
    int x_max = std::max(x0, x1);
1109
    int y_min = std::min(y0, y1);
1110
    int y_max = std::max(y0, y1);
1111

1112
    for (int y = y_min - t0; y < y_max + t1; y++)
1113
    {
1114
        if (y < 0)
1115
            continue;
1116

1117
        if (y >= h)
1118
            break;
1119

1120
        unsigned char* p = pixels + stride * y;
1121

1122
        for (int x = x_min - t0; x < x_max + t1; x++)
1123
        {
1124
            if (x < 0)
1125
                continue;
1126

1127
            if (x >= w)
1128
                break;
1129

1130
            // distance from line
1131
            if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
1132
            {
1133
                p[x * 3 + 0] = pen_color[0];
1134
                p[x * 3 + 1] = pen_color[1];
1135
                p[x * 3 + 2] = pen_color[2];
1136
            }
1137
        }
1138
    }
1139
}
1140

1141
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)
1142
{
1143
    const unsigned char* pen_color = (const unsigned char*)&color;
1144

1145
    const float t0 = thickness / 2.f;
1146
    const float t1 = thickness - t0;
1147

1148
    int x_min = std::min(x0, x1);
1149
    int x_max = std::max(x0, x1);
1150
    int y_min = std::min(y0, y1);
1151
    int y_max = std::max(y0, y1);
1152

1153
    for (int y = y_min - t0; y < y_max + t1; y++)
1154
    {
1155
        if (y < 0)
1156
            continue;
1157

1158
        if (y >= h)
1159
            break;
1160

1161
        unsigned char* p = pixels + stride * y;
1162

1163
        for (int x = x_min - t0; x < x_max + t1; x++)
1164
        {
1165
            if (x < 0)
1166
                continue;
1167

1168
            if (x >= w)
1169
                break;
1170

1171
            // distance from line
1172
            if (distance_lessthan(x, y, x0, y0, x1, y1, t1))
1173
            {
1174
                p[x * 4 + 0] = pen_color[0];
1175
                p[x * 4 + 1] = pen_color[1];
1176
                p[x * 4 + 2] = pen_color[2];
1177
                p[x * 4 + 3] = pen_color[3];
1178
            }
1179
        }
1180
    }
1181
}
1182

1183
void draw_line_yuv420sp(unsigned char* yuv420sp, int w, int h, int x0, int y0, int x1, int y1, unsigned int color, int thickness)
1184
{
1185
    // assert w % 2 == 0
1186
    // assert h % 2 == 0
1187
    // assert x0 % 2 == 0
1188
    // assert y0 % 2 == 0
1189
    // assert x1 % 2 == 0
1190
    // assert y1 % 2 == 0
1191
    // assert thickness % 2 == 0
1192

1193
    const unsigned char* pen_color = (const unsigned char*)&color;
1194

1195
    unsigned int v_y;
1196
    unsigned int v_uv;
1197
    unsigned char* pen_color_y = (unsigned char*)&v_y;
1198
    unsigned char* pen_color_uv = (unsigned char*)&v_uv;
1199
    pen_color_y[0] = pen_color[0];
1200
    pen_color_uv[0] = pen_color[1];
1201
    pen_color_uv[1] = pen_color[2];
1202

1203
    unsigned char* Y = yuv420sp;
1204
    draw_line_c1(Y, w, h, x0, y0, x1, y1, v_y, thickness);
1205

1206
    unsigned char* UV = yuv420sp + w * h;
1207
    int thickness_uv = thickness == -1 ? thickness : std::max(thickness / 2, 1);
1208
    draw_line_c2(UV, w / 2, h / 2, x0 / 2, y0 / 2, x1 / 2, y1 / 2, v_uv, thickness_uv);
1209
}
1210

1211
void get_text_drawing_size(const char* text, int fontpixelsize, int* w, int* h)
1212
{
1213
    *w = 0;
1214
    *h = 0;
1215

1216
    const int n = strlen(text);
1217

1218
    int line_w = 0;
1219
    for (int i = 0; i < n; i++)
1220
    {
1221
        char ch = text[i];
1222

1223
        if (ch == '\n')
1224
        {
1225
            // newline
1226
            *w = std::max(*w, line_w);
1227
            *h += fontpixelsize * 2;
1228
            line_w = 0;
1229
        }
1230

1231
        if (isprint(ch) != 0)
1232
        {
1233
            line_w += fontpixelsize;
1234
        }
1235
    }
1236

1237
    *w = std::max(*w, line_w);
1238
    *h += fontpixelsize * 2;
1239
}
1240

1241
void draw_text_c1(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
1242
{
1243
    return draw_text_c1(pixels, w, h, w, text, x, y, fontpixelsize, color);
1244
}
1245

1246
void draw_text_c2(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
1247
{
1248
    return draw_text_c2(pixels, w, h, w * 2, text, x, y, fontpixelsize, color);
1249
}
1250

1251
void draw_text_c3(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
1252
{
1253
    return draw_text_c3(pixels, w, h, w * 3, text, x, y, fontpixelsize, color);
1254
}
1255

1256
void draw_text_c4(unsigned char* pixels, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
1257
{
1258
    return draw_text_c4(pixels, w, h, w * 4, text, x, y, fontpixelsize, color);
1259
}
1260

1261
void resize_bilinear_font(const unsigned char* font_bitmap, unsigned char* resized_font_bitmap, int fontpixelsize)
1262
{
1263
    const int INTER_RESIZE_COEF_BITS = 11;
1264
    const int INTER_RESIZE_COEF_SCALE = 1 << INTER_RESIZE_COEF_BITS;
1265

1266
    const int srcw = 20;
1267
    const int srch = 40;
1268
    const int w = fontpixelsize;
1269
    const int h = fontpixelsize * 2;
1270

1271
    double scale = (double)srcw / w;
1272

1273
    int* buf = new int[w + h + w + h];
1274

1275
    int* xofs = buf;     //new int[w];
1276
    int* yofs = buf + w; //new int[h];
1277

1278
    short* ialpha = (short*)(buf + w + h);    //new short[w * 2];
1279
    short* ibeta = (short*)(buf + w + h + w); //new short[h * 2];
1280

1281
    float fx;
1282
    float fy;
1283
    int sx;
1284
    int sy;
1285

1286
#define SATURATE_CAST_SHORT(X) (short)::std::min(::std::max((int)(X + (X >= 0.f ? 0.5f : -0.5f)), SHRT_MIN), SHRT_MAX);
1287

1288
    for (int dx = 0; dx < w; dx++)
1289
    {
1290
        fx = (float)((dx + 0.5) * scale - 0.5);
1291
        sx = static_cast<int>(floor(fx));
1292
        fx -= sx;
1293

1294
        xofs[dx] = sx;
1295

1296
        float a0 = (1.f - fx) * INTER_RESIZE_COEF_SCALE;
1297
        float a1 = fx * INTER_RESIZE_COEF_SCALE;
1298

1299
        ialpha[dx * 2] = SATURATE_CAST_SHORT(a0);
1300
        ialpha[dx * 2 + 1] = SATURATE_CAST_SHORT(a1);
1301
    }
1302

1303
    for (int dy = 0; dy < h; dy++)
1304
    {
1305
        fy = (float)((dy + 0.5) * scale - 0.5);
1306
        sy = static_cast<int>(floor(fy));
1307
        fy -= sy;
1308

1309
        yofs[dy] = sy;
1310

1311
        float b0 = (1.f - fy) * INTER_RESIZE_COEF_SCALE;
1312
        float b1 = fy * INTER_RESIZE_COEF_SCALE;
1313

1314
        ibeta[dy * 2] = SATURATE_CAST_SHORT(b0);
1315
        ibeta[dy * 2 + 1] = SATURATE_CAST_SHORT(b1);
1316
    }
1317

1318
#undef SATURATE_CAST_SHORT
1319

1320
    // loop body
1321
    Mat rowsbuf0(w, (size_t)2u);
1322
    Mat rowsbuf1(w, (size_t)2u);
1323
    short* rows0 = (short*)rowsbuf0;
1324
    short* rows1 = (short*)rowsbuf1;
1325

1326
    {
1327
        short* rows1p = rows1;
1328
        for (int dx = 0; dx < w; dx++)
1329
        {
1330
            rows1p[dx] = 0;
1331
        }
1332
    }
1333

1334
    int prev_sy1 = -2;
1335

1336
    for (int dy = 0; dy < h; dy++)
1337
    {
1338
        sy = yofs[dy];
1339

1340
        if (sy == prev_sy1)
1341
        {
1342
            // reuse all rows
1343
        }
1344
        else if (sy == prev_sy1 + 1)
1345
        {
1346
            // hresize one row
1347
            short* rows0_old = rows0;
1348
            rows0 = rows1;
1349
            rows1 = rows0_old;
1350
            const unsigned char* S1 = font_bitmap + 10 * (sy + 1);
1351

1352
            if (sy >= srch - 1)
1353
            {
1354
                short* rows1p = rows1;
1355
                for (int dx = 0; dx < w; dx++)
1356
                {
1357
                    rows1p[dx] = 0;
1358
                }
1359
            }
1360
            else
1361
            {
1362
                const short* ialphap = ialpha;
1363
                short* rows1p = rows1;
1364
                for (int dx = 0; dx < w; dx++)
1365
                {
1366
                    sx = xofs[dx];
1367
                    short a0 = ialphap[0];
1368
                    short a1 = ialphap[1];
1369

1370
                    unsigned char S1p0;
1371
                    unsigned char S1p1;
1372

1373
                    if (sx < 0)
1374
                    {
1375
                        S1p0 = 0;
1376
                        S1p1 = S1[0] & 0x0f;
1377
                    }
1378
                    else if (sx >= srcw - 1)
1379
                    {
1380
                        S1p0 = (S1[9] & 0xf0) >> 4;
1381
                        S1p1 = 0;
1382
                    }
1383
                    else
1384
                    {
1385
                        S1p0 = sx % 2 == 0 ? S1[sx / 2] & 0x0f : (S1[sx / 2] & 0xf0) >> 4;
1386
                        S1p1 = sx % 2 == 0 ? (S1[sx / 2] & 0xf0) >> 4 : S1[sx / 2 + 1] & 0x0f;
1387
                    }
1388
                    rows1p[dx] = (S1p0 * a0 + S1p1 * a1) * 17 >> 4;
1389

1390
                    ialphap += 2;
1391
                }
1392
            }
1393
        }
1394
        else
1395
        {
1396
            // hresize two rows
1397
            const unsigned char* S0 = font_bitmap + 10 * (sy);
1398
            const unsigned char* S1 = font_bitmap + 10 * (sy + 1);
1399

1400
            if (sy >= srch - 1)
1401
            {
1402
                const short* ialphap = ialpha;
1403
                short* rows0p = rows0;
1404
                short* rows1p = rows1;
1405
                for (int dx = 0; dx < w; dx++)
1406
                {
1407
                    sx = xofs[dx];
1408
                    short a0 = ialphap[0];
1409
                    short a1 = ialphap[1];
1410

1411
                    unsigned char S0p0;
1412
                    unsigned char S0p1;
1413

1414
                    if (sx < 0)
1415
                    {
1416
                        S0p0 = 0;
1417
                        S0p1 = S0[0] & 0x0f;
1418
                    }
1419
                    else if (sx >= srcw - 1)
1420
                    {
1421
                        S0p0 = (S0[9] & 0xf0) >> 4;
1422
                        S0p1 = 0;
1423
                    }
1424
                    else
1425
                    {
1426
                        S0p0 = sx % 2 == 0 ? S0[sx / 2] & 0x0f : (S0[sx / 2] & 0xf0) >> 4;
1427
                        S0p1 = sx % 2 == 0 ? (S0[sx / 2] & 0xf0) >> 4 : S0[sx / 2 + 1] & 0x0f;
1428
                    }
1429
                    rows0p[dx] = (S0p0 * a0 + S0p1 * a1) * 17 >> 4;
1430
                    rows1p[dx] = 0;
1431

1432
                    ialphap += 2;
1433
                }
1434
            }
1435
            else
1436
            {
1437
                const short* ialphap = ialpha;
1438
                short* rows0p = rows0;
1439
                short* rows1p = rows1;
1440
                for (int dx = 0; dx < w; dx++)
1441
                {
1442
                    sx = xofs[dx];
1443
                    short a0 = ialphap[0];
1444
                    short a1 = ialphap[1];
1445

1446
                    unsigned char S0p0;
1447
                    unsigned char S0p1;
1448
                    unsigned char S1p0;
1449
                    unsigned char S1p1;
1450

1451
                    if (sx < 0)
1452
                    {
1453
                        S0p0 = 0;
1454
                        S0p1 = S0[0] & 0x0f;
1455
                        S1p0 = 0;
1456
                        S1p1 = S1[0] & 0x0f;
1457
                    }
1458
                    else if (sx >= srcw - 1)
1459
                    {
1460
                        S0p0 = (S0[9] & 0xf0) >> 4;
1461
                        S0p1 = 0;
1462
                        S1p0 = (S1[9] & 0xf0) >> 4;
1463
                        S1p1 = 0;
1464
                    }
1465
                    else
1466
                    {
1467
                        S0p0 = sx % 2 == 0 ? S0[sx / 2] & 0x0f : (S0[sx / 2] & 0xf0) >> 4;
1468
                        S0p1 = sx % 2 == 0 ? (S0[sx / 2] & 0xf0) >> 4 : S0[sx / 2 + 1] & 0x0f;
1469
                        S1p0 = sx % 2 == 0 ? S1[sx / 2] & 0x0f : (S1[sx / 2] & 0xf0) >> 4;
1470
                        S1p1 = sx % 2 == 0 ? (S1[sx / 2] & 0xf0) >> 4 : S1[sx / 2 + 1] & 0x0f;
1471
                    }
1472
                    rows0p[dx] = (S0p0 * a0 + S0p1 * a1) * 17 >> 4;
1473
                    rows1p[dx] = (S1p0 * a0 + S1p1 * a1) * 17 >> 4;
1474

1475
                    ialphap += 2;
1476
                }
1477
            }
1478
        }
1479

1480
        prev_sy1 = sy;
1481

1482
        if (dy + 1 < h && yofs[dy + 1] == sy)
1483
        {
1484
            // vresize for two rows
1485
            short b0 = ibeta[0];
1486
            short b1 = ibeta[1];
1487
            short b2 = ibeta[2];
1488
            short b3 = ibeta[3];
1489

1490
            short* rows0p = rows0;
1491
            short* rows1p = rows1;
1492
            unsigned char* Dp0 = resized_font_bitmap + w * (dy);
1493
            unsigned char* Dp1 = resized_font_bitmap + w * (dy + 1);
1494

1495
            int dx = 0;
1496
#if __ARM_NEON
1497
            int16x8_t _b0 = vdupq_n_s16(b0);
1498
            int16x8_t _b1 = vdupq_n_s16(b1);
1499
            int16x8_t _b2 = vdupq_n_s16(b2);
1500
            int16x8_t _b3 = vdupq_n_s16(b3);
1501
            for (; dx + 15 < w; dx += 16)
1502
            {
1503
                int16x8_t _r00 = vld1q_s16(rows0p);
1504
                int16x8_t _r01 = vld1q_s16(rows0p + 8);
1505
                int16x8_t _r10 = vld1q_s16(rows1p);
1506
                int16x8_t _r11 = vld1q_s16(rows1p + 8);
1507
                int16x8_t _acc00 = vaddq_s16(vqdmulhq_s16(_r00, _b0), vqdmulhq_s16(_r10, _b1));
1508
                int16x8_t _acc01 = vaddq_s16(vqdmulhq_s16(_r01, _b0), vqdmulhq_s16(_r11, _b1));
1509
                int16x8_t _acc10 = vaddq_s16(vqdmulhq_s16(_r00, _b2), vqdmulhq_s16(_r10, _b3));
1510
                int16x8_t _acc11 = vaddq_s16(vqdmulhq_s16(_r01, _b2), vqdmulhq_s16(_r11, _b3));
1511
                uint8x16_t _Dp0 = vcombine_u8(vqrshrun_n_s16(_acc00, 3), vqrshrun_n_s16(_acc01, 3));
1512
                uint8x16_t _Dp1 = vcombine_u8(vqrshrun_n_s16(_acc10, 3), vqrshrun_n_s16(_acc11, 3));
1513
                vst1q_u8(Dp0, _Dp0);
1514
                vst1q_u8(Dp1, _Dp1);
1515
                Dp0 += 16;
1516
                Dp1 += 16;
1517
                rows0p += 16;
1518
                rows1p += 16;
1519
            }
1520
            for (; dx + 7 < w; dx += 8)
1521
            {
1522
                int16x8_t _r0 = vld1q_s16(rows0p);
1523
                int16x8_t _r1 = vld1q_s16(rows1p);
1524
                int16x8_t _acc0 = vaddq_s16(vqdmulhq_s16(_r0, _b0), vqdmulhq_s16(_r1, _b1));
1525
                int16x8_t _acc1 = vaddq_s16(vqdmulhq_s16(_r0, _b2), vqdmulhq_s16(_r1, _b3));
1526
                uint8x8_t _Dp0 = vqrshrun_n_s16(_acc0, 3);
1527
                uint8x8_t _Dp1 = vqrshrun_n_s16(_acc1, 3);
1528
                vst1_u8(Dp0, _Dp0);
1529
                vst1_u8(Dp1, _Dp1);
1530
                Dp0 += 8;
1531
                Dp1 += 8;
1532
                rows0p += 8;
1533
                rows1p += 8;
1534
            }
1535
#endif // __ARM_NEON
1536
#if __SSE2__
1537
            __m128i _b0 = _mm_set1_epi16(b0);
1538
            __m128i _b1 = _mm_set1_epi16(b1);
1539
            __m128i _b2 = _mm_set1_epi16(b2);
1540
            __m128i _b3 = _mm_set1_epi16(b3);
1541
            __m128i _v2 = _mm_set1_epi16(2);
1542
            for (; dx + 15 < w; dx += 16)
1543
            {
1544
                __m128i _r00 = _mm_loadu_si128((const __m128i*)rows0p);
1545
                __m128i _r01 = _mm_loadu_si128((const __m128i*)(rows0p + 8));
1546
                __m128i _r10 = _mm_loadu_si128((const __m128i*)rows1p);
1547
                __m128i _r11 = _mm_loadu_si128((const __m128i*)(rows1p + 8));
1548
                __m128i _acc00 = _mm_add_epi16(_mm_mulhi_epi16(_r00, _b0), _mm_mulhi_epi16(_r10, _b1));
1549
                __m128i _acc01 = _mm_add_epi16(_mm_mulhi_epi16(_r01, _b0), _mm_mulhi_epi16(_r11, _b1));
1550
                __m128i _acc10 = _mm_add_epi16(_mm_mulhi_epi16(_r00, _b2), _mm_mulhi_epi16(_r10, _b3));
1551
                __m128i _acc11 = _mm_add_epi16(_mm_mulhi_epi16(_r01, _b2), _mm_mulhi_epi16(_r11, _b3));
1552
                _acc00 = _mm_srai_epi16(_mm_add_epi16(_acc00, _v2), 2);
1553
                _acc01 = _mm_srai_epi16(_mm_add_epi16(_acc01, _v2), 2);
1554
                _acc10 = _mm_srai_epi16(_mm_add_epi16(_acc10, _v2), 2);
1555
                _acc11 = _mm_srai_epi16(_mm_add_epi16(_acc11, _v2), 2);
1556
                __m128i _Dp0 = _mm_packus_epi16(_acc00, _acc01);
1557
                __m128i _Dp1 = _mm_packus_epi16(_acc10, _acc11);
1558
                _mm_storeu_si128((__m128i*)Dp0, _Dp0);
1559
                _mm_storeu_si128((__m128i*)Dp1, _Dp1);
1560
                Dp0 += 16;
1561
                Dp1 += 16;
1562
                rows0p += 16;
1563
                rows1p += 16;
1564
            }
1565
            for (; dx + 7 < w; dx += 8)
1566
            {
1567
                __m128i _r0 = _mm_loadu_si128((const __m128i*)rows0p);
1568
                __m128i _r1 = _mm_loadu_si128((const __m128i*)rows1p);
1569
                __m128i _acc0 = _mm_add_epi16(_mm_mulhi_epi16(_r0, _b0), _mm_mulhi_epi16(_r1, _b1));
1570
                __m128i _acc1 = _mm_add_epi16(_mm_mulhi_epi16(_r0, _b2), _mm_mulhi_epi16(_r1, _b3));
1571
                _acc0 = _mm_srai_epi16(_mm_add_epi16(_acc0, _v2), 2);
1572
                _acc1 = _mm_srai_epi16(_mm_add_epi16(_acc1, _v2), 2);
1573
                __m128i _Dp0 = _mm_packus_epi16(_acc0, _acc0);
1574
                __m128i _Dp1 = _mm_packus_epi16(_acc1, _acc1);
1575
                _mm_storel_epi64((__m128i*)Dp0, _Dp0);
1576
                _mm_storel_epi64((__m128i*)Dp1, _Dp1);
1577
                Dp0 += 8;
1578
                Dp1 += 8;
1579
                rows0p += 8;
1580
                rows1p += 8;
1581
            }
1582
#endif // __SSE2__
1583
            for (; dx < w; dx++)
1584
            {
1585
                short s0 = *rows0p++;
1586
                short s1 = *rows1p++;
1587

1588
                *Dp0++ = (unsigned char)(((short)((b0 * s0) >> 16) + (short)((b1 * s1) >> 16) + 2) >> 2);
1589
                *Dp1++ = (unsigned char)(((short)((b2 * s0) >> 16) + (short)((b3 * s1) >> 16) + 2) >> 2);
1590
            }
1591

1592
            ibeta += 4;
1593
            dy += 1;
1594
        }
1595
        else
1596
        {
1597
            // vresize
1598
            short b0 = ibeta[0];
1599
            short b1 = ibeta[1];
1600

1601
            short* rows0p = rows0;
1602
            short* rows1p = rows1;
1603
            unsigned char* Dp = resized_font_bitmap + w * (dy);
1604

1605
            int dx = 0;
1606
#if __ARM_NEON
1607
            int16x8_t _b0 = vdupq_n_s16(b0);
1608
            int16x8_t _b1 = vdupq_n_s16(b1);
1609
            for (; dx + 15 < w; dx += 16)
1610
            {
1611
                int16x8_t _r00 = vld1q_s16(rows0p);
1612
                int16x8_t _r01 = vld1q_s16(rows0p + 8);
1613
                int16x8_t _r10 = vld1q_s16(rows1p);
1614
                int16x8_t _r11 = vld1q_s16(rows1p + 8);
1615
                int16x8_t _acc0 = vaddq_s16(vqdmulhq_s16(_r00, _b0), vqdmulhq_s16(_r10, _b1));
1616
                int16x8_t _acc1 = vaddq_s16(vqdmulhq_s16(_r01, _b0), vqdmulhq_s16(_r11, _b1));
1617
                uint8x16_t _Dp = vcombine_u8(vqrshrun_n_s16(_acc0, 3), vqrshrun_n_s16(_acc1, 3));
1618
                vst1q_u8(Dp, _Dp);
1619
                Dp += 16;
1620
                rows0p += 16;
1621
                rows1p += 16;
1622
            }
1623
            for (; dx + 7 < w; dx += 8)
1624
            {
1625
                int16x8_t _r0 = vld1q_s16(rows0p);
1626
                int16x8_t _r1 = vld1q_s16(rows1p);
1627
                int16x8_t _acc = vaddq_s16(vqdmulhq_s16(_r0, _b0), vqdmulhq_s16(_r1, _b1));
1628
                uint8x8_t _Dp = vqrshrun_n_s16(_acc, 3);
1629
                vst1_u8(Dp, _Dp);
1630
                Dp += 8;
1631
                rows0p += 8;
1632
                rows1p += 8;
1633
            }
1634
#endif // __ARM_NEON
1635
#if __SSE2__
1636
            __m128i _b0 = _mm_set1_epi16(b0);
1637
            __m128i _b1 = _mm_set1_epi16(b1);
1638
            __m128i _v2 = _mm_set1_epi16(2);
1639
            for (; dx + 15 < w; dx += 16)
1640
            {
1641
                __m128i _r00 = _mm_loadu_si128((const __m128i*)rows0p);
1642
                __m128i _r01 = _mm_loadu_si128((const __m128i*)(rows0p + 8));
1643
                __m128i _r10 = _mm_loadu_si128((const __m128i*)rows1p);
1644
                __m128i _r11 = _mm_loadu_si128((const __m128i*)(rows1p + 8));
1645
                __m128i _acc0 = _mm_add_epi16(_mm_mulhi_epi16(_r00, _b0), _mm_mulhi_epi16(_r10, _b1));
1646
                __m128i _acc1 = _mm_add_epi16(_mm_mulhi_epi16(_r01, _b0), _mm_mulhi_epi16(_r11, _b1));
1647
                _acc0 = _mm_srai_epi16(_mm_add_epi16(_acc0, _v2), 2);
1648
                _acc1 = _mm_srai_epi16(_mm_add_epi16(_acc1, _v2), 2);
1649
                __m128i _Dp = _mm_packus_epi16(_acc0, _acc1);
1650
                _mm_storeu_si128((__m128i*)Dp, _Dp);
1651
                Dp += 16;
1652
                rows0p += 16;
1653
                rows1p += 16;
1654
            }
1655
            for (; dx + 7 < w; dx += 8)
1656
            {
1657
                __m128i _r0 = _mm_loadu_si128((const __m128i*)rows0p);
1658
                __m128i _r1 = _mm_loadu_si128((const __m128i*)rows1p);
1659
                __m128i _acc = _mm_add_epi16(_mm_mulhi_epi16(_r0, _b0), _mm_mulhi_epi16(_r1, _b1));
1660
                _acc = _mm_srai_epi16(_mm_add_epi16(_acc, _v2), 2);
1661
                __m128i _Dp = _mm_packus_epi16(_acc, _acc);
1662
                _mm_storel_epi64((__m128i*)Dp, _Dp);
1663
                Dp += 8;
1664
                rows0p += 8;
1665
                rows1p += 8;
1666
            }
1667
#endif // __SSE2__
1668
            for (; dx < w; dx++)
1669
            {
1670
                short s0 = *rows0p++;
1671
                short s1 = *rows1p++;
1672

1673
                *Dp++ = (unsigned char)(((short)((b0 * s0) >> 16) + (short)((b1 * s1) >> 16) + 2) >> 2);
1674
            }
1675

1676
            ibeta += 2;
1677
        }
1678
    }
1679

1680
    delete[] buf;
1681
}
1682

1683
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)
1684
{
1685
    const unsigned char* pen_color = (const unsigned char*)&color;
1686

1687
    unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
1688

1689
    const int n = strlen(text);
1690

1691
    int cursor_x = x;
1692
    int cursor_y = y;
1693
    for (int i = 0; i < n; i++)
1694
    {
1695
        char ch = text[i];
1696

1697
        if (ch == '\n')
1698
        {
1699
            // newline
1700
            cursor_x = x;
1701
            cursor_y += fontpixelsize * 2;
1702
            continue;
1703
        }
1704

1705
        if (ch == ' ')
1706
        {
1707
            cursor_x += fontpixelsize;
1708
            continue;
1709
        }
1710

1711
        if (isprint(ch) != 0)
1712
        {
1713
            const unsigned char* font_bitmap = mono_font_data[ch - '!'];
1714

1715
            // draw resized character
1716
            resize_bilinear_font(font_bitmap, resized_font_bitmap, fontpixelsize);
1717

1718
            const int ystart = std::max(cursor_y, 0);
1719
            const int yend = std::min(cursor_y + fontpixelsize * 2, h);
1720
            const int xstart = std::max(cursor_x, 0);
1721
            const int xend = std::min(cursor_x + fontpixelsize, w);
1722

1723
            for (int j = ystart; j < yend; j++)
1724
            {
1725
                const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize + xstart - cursor_x;
1726
                unsigned char* p = pixels + stride * j + xstart;
1727

1728
                for (int k = xstart; k < xend; k++)
1729
                {
1730
                    unsigned char alpha = *palpha++;
1731

1732
                    p[0] = (p[0] * (255 - alpha) + pen_color[0] * alpha) / 255;
1733
                    p += 1;
1734
                }
1735
            }
1736

1737
            cursor_x += fontpixelsize;
1738
        }
1739
    }
1740

1741
    delete[] resized_font_bitmap;
1742
}
1743

1744
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)
1745
{
1746
    const unsigned char* pen_color = (const unsigned char*)&color;
1747

1748
    unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
1749

1750
    const int n = strlen(text);
1751

1752
    int cursor_x = x;
1753
    int cursor_y = y;
1754
    for (int i = 0; i < n; i++)
1755
    {
1756
        char ch = text[i];
1757

1758
        if (ch == '\n')
1759
        {
1760
            // newline
1761
            cursor_x = x;
1762
            cursor_y += fontpixelsize * 2;
1763
            continue;
1764
        }
1765

1766
        if (ch == ' ')
1767
        {
1768
            cursor_x += fontpixelsize;
1769
            continue;
1770
        }
1771

1772
        if (isprint(ch) != 0)
1773
        {
1774
            const unsigned char* font_bitmap = mono_font_data[ch - '!'];
1775

1776
            // draw resized character
1777
            resize_bilinear_font(font_bitmap, resized_font_bitmap, fontpixelsize);
1778

1779
            const int ystart = std::max(cursor_y, 0);
1780
            const int yend = std::min(cursor_y + fontpixelsize * 2, h);
1781
            const int xstart = std::max(cursor_x, 0);
1782
            const int xend = std::min(cursor_x + fontpixelsize, w);
1783

1784
            for (int j = ystart; j < yend; j++)
1785
            {
1786
                const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize + xstart - cursor_x;
1787
                unsigned char* p = pixels + stride * j + xstart * 2;
1788

1789
                for (int k = xstart; k < xend; k++)
1790
                {
1791
                    unsigned char alpha = *palpha++;
1792

1793
                    p[0] = (p[0] * (255 - alpha) + pen_color[0] * alpha) / 255;
1794
                    p[1] = (p[1] * (255 - alpha) + pen_color[1] * alpha) / 255;
1795
                    p += 2;
1796
                }
1797
            }
1798

1799
            cursor_x += fontpixelsize;
1800
        }
1801
    }
1802

1803
    delete[] resized_font_bitmap;
1804
}
1805

1806
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)
1807
{
1808
    const unsigned char* pen_color = (const unsigned char*)&color;
1809

1810
    unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
1811

1812
    const int n = strlen(text);
1813

1814
    int cursor_x = x;
1815
    int cursor_y = y;
1816
    for (int i = 0; i < n; i++)
1817
    {
1818
        char ch = text[i];
1819

1820
        if (ch == '\n')
1821
        {
1822
            // newline
1823
            cursor_x = x;
1824
            cursor_y += fontpixelsize * 2;
1825
            continue;
1826
        }
1827

1828
        if (ch == ' ')
1829
        {
1830
            cursor_x += fontpixelsize;
1831
            continue;
1832
        }
1833

1834
        if (isprint(ch) != 0)
1835
        {
1836
            const unsigned char* font_bitmap = mono_font_data[ch - '!'];
1837

1838
            // draw resized character
1839
            resize_bilinear_font(font_bitmap, resized_font_bitmap, fontpixelsize);
1840

1841
            const int ystart = std::max(cursor_y, 0);
1842
            const int yend = std::min(cursor_y + fontpixelsize * 2, h);
1843
            const int xstart = std::max(cursor_x, 0);
1844
            const int xend = std::min(cursor_x + fontpixelsize, w);
1845

1846
            for (int j = ystart; j < yend; j++)
1847
            {
1848
                const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize + xstart - cursor_x;
1849
                unsigned char* p = pixels + stride * j + xstart * 3;
1850

1851
                for (int k = xstart; k < xend; k++)
1852
                {
1853
                    unsigned char alpha = *palpha++;
1854

1855
                    p[0] = (p[0] * (255 - alpha) + pen_color[0] * alpha) / 255;
1856
                    p[1] = (p[1] * (255 - alpha) + pen_color[1] * alpha) / 255;
1857
                    p[2] = (p[2] * (255 - alpha) + pen_color[2] * alpha) / 255;
1858
                    p += 3;
1859
                }
1860
            }
1861

1862
            cursor_x += fontpixelsize;
1863
        }
1864
    }
1865

1866
    delete[] resized_font_bitmap;
1867
}
1868

1869
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)
1870
{
1871
    const unsigned char* pen_color = (const unsigned char*)&color;
1872

1873
    unsigned char* resized_font_bitmap = new unsigned char[fontpixelsize * fontpixelsize * 2];
1874

1875
    const int n = strlen(text);
1876

1877
    int cursor_x = x;
1878
    int cursor_y = y;
1879
    for (int i = 0; i < n; i++)
1880
    {
1881
        char ch = text[i];
1882

1883
        if (ch == '\n')
1884
        {
1885
            // newline
1886
            cursor_x = x;
1887
            cursor_y += fontpixelsize * 2;
1888
            continue;
1889
        }
1890

1891
        if (ch == ' ')
1892
        {
1893
            cursor_x += fontpixelsize;
1894
            continue;
1895
        }
1896

1897
        if (isprint(ch) != 0)
1898
        {
1899
            const unsigned char* font_bitmap = mono_font_data[ch - '!'];
1900

1901
            // draw resized character
1902
            resize_bilinear_font(font_bitmap, resized_font_bitmap, fontpixelsize);
1903

1904
            const int ystart = std::max(cursor_y, 0);
1905
            const int yend = std::min(cursor_y + fontpixelsize * 2, h);
1906
            const int xstart = std::max(cursor_x, 0);
1907
            const int xend = std::min(cursor_x + fontpixelsize, w);
1908

1909
            for (int j = ystart; j < yend; j++)
1910
            {
1911
                const unsigned char* palpha = resized_font_bitmap + (j - cursor_y) * fontpixelsize + xstart - cursor_x;
1912
                unsigned char* p = pixels + stride * j + xstart * 4;
1913

1914
                for (int k = xstart; k < xend; k++)
1915
                {
1916
                    unsigned char alpha = *palpha++;
1917

1918
                    p[0] = (p[0] * (255 - alpha) + pen_color[0] * alpha) / 255;
1919
                    p[1] = (p[1] * (255 - alpha) + pen_color[1] * alpha) / 255;
1920
                    p[2] = (p[2] * (255 - alpha) + pen_color[2] * alpha) / 255;
1921
                    p[3] = (p[3] * (255 - alpha) + pen_color[3] * alpha) / 255;
1922
                    p += 4;
1923
                }
1924
            }
1925

1926
            cursor_x += fontpixelsize;
1927
        }
1928
    }
1929

1930
    delete[] resized_font_bitmap;
1931
}
1932

1933
void draw_text_yuv420sp(unsigned char* yuv420sp, int w, int h, const char* text, int x, int y, int fontpixelsize, unsigned int color)
1934
{
1935
    // assert w % 2 == 0
1936
    // assert h % 2 == 0
1937
    // assert x % 2 == 0
1938
    // assert y % 2 == 0
1939
    // assert fontpixelsize % 2 == 0
1940

1941
    const unsigned char* pen_color = (const unsigned char*)&color;
1942

1943
    unsigned int v_y;
1944
    unsigned int v_uv;
1945
    unsigned char* pen_color_y = (unsigned char*)&v_y;
1946
    unsigned char* pen_color_uv = (unsigned char*)&v_uv;
1947
    pen_color_y[0] = pen_color[0];
1948
    pen_color_uv[0] = pen_color[1];
1949
    pen_color_uv[1] = pen_color[2];
1950

1951
    unsigned char* Y = yuv420sp;
1952
    draw_text_c1(Y, w, h, text, x, y, fontpixelsize, v_y);
1953

1954
    unsigned char* UV = yuv420sp + w * h;
1955
    draw_text_c2(UV, w / 2, h / 2, text, x / 2, y / 2, std::max(fontpixelsize / 2, 1), v_uv);
1956
}
1957

1958
#endif // NCNN_PIXEL_DRAWING
1959

1960
} // namespace ncnn
1961

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.