This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit ef4a597ad857213a946c72ee78b391de103ab840
Author:     Niklas Haas <[email protected]>
AuthorDate: Wed Feb 25 16:46:04 2026 +0100
Commit:     Niklas Haas <[email protected]>
CommitDate: Thu Feb 26 13:09:14 2026 +0000

    swscale/ops: allow excluding components from SWS_OP_DITHER
    
    We often need to dither only a subset of the components. Previously this
    was not possible, but we can just use the special value -1 for this.
    
    The main motivating factor is actually the fact that "unnecessary" dither 
ops
    would otherwise frequently prevent plane splitting, since e.g. a copied
    alpha plane has to come along for the ride through the whole F32/dither
    pipeline.
    
    Additionally, it somewhat simplifies implementations.
    
    Signed-off-by: Niklas Haas <[email protected]>
---
 libswscale/format.c        | 4 +++-
 libswscale/ops.c           | 6 ++++--
 libswscale/ops.h           | 2 +-
 libswscale/ops_optimizer.c | 5 +++--
 4 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/libswscale/format.c b/libswscale/format.c
index e0434a2024..d53acdbcdc 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -1229,8 +1229,10 @@ static int fmt_dither(SwsContext *ctx, SwsOpList *ops,
         /* Brute-forced offsets; minimizes quantization error across a 16x16
          * bayer dither pattern for standard RGBA and YUVA pixel formats */
         const int offsets_16x16[4] = {0, 3, 2, 5};
-        for (int i = 0; i < 4; i++)
+        for (int i = 0; i < 4; i++) {
+            av_assert0(offsets_16x16[i] <= INT8_MAX);
             dither.y_offset[i] = offsets_16x16[i];
+        }
 
         if (src.desc->nb_components < 3 && bpc >= 8) {
             /**
diff --git a/libswscale/ops.c b/libswscale/ops.c
index 5f60c6f08e..b709ffef79 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -181,8 +181,10 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4])
         return;
     case SWS_OP_DITHER:
         av_assert1(!ff_sws_pixel_type_is_int(op->type));
-        for (int i = 0; i < 4; i++)
-            x[i] = x[i].den ? av_add_q(x[i], av_make_q(1, 2)) : x[i];
+        for (int i = 0; i < 4; i++) {
+            if (op->dither.y_offset[i] >= 0 && x[i].den)
+                x[i] = av_add_q(x[i], av_make_q(1, 2));
+        }
         return;
     case SWS_OP_MIN:
         for (int i = 0; i < 4; i++)
diff --git a/libswscale/ops.h b/libswscale/ops.h
index 7b79fdc69d..d1576b9325 100644
--- a/libswscale/ops.h
+++ b/libswscale/ops.h
@@ -139,7 +139,7 @@ typedef struct SwsConvertOp {
 typedef struct SwsDitherOp {
     AVRational *matrix; /* tightly packed dither matrix (refstruct) */
     int size_log2; /* size (in bits) of the dither matrix */
-    uint8_t y_offset[4]; /* row offset for each component */
+    int8_t y_offset[4]; /* row offset for each component, or -1 for ignored */
 } SwsDitherOp;
 
 typedef struct SwsLinearOp {
diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
index 45ad3d4490..203dff1ac2 100644
--- a/libswscale/ops_optimizer.c
+++ b/libswscale/ops_optimizer.c
@@ -518,8 +518,9 @@ retry:
 
         case SWS_OP_DITHER:
             for (int i = 0; i < 4; i++) {
-                noop &= (prev->comps.flags[i] & SWS_COMP_EXACT) ||
-                        next->comps.unused[i];
+                if (next->comps.unused[i] || op->dither.y_offset[i] < 0)
+                    continue;
+                noop &= !!(prev->comps.flags[i] & SWS_COMP_EXACT);
             }
 
             if (noop) {

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

Reply via email to