| @@ -39,6 +39,7 @@ enum MorphModes { · 38 unmodified lines |
| 39 | 39 | DILATE, |
| 40 | 40 | OPEN, |
| 41 | 41 | CLOSE, |
| 42 | + GRADIENT, |
| 42 | 43 | NB_MODES |
| 43 | 44 | }; |
| 44 | 45 | |
| @@ -53,6 +54,7 @@ typedef struct IPlane { · 8 unmodified lines |
| 53 | 54 | void (*min_out_place)(uint8_t *c, const uint8_t *a, const uint8_t *b, int x); |
| 54 | 55 | void (*max_in_place)(uint8_t *a, const uint8_t *b, int x); |
| 55 | 56 | void (*min_in_place)(uint8_t *a, const uint8_t *b, int x); |
| 57 | + void (*diff_in_place)(uint8_t *a, const uint8_t *b, int x); |
| 56 | 58 | } IPlane; |
| 57 | 59 | |
| 58 | 60 | typedef struct LUT { |
| @@ -124,6 +126,7 @@ static const AVOption morpho_options[] = { · 65 unmodified lines |
| 124 | 126 | { "dilate", NULL, 0, AV_OPT_TYPE_CONST, {.i64=DILATE}, 0, 0, FLAGS, "mode" }, |
| 125 | 127 | { "open", NULL, 0, AV_OPT_TYPE_CONST, {.i64=OPEN}, 0, 0, FLAGS, "mode" }, |
| 126 | 128 | { "close", NULL, 0, AV_OPT_TYPE_CONST, {.i64=CLOSE}, 0, 0, FLAGS, "mode" }, |
| 129 | + { "gradient",NULL, 0, AV_OPT_TYPE_CONST, {.i64=GRADIENT},0, 0, FLAGS, "mode" }, |
| 127 | 130 | { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, FLAGS }, |
| 128 | 131 | { "structure", "when to process structures", OFFSET(structures), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "str" }, |
| 129 | 132 | { "first", "process only first structure, ignore rest", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "str" }, |
| @@ -184,6 +187,12 @@ static void maxinplace_fun(uint8_t *a, const uint8_t *b, int x) · 54 unmodified lines |
| 184 | 187 | a[i] = FFMAX(a[i], b[i]); |
| 185 | 188 | } |
| 186 | 189 | |
| 190 | +static void diffinplace_fun(uint8_t *a, const uint8_t *b, int x) |
| 191 | +{ |
| 192 | + for (int i = 0; i < x; i++) |
| 193 | + a[i] -= b[i]; |
| 194 | +} |
| 195 | + |
| 187 | 196 | static void min16_fun(uint8_t *cc, const uint8_t *aa, const uint8_t *bb, int x) |
| 188 | 197 | { |
| 189 | 198 | const uint16_t *a = (const uint16_t *)aa; |
| @@ -203,6 +212,15 @@ static void mininplace16_fun(uint8_t *aa, const uint8_t *bb, int x) · 13 unmodified lines |
| 203 | 212 | a[i] = FFMIN(a[i], b[i]); |
| 204 | 213 | } |
| 205 | 214 | |
| 215 | +static void diffinplace16_fun(uint8_t *aa, const uint8_t *bb, int x) |
| 216 | +{ |
| 217 | + uint16_t *a = (uint16_t *)aa; |
| 218 | + const uint16_t *b = (const uint16_t *)bb; |
| 219 | + |
| 220 | + for (int i = 0; i < x; i++) |
| 221 | + a[i] -= b[i]; |
| 222 | +} |
| 223 | + |
| 206 | 224 | static void max16_fun(uint8_t *cc, const uint8_t *aa, const uint8_t *bb, int x) |
| 207 | 225 | { |
| 208 | 226 | const uint16_t *a = (const uint16_t *)aa; |
| @@ -453,6 +471,12 @@ static int erode(IPlane *g, IPlane *f, chord_set *SE, LUT *Ty) · 244 unmodified lines |
| 453 | 471 | return 0; |
| 454 | 472 | } |
| 455 | 473 | |
| 474 | +static void gradient(IPlane *g, IPlane *f) |
| 475 | +{ |
| 476 | + for (int y = 0; y < f->h; y++) |
| 477 | + f->diff_in_place(g->img[y], f->img[y], f->w); |
| 478 | +} |
| 479 | + |
| 456 | 480 | static int insert_chord_set(chord_set *chords, chord c) |
| 457 | 481 | { |
| 458 | 482 | // Checking if chord fits in dynamic array, resize if not. |
| @@ -689,6 +713,7 @@ static int read_iplane(IPlane *imp, const uint8_t *dst, int dst_linesize, · 230 unmodified lines |
| 689 | 713 | imp->min_out_place = type_size == 1 ? min_fun : min16_fun; |
| 690 | 714 | imp->max_in_place = type_size == 1 ? maxinplace_fun : maxinplace16_fun; |
| 691 | 715 | imp->min_in_place = type_size == 1 ? mininplace_fun : mininplace16_fun; |
| 716 | + imp->diff_in_place = type_size == 1 ? diffinplace_fun : diffinplace16_fun; |
| 692 | 717 | |
| 693 | 718 | for (int y = 0; y < h; y++) |
| 694 | 719 | imp->img[y] = (uint8_t *)dst + y * dst_linesize; |
| @@ -832,6 +857,18 @@ copy: · 137 unmodified lines |
| 832 | 857 | break; |
| 833 | 858 | ret = erode(&s->g[p], &s->h[p], &s->SE[p], &s->Ty[1][p]); |
| 834 | 859 | break; |
| 860 | + case GRADIENT: |
| 861 | + ret = read_iplane(&s->h[p], s->temp->data[p], s->temp->linesize[p], width, height, 1, type_size, depth); |
| 862 | + if (ret < 0) |
| 863 | + break; |
| 864 | + ret = dilate(&s->g[p], &s->f[p], &s->SE[p], &s->Ty[0][p]); |
| 865 | + if (ret < 0) |
| 866 | + break; |
| 867 | + ret = erode(&s->h[p], &s->f[p], &s->SE[p], &s->Ty[1][p]); |
| 868 | + if (ret < 0) |
| 869 | + return ret; |
| 870 | + gradient(&s->g[p], &s->h[p]); |
| 871 | + break; |
| 835 | 872 | default: |
| 836 | 873 | av_assert0(0); |
| 837 | 874 | } |