PR #23772 opened by joeha
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23772
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23772.patch

This is a patch for the delogo filter. With this I can create a
circular or elliptic zone to apply the delogo algorithm. The borders are
defined with x,y,w,h parameter just like the rectangular area definition. To
become circular I added an additional parameter 'r'=0/1 defaulting to '0' i.e.
rectangular area definition.

I added a large comment to the function body describing the calculation
of the ellipse. Hope you don't mind.

The patch now includes a description of the 'r' parameter for the html and man
pages.


The patch has been rebased to the current master branch, tested with
'make fate-rsync fate' and applies clean to the master branch


>From 504a940a74627f0fa5c3f51fd631acc560592fd4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Habenicht?= <[email protected]>
Date: Fri, 31 Jan 2025 22:39:37 +0100
Subject: [PATCH 1/4] avfilter/delogo: add parameter to switch on circular
 delogo

Add a parameter (boolean) r to switch the area from
rectangular (r=0) to circular(r=1) delogo.
---
 libavfilter/vf_delogo.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c
index 83f7f66ad5..74c1aca101 100644
--- a/libavfilter/vf_delogo.c
+++ b/libavfilter/vf_delogo.c
@@ -195,7 +195,7 @@ static void apply_delogo(uint8_t *dst, int dst_linesize,
 
 typedef struct DelogoContext {
     const AVClass *class;
-    int x, y, w, h, band, show;
+    int x, y, w, h, band, show, round;
     char *x_expr, *y_expr, *w_expr, *h_expr;
     AVExpr *x_pexpr, *y_pexpr, *w_pexpr, *h_pexpr;
     double var_values[VAR_VARS_NB];
@@ -209,6 +209,7 @@ static const AVOption delogo_options[]= {
     { "y",    "set logo y position",       OFFSET(y_expr),    
AV_OPT_TYPE_STRING, { .str = "-1" }, 0, 0, FLAGS },
     { "w",    "set logo width",            OFFSET(w_expr),    
AV_OPT_TYPE_STRING, { .str = "-1" }, 0, 0, FLAGS },
     { "h",    "set logo height",           OFFSET(h_expr),    
AV_OPT_TYPE_STRING, { .str = "-1" }, 0, 0, FLAGS },
+    { "r",    "logo is round/ellipse",     OFFSET(round),     
AV_OPT_TYPE_BOOL,   { .i64 =  0 },   0, 1, FLAGS },
     { "show", "show delogo area",          OFFSET(show),      
AV_OPT_TYPE_BOOL,   { .i64 =  0 },   0, 1, FLAGS },
     { NULL }
 };
@@ -259,8 +260,8 @@ static av_cold int init(AVFilterContext *ctx)
 
     s->band = 1;
 
-    av_log(ctx, AV_LOG_VERBOSE, "x:%d y:%d, w:%d h:%d band:%d show:%d\n",
-           s->x, s->y, s->w, s->h, s->band, s->show);
+    av_log(ctx, AV_LOG_VERBOSE, "x:%d y:%d, w:%d h:%d band:%d round:%d 
show:%d\n",
+           s->x, s->y, s->w, s->h, s->band, s->round, s->show);
 
     s->w += s->band*2;
     s->h += s->band*2;
-- 
2.52.0


>From 02f73e418ba7fb6a29ca361a55b1967c9993ce1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Habenicht?= <[email protected]>
Date: Mon, 3 Feb 2025 21:21:48 +0100
Subject: [PATCH 2/4] avfilter/delogo: added circular delogo algorithm
 description

Added a description of the elliptic formed delogo algorithm. Placed it
outside the doxygen function comment.
---
 libavfilter/vf_delogo.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c
index 74c1aca101..3e4ac4c82e 100644
--- a/libavfilter/vf_delogo.c
+++ b/libavfilter/vf_delogo.c
@@ -100,6 +100,30 @@ static void apply_delogo(uint8_t *dst, int dst_linesize,
                          int logo_x, int logo_y, int logo_w, int logo_h,
                          unsigned int band, int show, int direct)
 {
+    /* Round area algorithm description:
+     *
+     * logo_x, logo_y, logo_w and logo_h define the boundaries of the
+     * ellipse. In the ellipse formula x^2 / a^2 + y^2 / b^2 = 1 let
+     * a = logo_w/2, b = logo_h/2 and the center of the ellipse
+     * (0,0) = (logo_x + a, logo_y + b).
+     * Let the picture dimensions (px,py,pw,ph) := function API(x,y,w,h).
+     * A point of the picture is transformed into the ellipse coordinates
+     * by using x = px - (logo_x + a), y = py - (logo_y +b).
+     *
+     * A point is inside the ellipse if x^2 / a^2 + y^2 / b^2 <= 1
+     * <=> (x + logo_x)^2 / (logo_w / 2)^2
+     *     + (y + logo_y)^2 / (logo_h / 2)^2 <= 1
+     * <=> (px - logo_x - a + logo_x)^2 / (logo_w / 2)^2
+     *     + (py - logo_y - b + logo_y)^2 / (logo_h / 2)^2 <= 1
+     * <=> (px - a)^2 / (logo_w / 2)^2
+     *     + (py - b)^2 / (logo_h / 2)^2 <= 1
+     * <=> ((px - a) / (logo_w / 2))^2
+     *     + ((py - b) / (logo_h / 2))^2 <= 1
+     *
+     * px is later defined x, py defined y.
+     * logo_w is later defined logo_w2, logo_h defined logo_h2.
+     */
+
     int x, y;
     uint64_t interp, weightl, weightr, weightt, weightb, weight;
     uint8_t *xdst, *xsrc;
-- 
2.52.0


>From f306be64db1ff1c7892312a70417b4aaffee83fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Habenicht?= <[email protected]>
Date: Mon, 3 Feb 2025 21:23:14 +0100
Subject: [PATCH 3/4] avfilter/delogo: added the circular delogo algorithm

Use the corrected x,y,w,h values with boundaries and clipping to
calculate the points inside the ellipse.
---
 libavfilter/vf_delogo.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c
index 3e4ac4c82e..30a9f18b3e 100644
--- a/libavfilter/vf_delogo.c
+++ b/libavfilter/vf_delogo.c
@@ -90,6 +90,7 @@ static int set_expr(AVExpr **pexpr, const char *expr, const 
char *option, void *
  * @param logo_w width of the logo
  * @param logo_h height of the logo
  * @param band   the size of the band around the processed area
+ * @param round  whether delogo is applied to a rectangular or round area
  * @param show   show a rectangle around the processed area, useful for
  *               parameters tweaking
  * @param direct if non-zero perform in-place processing
@@ -98,7 +99,7 @@ static void apply_delogo(uint8_t *dst, int dst_linesize,
                          uint8_t *src, int src_linesize,
                          int w, int h, AVRational sar,
                          int logo_x, int logo_y, int logo_w, int logo_h,
-                         unsigned int band, int show, int direct)
+                         unsigned int band, int round, int show, int direct)
 {
     /* Round area algorithm description:
      *
@@ -132,6 +133,7 @@ static void apply_delogo(uint8_t *dst, int dst_linesize,
     unsigned int left_sample, right_sample;
     int xclipl, xclipr, yclipt, yclipb;
     int logo_x1, logo_x2, logo_y1, logo_y2;
+    double a, b, logo_w2, logo_h2;
 
     xclipl = FFMAX(-logo_x, 0);
     xclipr = FFMAX(logo_x+logo_w-w, 0);
@@ -147,6 +149,13 @@ static void apply_delogo(uint8_t *dst, int dst_linesize,
     topright = src+logo_y1 * src_linesize+logo_x2;
     botleft  = src+logo_y2 * src_linesize+logo_x1;
 
+    if (round) {
+        logo_w2 = (logo_x2 - logo_x1) / 2.0;
+        logo_h2 = (logo_y2 - logo_y1) / 2.0;
+        a = logo_x1 + logo_w2;
+        b = logo_y1 + logo_h2;
+    }
+
     if (!direct)
         av_image_copy_plane(dst, dst_linesize, src, src_linesize, w, h);
 
@@ -171,6 +180,21 @@ static void apply_delogo(uint8_t *dst, int dst_linesize,
                 continue;
             }
 
+            if (round) {
+                double xf, yf;
+                /* Evaluate if x,y is inside the ellipse, else continue
+                 * This is the calculation
+                 *      (px - a)^2 / (logo_w / 2)^2 +
+                 *      (py - b)^2 / (logo_h / 2)^2 <= 1
+                 */
+                xf = ((double)x - a) / logo_w2;
+                xf *= xf;
+                yf = ((double)y - b) / logo_h2;
+                yf *= yf;
+                if (xf + yf > 1.0)
+                    continue;
+            }
+
             /* Weighted interpolation based on relative distances, taking SAR 
into account */
             weightl = (uint64_t)              (logo_x2-x) * (y-logo_y1) * 
(logo_y2-y) * sar.den;
             weightr = (uint64_t)(x-logo_x1)               * (y-logo_y1) * 
(logo_y2-y) * sar.den;
@@ -390,7 +414,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
                      AV_CEIL_RSHIFT(s->w + (s->x & ((1<<hsub)-1)), hsub),
                      AV_CEIL_RSHIFT(s->h + (s->y & ((1<<vsub)-1)), vsub),
                      s->band>>FFMIN(hsub, vsub),
-                     s->show, direct);
+                     s->round, s->show, direct);
     }
 
     if (!direct)
-- 
2.52.0


>From 23a325c611d3368c35ea9220bd1731563035b31c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Habenicht?= <[email protected]>
Date: Fri, 10 Jul 2026 21:21:13 +0200
Subject: [PATCH 4/4] avfilter/delogo: update the documentation source file

added a description of the parameter 'r' to the documentation source files
including an example
---
 doc/filters.texi | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 34219890d4..4661391e35 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -11794,7 +11794,7 @@ The default is @samp{4}.
 @section delogo
 
 Suppress a TV station logo by a simple interpolation of the surrounding
-pixels. Just set a rectangle covering the logo and watch it disappear
+pixels. Just set a rectangle or circle covering the logo and watch it disappear
 (and sometimes something even uglier appear - your mileage may vary).
 
 It accepts the following parameters:
@@ -11815,7 +11815,12 @@ When set to 1, a green rectangle is drawn on the 
screen to simplify
 finding the right @var{x}, @var{y}, @var{w}, and @var{h} parameters.
 The default value is 0.
 
-The rectangle is drawn on the outermost pixels which will be (partly)
+@item r
+Specify whether the mask got an elliptic or a rectangular shape. When set
+to 1 the mask is set to an elliptic shape, setting to 0 sets a rectangular
+shape. The default value is 0.
+
+The rectangle (or ellipse) is drawn on the outermost pixels which will be 
(partly)
 replaced with interpolated values. The values of the next pixels
 immediately outside this rectangle in each direction will be used to
 compute the interpolated pixel values inside the rectangle.
@@ -11832,6 +11837,12 @@ and size 100x77:
 delogo=x=0:y=0:w=100:h=77
 @end example
 
+@item
+Set a circle with a radius of 10 and the center to 10,10:
+@example
+delogo=x=0:y=0:w=20:h=20
+@end example
+
 @end itemize
 
 @anchor{derain}
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to