1 #include "drawing.h"
2 #include "string.h"
3
4 #define max(a, b) (((a) > (b)) ? (a) : (b))
5 #define min(a, b) (((a) < (b)) ? (a) : (b))
6
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)7 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)
8 {
9 const unsigned char* pen_color = (const unsigned char*)&color;
10
11 if (thickness == -1)
12 {
13 // filled
14 for (int y = ry; y < ry + rh; y++)
15 {
16 if (y < 0)
17 continue;
18
19 if (y >= h)
20 break;
21
22 unsigned char* p = pixels + stride * y;
23
24 for (int x = rx; x < rx + rw; x++)
25 {
26 if (x < 0)
27 continue;
28
29 if (x >= w)
30 break;
31
32 p[x] = pen_color[0];
33 }
34 }
35
36 return;
37 }
38
39 const int t0 = thickness / 2;
40 const int t1 = thickness - t0;
41
42 // draw top
43 {
44 for (int y = ry - t0; y < ry + t1; y++)
45 {
46 if (y < 0)
47 continue;
48
49 if (y >= h)
50 break;
51
52 unsigned char* p = pixels + stride * y;
53
54 for (int x = rx - t0; x < rx + rw + t1; x++)
55 {
56 if (x < 0)
57 continue;
58
59 if (x >= w)
60 break;
61
62 p[x] = pen_color[0];
63 }
64 }
65 }
66
67 // draw bottom
68 {
69 for (int y = ry + rh - t0; y < ry + rh + t1; y++)
70 {
71 if (y < 0)
72 continue;
73
74 if (y >= h)
75 break;
76
77 unsigned char* p = pixels + stride * y;
78
79 for (int x = rx - t0; x < rx + rw + t1; x++)
80 {
81 if (x < 0)
82 continue;
83
84 if (x >= w)
85 break;
86
87 p[x] = pen_color[0];
88 }
89 }
90 }
91
92 // draw left
93 for (int x = rx - t0; x < rx + t1; x++)
94 {
95 if (x < 0)
96 continue;
97
98 if (x >= w)
99 break;
100
101 for (int y = ry + t1; y < ry + rh - t0; y++)
102 {
103 if (y < 0)
104 continue;
105
106 if (y >= h)
107 break;
108
109 unsigned char* p = pixels + stride * y;
110
111 p[x] = pen_color[0];
112 }
113 }
114
115 // draw right
116 for (int x = rx + rw - t0; x < rx + rw + t1; x++)
117 {
118 if (x < 0)
119 continue;
120
121 if (x >= w)
122 break;
123
124 for (int y = ry + t1; y < ry + rh - t0; y++)
125 {
126 if (y < 0)
127 continue;
128
129 if (y >= h)
130 break;
131
132 unsigned char* p = pixels + stride * y;
133
134 p[x] = pen_color[0];
135 }
136 }
137 }
138
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)139 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)
140 {
141 const unsigned char* pen_color = (const unsigned char*)&color;
142
143 if (thickness == -1)
144 {
145 // filled
146 for (int y = ry; y < ry + rh; y++)
147 {
148 if (y < 0)
149 continue;
150
151 if (y >= h)
152 break;
153
154 unsigned char* p = pixels + stride * y;
155
156 for (int x = rx; x < rx + rw; x++)
157 {
158 if (x < 0)
159 continue;
160
161 if (x >= w)
162 break;
163
164 p[x * 2 + 0] = pen_color[0];
165 p[x * 2 + 1] = pen_color[1];
166 }
167 }
168
169 return;
170 }
171
172 const int t0 = thickness / 2;
173 const int t1 = thickness - t0;
174
175 // draw top
176 {
177 for (int y = ry - t0; y < ry + t1; y++)
178 {
179 if (y < 0)
180 continue;
181
182 if (y >= h)
183 break;
184
185 unsigned char* p = pixels + stride * y;
186
187 for (int x = rx - t0; x < rx + rw + t1; x++)
188 {
189 if (x < 0)
190 continue;
191
192 if (x >= w)
193 break;
194
195 p[x * 2 + 0] = pen_color[0];
196 p[x * 2 + 1] = pen_color[1];
197 }
198 }
199 }
200
201 // draw bottom
202 {
203 for (int y = ry + rh - t0; y < ry + rh + t1; y++)
204 {
205 if (y < 0)
206 continue;
207
208 if (y >= h)
209 break;
210
211 unsigned char* p = pixels + stride * y;
212
213 for (int x = rx - t0; x < rx + rw + t1; x++)
214 {
215 if (x < 0)
216 continue;
217
218 if (x >= w)
219 break;
220
221 p[x * 2 + 0] = pen_color[0];
222 p[x * 2 + 1] = pen_color[1];
223 }
224 }
225 }
226
227 // draw left
228 for (int x = rx - t0; x < rx + t1; x++)
229 {
230 if (x < 0)
231 continue;
232
233 if (x >= w)
234 break;
235
236 for (int y = ry + t1; y < ry + rh - t0; y++)
237 {
238 if (y < 0)
239 continue;
240
241 if (y >= h)
242 break;
243
244 unsigned char* p = pixels + stride * y;
245
246 p[x * 2 + 0] = pen_color[0];
247 p[x * 2 + 1] = pen_color[1];
248 }
249 }
250
251 // draw right
252 for (int x = rx + rw - t0; x < rx + rw + t1; x++)
253 {
254 if (x < 0)
255 continue;
256
257 if (x >= w)
258 break;
259
260 for (int y = ry + t1; y < ry + rh - t0; y++)
261 {
262 if (y < 0)
263 continue;
264
265 if (y >= h)
266 break;
267
268 unsigned char* p = pixels + stride * y;
269
270 p[x * 2 + 0] = pen_color[0];
271 p[x * 2 + 1] = pen_color[1];
272 }
273 }
274 }
275
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)276 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)
277 {
278 const unsigned char* pen_color = (const unsigned char*)&color;
279
280 if (thickness == -1)
281 {
282 // filled
283 for (int y = ry; y < ry + rh; y++)
284 {
285 if (y < 0)
286 continue;
287
288 if (y >= h)
289 break;
290
291 unsigned char* p = pixels + stride * y;
292
293 for (int x = rx; x < rx + rw; x++)
294 {
295 if (x < 0)
296 continue;
297
298 if (x >= w)
299 break;
300
301 p[x * 3 + 0] = pen_color[0];
302 p[x * 3 + 1] = pen_color[1];
303 p[x * 3 + 2] = pen_color[2];
304 }
305 }
306
307 return;
308 }
309
310 const int t0 = thickness / 2;
311 const int t1 = thickness - t0;
312
313 // draw top
314 {
315 for (int y = ry - t0; y < ry + t1; y++)
316 {
317 if (y < 0)
318 continue;
319
320 if (y >= h)
321 break;
322
323 unsigned char* p = pixels + stride * y;
324
325 for (int x = rx - t0; x < rx + rw + t1; x++)
326 {
327 if (x < 0)
328 continue;
329
330 if (x >= w)
331 break;
332
333 p[x * 3 + 0] = pen_color[0];
334 p[x * 3 + 1] = pen_color[1];
335 p[x * 3 + 2] = pen_color[2];
336 }
337 }
338 }
339
340 // draw bottom
341 {
342 for (int y = ry + rh - t0; y < ry + rh + t1; y++)
343 {
344 if (y < 0)
345 continue;
346
347 if (y >= h)
348 break;
349
350 unsigned char* p = pixels + stride * y;
351
352 for (int x = rx - t0; x < rx + rw + t1; x++)
353 {
354 if (x < 0)
355 continue;
356
357 if (x >= w)
358 break;
359
360 p[x * 3 + 0] = pen_color[0];
361 p[x * 3 + 1] = pen_color[1];
362 p[x * 3 + 2] = pen_color[2];
363 }
364 }
365 }
366
367 // draw left
368 for (int x = rx - t0; x < rx + t1; x++)
369 {
370 if (x < 0)
371 continue;
372
373 if (x >= w)
374 break;
375
376 for (int y = ry + t1; y < ry + rh - t0; y++)
377 {
378 if (y < 0)
379 continue;
380
381 if (y >= h)
382 break;
383
384 unsigned char* p = pixels + stride * y;
385
386 p[x * 3 + 0] = pen_color[0];
387 p[x * 3 + 1] = pen_color[1];
388 p[x * 3 + 2] = pen_color[2];
389 }
390 }
391
392 // draw right
393 for (int x = rx + rw - t0; x < rx + rw + t1; x++)
394 {
395 if (x < 0)
396 continue;
397
398 if (x >= w)
399 break;
400
401 for (int y = ry + t1; y < ry + rh - t0; y++)
402 {
403 if (y < 0)
404 continue;
405
406 if (y >= h)
407 break;
408
409 unsigned char* p = pixels + stride * y;
410
411 p[x * 3 + 0] = pen_color[0];
412 p[x * 3 + 1] = pen_color[1];
413 p[x * 3 + 2] = pen_color[2];
414 }
415 }
416 }
417
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)418 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)
419 {
420 const unsigned char* pen_color = (const unsigned char*)&color;
421
422 if (thickness == -1)
423 {
424 // filled
425 for (int y = ry; y < ry + rh; 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 for (int x = rx; x < rx + rw; x++)
436 {
437 if (x < 0)
438 continue;
439
440 if (x >= w)
441 break;
442
443 p[x * 4 + 0] = pen_color[0];
444 p[x * 4 + 1] = pen_color[1];
445 p[x * 4 + 2] = pen_color[2];
446 p[x * 4 + 3] = pen_color[3];
447 }
448 }
449
450 return;
451 }
452
453 const int t0 = thickness / 2;
454 const int t1 = thickness - t0;
455
456 // draw top
457 {
458 for (int y = ry - t0; y < ry + t1; y++)
459 {
460 if (y < 0)
461 continue;
462
463 if (y >= h)
464 break;
465
466 unsigned char* p = pixels + stride * y;
467
468 for (int x = rx - t0; x < rx + rw + t1; x++)
469 {
470 if (x < 0)
471 continue;
472
473 if (x >= w)
474 break;
475
476 p[x * 4 + 0] = pen_color[0];
477 p[x * 4 + 1] = pen_color[1];
478 p[x * 4 + 2] = pen_color[2];
479 p[x * 4 + 3] = pen_color[3];
480 }
481 }
482 }
483
484 // draw bottom
485 {
486 for (int y = ry + rh - t0; y < ry + rh + t1; y++)
487 {
488 if (y < 0)
489 continue;
490
491 if (y >= h)
492 break;
493
494 unsigned char* p = pixels + stride * y;
495
496 for (int x = rx - t0; x < rx + rw + t1; x++)
497 {
498 if (x < 0)
499 continue;
500
501 if (x >= w)
502 break;
503
504 p[x * 4 + 0] = pen_color[0];
505 p[x * 4 + 1] = pen_color[1];
506 p[x * 4 + 2] = pen_color[2];
507 p[x * 4 + 3] = pen_color[3];
508 }
509 }
510 }
511
512 // draw left
513 for (int x = rx - t0; x < rx + t1; x++)
514 {
515 if (x < 0)
516 continue;
517
518 if (x >= w)
519 break;
520
521 for (int y = ry + t1; y < ry + rh - t0; y++)
522 {
523 if (y < 0)
524 continue;
525
526 if (y >= h)
527 break;
528
529 unsigned char* p = pixels + stride * y;
530
531 p[x * 4 + 0] = pen_color[0];
532 p[x * 4 + 1] = pen_color[1];
533 p[x * 4 + 2] = pen_color[2];
534 p[x * 4 + 3] = pen_color[3];
535 }
536 }
537
538 // draw right
539 for (int x = rx + rw - t0; x < rx + rw + t1; x++)
540 {
541 if (x < 0)
542 continue;
543
544 if (x >= w)
545 break;
546
547 for (int y = ry + t1; y < ry + rh - t0; y++)
548 {
549 if (y < 0)
550 continue;
551
552 if (y >= h)
553 break;
554
555 unsigned char* p = pixels + stride * y;
556
557 p[x * 4 + 0] = pen_color[0];
558 p[x * 4 + 1] = pen_color[1];
559 p[x * 4 + 2] = pen_color[2];
560 p[x * 4 + 3] = pen_color[3];
561 }
562 }
563 }
564
draw_rectangle_yuv420sp(unsigned char * yuv420sp,int w,int h,int rx,int ry,int rw,int rh,unsigned int color,int thickness)565 void draw_rectangle_yuv420sp(unsigned char* yuv420sp, int w, int h, int rx, int ry, int rw, int rh, unsigned int color, int thickness)
566 {
567 // assert w % 2 == 0
568 // assert h % 2 == 0
569 // assert rx % 2 == 0
570 // assert ry % 2 == 0
571 // assert rw % 2 == 0
572 // assert rh % 2 == 0
573 // assert thickness % 2 == 0
574
575 const unsigned char* pen_color = (const unsigned char*)&color;
576
577 unsigned int v_y;
578 unsigned int v_uv;
579 unsigned char* pen_color_y = (unsigned char*)&v_y;
580 unsigned char* pen_color_uv = (unsigned char*)&v_uv;
581 pen_color_y[0] = pen_color[0];
582 pen_color_uv[0] = pen_color[1];
583 pen_color_uv[1] = pen_color[2];
584
585 unsigned char* Y = yuv420sp;
586 draw_rectangle_c1(Y, w, h, w, rx, ry, rw, rh, v_y, thickness);
587
588 unsigned char* UV = yuv420sp + w * h;
589 int thickness_uv = thickness == -1 ? thickness : max(thickness / 2, 1);
590 draw_rectangle_c2(UV, w / 2, h / 2, w, rx / 2, ry / 2, rw / 2, rh / 2, v_uv, thickness_uv);
591 }
592
593
draw_image_yuv420sp(unsigned char * yuv420sp,int w,int h,unsigned char * draw_img,int rx,int ry,int rw,int rh)594 void draw_image_yuv420sp(unsigned char* yuv420sp, int w, int h, unsigned char* draw_img, int rx, int ry, int rw, int rh) {
595 for (int i = 0; i < rh; i++) {
596 memcpy(yuv420sp + (ry+i) * w + rx, draw_img + i * rw, rw);
597 }
598 for (int i = 0; i < rh/2; i++) {
599 memcpy(yuv420sp + w*h + (ry/2+i) * w+ rx, draw_img + rw*rh + i*rw, rw);
600 }
601 }