History

avfilter/vf_convolution: add column/vertical mode

Paul B Mahol committed 8 years ago

Commit aba39cc1 parent 901dc112 files · +144 −47Browse files

Unified · Split

2 files
  1. doc/filters.texi +2 −2
  2. libavfilter/vf_convolution.c +142 −45
doc/filters.texi+2−2
@@ -6416,7 +6416,7 @@ colorspace=smpte240m · 6415 unmodified lines
6416 6416
6417@section convolution6417@section convolution
6418 6418
6419Apply convolution of 3x3, 5x5, 7x7 or horizontal up to 49 elements.6419Apply convolution of 3x3, 5x5, 7x7 or horizontal/vertical up to 49 elements.
6420 6420
6421The filter accepts the following options:6421The filter accepts the following options:
6422 6422
@@ -6447,7 +6447,7 @@ Useful for making the overall image brighter or darker. Default is 0.0. · 24 unmodified lines
6447@item 1mode6447@item 1mode
6448@item 2mode6448@item 2mode
6449@item 3mode6449@item 3mode
6450Set matrix mode for each plane. Can be @var{square} or @var{row}.6450Set matrix mode for each plane. Can be @var{square}, @var{row} or @var{column}.
6451Default is @var{square}.6451Default is @var{square}.
6452@end table6452@end table
6453 6453
libavfilter/vf_convolution.c+142−45
@@ -32,6 +32,7 @@ · 31 unmodified lines
32enum MatrixMode {32enum MatrixMode {
33 MATRIX_SQUARE,33 MATRIX_SQUARE,
34 MATRIX_ROW,34 MATRIX_ROW,
35 MATRIX_COLUMN,
35 MATRIX_NBMODES,36 MATRIX_NBMODES,
36};37};
37 38
@@ -60,9 +61,10 @@ typedef struct ConvolutionContext { · 22 unmodified lines
60 61
61 void (*setup[4])(int radius, const uint8_t *c[], const uint8_t *src, int stride,62 void (*setup[4])(int radius, const uint8_t *c[], const uint8_t *src, int stride,
62 int x, int width, int y, int height, int bpc);63 int x, int width, int y, int height, int bpc);
63 void (*filter[4])(uint8_t *dst, const uint8_t *src, int width,64 void (*filter[4])(uint8_t *dst, int width,
64 float rdiv, float bias, const int *const matrix,65 float rdiv, float bias, const int *const matrix,
65 const uint8_t *c[], int peak, int radius);66 const uint8_t *c[], int peak, int radius,
67 int dstride, int stride);
66} ConvolutionContext;68} ConvolutionContext;
67 69
68#define OFFSET(x) offsetof(ConvolutionContext, x)70#define OFFSET(x) offsetof(ConvolutionContext, x)
@@ -87,6 +89,7 @@ static const AVOption convolution_options[] = { · 18 unmodified lines
87 { "3mode", "set matrix mode for 4th plane", OFFSET(mode[3]), AV_OPT_TYPE_INT, {.i64=MATRIX_SQUARE}, 0, MATRIX_NBMODES-1, FLAGS, "mode" },89 { "3mode", "set matrix mode for 4th plane", OFFSET(mode[3]), AV_OPT_TYPE_INT, {.i64=MATRIX_SQUARE}, 0, MATRIX_NBMODES-1, FLAGS, "mode" },
88 { "square", "square matrix", 0, AV_OPT_TYPE_CONST, {.i64=MATRIX_SQUARE}, 0, 0, FLAGS, "mode" },90 { "square", "square matrix", 0, AV_OPT_TYPE_CONST, {.i64=MATRIX_SQUARE}, 0, 0, FLAGS, "mode" },
89 { "row", "single row matrix", 0, AV_OPT_TYPE_CONST, {.i64=MATRIX_ROW} , 0, 0, FLAGS, "mode" },91 { "row", "single row matrix", 0, AV_OPT_TYPE_CONST, {.i64=MATRIX_ROW} , 0, 0, FLAGS, "mode" },
92 { "column", "single column matrix", 0, AV_OPT_TYPE_CONST, {.i64=MATRIX_COLUMN}, 0, 0, FLAGS, "mode" },
90 { NULL }93 { NULL }
91};94};
92 95
@@ -140,9 +143,10 @@ typedef struct ThreadData { · 47 unmodified lines
140 AVFrame *in, *out;143 AVFrame *in, *out;
141} ThreadData;144} ThreadData;
142 145
143static void filter16_prewitt(uint8_t *dstp, const uint8_t *src, int width,146static void filter16_prewitt(uint8_t *dstp, int width,
144 float scale, float delta, const int *const matrix,147 float scale, float delta, const int *const matrix,
145 const uint8_t *c[], int peak, int radius)148 const uint8_t *c[], int peak, int radius,
149 int dstride, int stride)
146{150{
147 uint16_t *dst = (uint16_t *)dstp;151 uint16_t *dst = (uint16_t *)dstp;
148 int x;152 int x;
@@ -157,9 +161,10 @@ static void filter16_prewitt(uint8_t *dstp, const uint8_t *src, int width, · 8 unmodified lines
157 }161 }
158}162}
159 163
160static void filter16_roberts(uint8_t *dstp, const uint8_t *src, int width,164static void filter16_roberts(uint8_t *dstp, int width,
161 float scale, float delta, const int *const matrix,165 float scale, float delta, const int *const matrix,
162 const uint8_t *c[], int peak, int radius)166 const uint8_t *c[], int peak, int radius,
167 int dstride, int stride)
163{168{
164 uint16_t *dst = (uint16_t *)dstp;169 uint16_t *dst = (uint16_t *)dstp;
165 int x;170 int x;
@@ -172,9 +177,10 @@ static void filter16_roberts(uint8_t *dstp, const uint8_t *src, int width, · 6 unmodified lines
172 }177 }
173}178}
174 179
175static void filter16_sobel(uint8_t *dstp, const uint8_t *src, int width,180static void filter16_sobel(uint8_t *dstp, int width,
176 float scale, float delta, const int *const matrix,181 float scale, float delta, const int *const matrix,
177 const uint8_t *c[], int peak, int radius)182 const uint8_t *c[], int peak, int radius,
183 int dstride, int stride)
178{184{
179 uint16_t *dst = (uint16_t *)dstp;185 uint16_t *dst = (uint16_t *)dstp;
180 int x;186 int x;
@@ -189,9 +195,10 @@ static void filter16_sobel(uint8_t *dstp, const uint8_t *src, int width, · 8 unmodified lines
189 }195 }
190}196}
191 197
192static void filter_prewitt(uint8_t *dst, const uint8_t *src, int width,198static void filter_prewitt(uint8_t *dst, int width,
193 float scale, float delta, const int *const matrix,199 float scale, float delta, const int *const matrix,
194 const uint8_t *c[], int peak, int radius)200 const uint8_t *c[], int peak, int radius,
201 int dstride, int stride)
195{202{
196 const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];203 const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
197 const uint8_t *c3 = c[3], *c5 = c[5];204 const uint8_t *c3 = c[3], *c5 = c[5];
@@ -208,9 +215,10 @@ static void filter_prewitt(uint8_t *dst, const uint8_t *src, int width, · 10 unmodified lines
208 }215 }
209}216}
210 217
211static void filter_roberts(uint8_t *dst, const uint8_t *src, int width,218static void filter_roberts(uint8_t *dst, int width,
212 float scale, float delta, const int *const matrix,219 float scale, float delta, const int *const matrix,
213 const uint8_t *c[], int peak, int radius)220 const uint8_t *c[], int peak, int radius,
221 int dstride, int stride)
214{222{
215 int x;223 int x;
216 224
@@ -222,9 +230,10 @@ static void filter_roberts(uint8_t *dst, const uint8_t *src, int width, · 5 unmodified lines
222 }230 }
223}231}
224 232
225static void filter_sobel(uint8_t *dst, const uint8_t *src, int width,233static void filter_sobel(uint8_t *dst, int width,
226 float scale, float delta, const int *const matrix,234 float scale, float delta, const int *const matrix,
227 const uint8_t *c[], int peak, int radius)235 const uint8_t *c[], int peak, int radius,
236 int dstride, int stride)
228{237{
229 const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];238 const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
230 const uint8_t *c3 = c[3], *c5 = c[5];239 const uint8_t *c3 = c[3], *c5 = c[5];
@@ -241,9 +250,10 @@ static void filter_sobel(uint8_t *dst, const uint8_t *src, int width, · 10 unmodified lines
241 }250 }
242}251}
243 252
244static void filter16_3x3(uint8_t *dstp, const uint8_t *src, int width,253static void filter16_3x3(uint8_t *dstp, int width,
245 float rdiv, float bias, const int *const matrix,254 float rdiv, float bias, const int *const matrix,
246 const uint8_t *c[], int peak, int radius)255 const uint8_t *c[], int peak, int radius,
256 int dstride, int stride)
247{257{
248 uint16_t *dst = (uint16_t *)dstp;258 uint16_t *dst = (uint16_t *)dstp;
249 int x;259 int x;
@@ -263,9 +273,10 @@ static void filter16_3x3(uint8_t *dstp, const uint8_t *src, int width, · 13 unmodified lines
263 }273 }
264}274}
265 275
266static void filter16_5x5(uint8_t *dstp, const uint8_t *src, int width,276static void filter16_5x5(uint8_t *dstp, int width,
267 float rdiv, float bias, const int *const matrix,277 float rdiv, float bias, const int *const matrix,
268 const uint8_t *c[], int peak, int radius)278 const uint8_t *c[], int peak, int radius,
279 int dstride, int stride)
269{280{
270 uint16_t *dst = (uint16_t *)dstp;281 uint16_t *dst = (uint16_t *)dstp;
271 int x;282 int x;
@@ -281,9 +292,10 @@ static void filter16_5x5(uint8_t *dstp, const uint8_t *src, int width, · 9 unmodified lines
281 }292 }
282}293}
283 294
284static void filter16_7x7(uint8_t *dstp, const uint8_t *src, int width,295static void filter16_7x7(uint8_t *dstp, int width,
285 float rdiv, float bias, const int *const matrix,296 float rdiv, float bias, const int *const matrix,
286 const uint8_t *c[], int peak, int radius)297 const uint8_t *c[], int peak, int radius,
298 int dstride, int stride)
287{299{
288 uint16_t *dst = (uint16_t *)dstp;300 uint16_t *dst = (uint16_t *)dstp;
289 int x;301 int x;
@@ -299,9 +311,10 @@ static void filter16_7x7(uint8_t *dstp, const uint8_t *src, int width, · 9 unmodified lines
299 }311 }
300}312}
301 313
302static void filter16_row(uint8_t *dstp, const uint8_t *src, int width,314static void filter16_row(uint8_t *dstp, int width,
303 float rdiv, float bias, const int *const matrix,315 float rdiv, float bias, const int *const matrix,
304 const uint8_t *c[], int peak, int radius)316 const uint8_t *c[], int peak, int radius,
317 int dstride, int stride)
305{318{
306 uint16_t *dst = (uint16_t *)dstp;319 uint16_t *dst = (uint16_t *)dstp;
307 int x;320 int x;
@@ -317,9 +330,30 @@ static void filter16_row(uint8_t *dstp, const uint8_t *src, int width, · 9 unmodified lines
317 }330 }
318}331}
319 332
320static void filter_7x7(uint8_t *dst, const uint8_t *src, int width,333static void filter16_column(uint8_t *dstp, int height,
334 float rdiv, float bias, const int *const matrix,
335 const uint8_t *c[], int peak, int radius,
336 int dstride, int stride)
337{
338 uint16_t *dst = (uint16_t *)dstp;
339 int y;
340
341 for (y = 0; y < height; y++) {
342 int i, sum = 0;
343
344 for (i = 0; i < 2 * radius + 1; i++)
345 sum += AV_RN16A(&c[i][0 + y * stride]) * matrix[i];
346
347 sum = (int)(sum * rdiv + bias + 0.5f);
348 dst[0] = av_clip(sum, 0, peak);
349 dst += dstride / 2;
350 }
351}
352
353static void filter_7x7(uint8_t *dst, int width,
321 float rdiv, float bias, const int *const matrix,354 float rdiv, float bias, const int *const matrix,
322 const uint8_t *c[], int peak, int radius)355 const uint8_t *c[], int peak, int radius,
356 int dstride, int stride)
323{357{
324 int x;358 int x;
325 359
@@ -334,9 +368,10 @@ static void filter_7x7(uint8_t *dst, const uint8_t *src, int width, · 8 unmodified lines
334 }368 }
335}369}
336 370
337static void filter_5x5(uint8_t *dst, const uint8_t *src, int width,371static void filter_5x5(uint8_t *dst, int width,
338 float rdiv, float bias, const int *const matrix,372 float rdiv, float bias, const int *const matrix,
339 const uint8_t *c[], int peak, int radius)373 const uint8_t *c[], int peak, int radius,
374 int dstride, int stride)
340{375{
341 int x;376 int x;
342 377
@@ -351,9 +386,10 @@ static void filter_5x5(uint8_t *dst, const uint8_t *src, int width, · 8 unmodified lines
351 }386 }
352}387}
353 388
354static void filter_3x3(uint8_t *dst, const uint8_t *src, int width,389static void filter_3x3(uint8_t *dst, int width,
355 float rdiv, float bias, const int *const matrix,390 float rdiv, float bias, const int *const matrix,
356 const uint8_t *c[], int peak, int radius)391 const uint8_t *c[], int peak, int radius,
392 int dstride, int stride)
357{393{
358 const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];394 const uint8_t *c0 = c[0], *c1 = c[1], *c2 = c[2];
359 const uint8_t *c3 = c[3], *c4 = c[4], *c5 = c[5];395 const uint8_t *c3 = c[3], *c4 = c[4], *c5 = c[5];
@@ -369,9 +405,10 @@ static void filter_3x3(uint8_t *dst, const uint8_t *src, int width, · 9 unmodified lines
369 }405 }
370}406}
371 407
372static void filter_row(uint8_t *dst, const uint8_t *src, int width,408static void filter_row(uint8_t *dst, int width,
373 float rdiv, float bias, const int *const matrix,409 float rdiv, float bias, const int *const matrix,
374 const uint8_t *c[], int peak, int radius)410 const uint8_t *c[], int peak, int radius,
411 int dstride, int stride)
375{412{
376 int x;413 int x;
377 414
@@ -386,6 +423,25 @@ static void filter_row(uint8_t *dst, const uint8_t *src, int width, · 8 unmodified lines
386 }423 }
387}424}
388 425
426static void filter_column(uint8_t *dst, int height,
427 float rdiv, float bias, const int *const matrix,
428 const uint8_t *c[], int peak, int radius,
429 int dstride, int stride)
430{
431 int y;
432
433 for (y = 0; y < height; y++) {
434 int i, sum = 0;
435
436 for (i = 0; i < 2 * radius + 1; i++)
437 sum += c[i][0 + y * stride] * matrix[i];
438
439 sum = (int)(sum * rdiv + bias + 0.5f);
440 dst[0] = av_clip_uint8(sum);
441 dst += dstride;
442 }
443}
444
389static void setup_3x3(int radius, const uint8_t *c[], const uint8_t *src, int stride,445static void setup_3x3(int radius, const uint8_t *c[], const uint8_t *src, int stride,
390 int x, int w, int y, int h, int bpc)446 int x, int w, int y, int h, int bpc)
391{447{
@@ -448,6 +504,20 @@ static void setup_row(int radius, const uint8_t *c[], const uint8_t *src, int st · 56 unmodified lines
448 }504 }
449}505}
450 506
507static void setup_column(int radius, const uint8_t *c[], const uint8_t *src, int stride,
508 int x, int w, int y, int h, int bpc)
509{
510 int i;
511
512 for (i = 0; i < radius * 2 + 1; i++) {
513 int xoff = FFABS(x + i - radius);
514
515 xoff = xoff >= h ? 2 * h - 1 - xoff : xoff;
516
517 c[i] = src + y * bpc + xoff * stride;
518 }
519}
520
451static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)521static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
452{522{
453 ConvolutionContext *s = ctx->priv;523 ConvolutionContext *s = ctx->priv;
@@ -457,43 +527,64 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) · 3 unmodified lines
457 int plane;527 int plane;
458 528
459 for (plane = 0; plane < s->nb_planes; plane++) {529 for (plane = 0; plane < s->nb_planes; plane++) {
530 const int mode = s->mode[plane];
531 const int bpc = s->bpc;
460 const int radius = s->size[plane] / 2;532 const int radius = s->size[plane] / 2;
461 const int height = s->planeheight[plane];533 const int height = s->planeheight[plane];
462 const int width = s->planewidth[plane];534 const int width = s->planewidth[plane];
463 const int stride = in->linesize[plane];535 const int stride = in->linesize[plane];
464 const int dstride = out->linesize[plane];536 const int dstride = out->linesize[plane];
465 const int slice_start = (height * jobnr) / nb_jobs;537 const int sizeh = mode == MATRIX_COLUMN ? width : height;
466 const int slice_end = (height * (jobnr+1)) / nb_jobs;538 const int sizew = mode == MATRIX_COLUMN ? height : width;
539 const int slice_start = (sizeh * jobnr) / nb_jobs;
540 const int slice_end = (sizeh * (jobnr+1)) / nb_jobs;
467 const float rdiv = s->rdiv[plane];541 const float rdiv = s->rdiv[plane];
468 const float bias = s->bias[plane];542 const float bias = s->bias[plane];
469 const uint8_t *src = in->data[plane];543 const uint8_t *src = in->data[plane];
470 uint8_t *dst = out->data[plane] + slice_start * out->linesize[plane];544 const int dst_pos = slice_start * (mode == MATRIX_COLUMN ? bpc : out->linesize[plane]);
545 uint8_t *dst = out->data[plane] + dst_pos;
471 const int *matrix = s->matrix[plane];546 const int *matrix = s->matrix[plane];
472 const int bpc = s->bpc;
473 const uint8_t *c[49];547 const uint8_t *c[49];
474 int y, x;548 int y, x;
475 549
476 if (s->copy[plane]) {550 if (s->copy[plane]) {
477 av_image_copy_plane(dst, dstride, src + slice_start * stride, stride,551 if (mode == MATRIX_COLUMN)
478 width * bpc, slice_end - slice_start);552 av_image_copy_plane(dst, dstride, src + slice_start * bpc, stride,
553 (slice_end - slice_start) * bpc, height);
554 else
555 av_image_copy_plane(dst, dstride, src + slice_start * stride, stride,
556 width * bpc, slice_end - slice_start);
479 continue;557 continue;
480 }558 }
481 559
482 for (y = slice_start; y < slice_end; y++) {560 for (y = slice_start; y < slice_end; y++) {
561 const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : radius * bpc;
562 const int yoff = mode == MATRIX_COLUMN ? radius * stride : 0;
563
483 for (x = 0; x < radius; x++) {564 for (x = 0; x < radius; x++) {
565 const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
566 const int yoff = mode == MATRIX_COLUMN ? x * stride : 0;
567
484 s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);568 s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
485 s->filter[plane](dst + x * bpc, src, 1, rdiv,569 s->filter[plane](dst + yoff + xoff, 1, rdiv,
486 bias, matrix, c, s->max, radius);570 bias, matrix, c, s->max, radius,
571 dstride, stride);
487 }572 }
488 s->setup[plane](radius, c, src, stride, radius, width, y, height, bpc);573 s->setup[plane](radius, c, src, stride, radius, width, y, height, bpc);
489 s->filter[plane](dst + radius * bpc, src, width - 2 * radius,574 s->filter[plane](dst + yoff + xoff, sizew - 2 * radius,
490 rdiv, bias, matrix, c, s->max, radius);575 rdiv, bias, matrix, c, s->max, radius,
491 for (x = width - radius; x < width; x++) {576 dstride, stride);
577 for (x = sizew - radius; x < sizew; x++) {
578 const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
579 const int yoff = mode == MATRIX_COLUMN ? x * stride : 0;
580
492 s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);581 s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
493 s->filter[plane](dst + x * bpc, src, 1, rdiv,582 s->filter[plane](dst + yoff + xoff, 1, rdiv,
494 bias, matrix, c, s->max, radius);583 bias, matrix, c, s->max, radius,
584 dstride, stride);
495 }585 }
496 dst += dstride;586 if (mode != MATRIX_COLUMN)
587 dst += dstride;
497 }588 }
498 }589 }
499 590
@@ -524,6 +615,8 @@ static int config_input(AVFilterLink *inlink) · 24 unmodified lines
524 for (p = 0; p < s->nb_planes; p++) {615 for (p = 0; p < s->nb_planes; p++) {
525 if (s->mode[p] == MATRIX_ROW)616 if (s->mode[p] == MATRIX_ROW)
526 s->filter[p] = filter16_row;617 s->filter[p] = filter16_row;
618 else if (s->mode[p] == MATRIX_COLUMN)
619 s->filter[p] = filter16_column;
527 else if (s->size[p] == 3)620 else if (s->size[p] == 3)
528 s->filter[p] = filter16_3x3;621 s->filter[p] = filter16_3x3;
529 else if (s->size[p] == 5)622 else if (s->size[p] == 5)
@@ -566,7 +659,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) · 36 unmodified lines
566 659
567 td.in = in;660 td.in = in;
568 td.out = out;661 td.out = out;
569 ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(s->planeheight[1], s->nb_threads));662 ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN3(s->planeheight[1], s->planewidth[1], s->nb_threads));
570 663
571 av_frame_free(&in);664 av_frame_free(&in);
572 return ff_filter_frame(outlink, out);665 return ff_filter_frame(outlink, out);
@@ -602,6 +695,10 @@ static av_cold int init(AVFilterContext *ctx) · 29 unmodified lines
602 s->filter[i] = filter_row;695 s->filter[i] = filter_row;
603 s->setup[i] = setup_row;696 s->setup[i] = setup_row;
604 s->size[i] = s->matrix_length[i];697 s->size[i] = s->matrix_length[i];
698 } else if (s->mode[i] == MATRIX_COLUMN) {
699 s->filter[i] = filter_column;
700 s->setup[i] = setup_column;
701 s->size[i] = s->matrix_length[i];
605 } else if (s->matrix_length[i] == 9) {702 } else if (s->matrix_length[i] == 9) {
606 s->size[i] = 3;703 s->size[i] = 3;
607 if (!memcmp(matrix, same3x3, sizeof(same3x3)))704 if (!memcmp(matrix, same3x3, sizeof(same3x3)))

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t