From patchwork Wed Jan 27 17:52:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 25224 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 7BDE944A67C for ; Wed, 27 Jan 2021 19:52:30 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 53FBB68A0F1; Wed, 27 Jan 2021 19:52:30 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1616B6806FE for ; Wed, 27 Jan 2021 19:52:24 +0200 (EET) Received: by mail-ej1-f41.google.com with SMTP id kg20so3913304ejc.4 for ; Wed, 27 Jan 2021 09:52:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=QOaVMPi2W9x3AZ6paBwDWKYBym5PFNsgqhMGCRxTi1o=; b=ZNwFk+k1jP7zc5Qlni95tRBYQAFvRxNq47IWsotCdMaffc43S+4ksswl5/efdSodqO QhQ3MfHJ09kp6XYfhdNvkkjOuRnN958/8in5KET1YT+RFXkUF5n+9bu9YOf0kJORBOjT JWVowSDdP8rr60EHeAcKHfAyhdmdnEp7weV+gEIhehm/mB/zK4Ee91CAxYwYjQDLQZoE ix8MJSQqXUGye6kEw/Be/en7xR7LjTg+fnXn2xKH+y96SqmWHkEy+yZJuwOds0yU9Oc6 g5WvaW7YNyIG0ozhtBvBlAjWpyDVjMV6Lsm8GA5MF6nflWdV0ExIm1rQJYD/X40ZgBoH 5cdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=QOaVMPi2W9x3AZ6paBwDWKYBym5PFNsgqhMGCRxTi1o=; b=bhMDYf1MDY5LgxLsAtHiWQuBxSLekttP8XPggOnHhY0YhXsIGXNSlf2ndJFnDWBqC0 h+9ST+kgPd4XYuBoyU77c6dNde3MYDd0HIh2mWTjKVZGpge02ku8dSABfDXNy1xp+AT2 KlL1ZrH5GkdYUyiwkTJL384Gjwny72OuHnNimPaLGnSvVTwAZtgxjAuydLpkmVG6U1E8 dzV042aRDIqQMMTNSaFJuYGZGJAtSOhCpBCjUS61pD05MBsgMF8F+oY116T+ISfvzr39 zUFlFtTFxnXad06jS0SgbkcUPFL5CG3eWPjqeq+ivvdQ51/leR64XHSVwvOGYmj/h/g9 +dig== X-Gm-Message-State: AOAM533ikGEtzoG7AIwNLWffuqK2oNKhIxbXPEp09Y7b+Norb1uPUHUD i+Rq9xWmqy4HhR4wFk+DcvSP4gDtzdOsZQ== X-Google-Smtp-Source: ABdhPJygnzkWwO7E5RayLcBDRucGrsncT92wajErlBhOuobf3ZcBkZ9PvPGCreVZKuwCEj6wcaR4ZA== X-Received: by 2002:a17:906:b09a:: with SMTP id x26mr7871903ejy.199.1611769943555; Wed, 27 Jan 2021 09:52:23 -0800 (PST) Received: from localhost.localdomain ([31.45.254.141]) by smtp.gmail.com with ESMTPSA id q22sm1180508ejx.3.2021.01.27.09.52.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Jan 2021 09:52:22 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Wed, 27 Jan 2021 18:52:11 +0100 Message-Id: <20210127175212.17869-1-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH 1/2] avfilter/vf_lut3d: add pyramid interpolation X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- doc/filters.texi | 2 ++ libavfilter/vf_lut3d.c | 62 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index fb9995eddf..a38f9b4124 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -13866,6 +13866,8 @@ Use values from the nearest defined point. Interpolate values using the 8 points defining a cube. @item tetrahedral Interpolate values using a tetrahedron. +@item pyramid +Interpolate values using a pyramid. @end table @end table diff --git a/libavfilter/vf_lut3d.c b/libavfilter/vf_lut3d.c index 172d6df0c8..12eb15fe67 100644 --- a/libavfilter/vf_lut3d.c +++ b/libavfilter/vf_lut3d.c @@ -49,6 +49,7 @@ enum interp_mode { INTERPOLATE_NEAREST, INTERPOLATE_TRILINEAR, INTERPOLATE_TETRAHEDRAL, + INTERPOLATE_PYRAMID, NB_INTERP_MODE }; @@ -103,6 +104,7 @@ typedef struct ThreadData { { "nearest", "use values from the nearest defined points", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_NEAREST}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ { "trilinear", "interpolate values using the 8 points defining a cube", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TRILINEAR}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ { "tetrahedral", "interpolate values using a tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ + { "pyramid", "interpolate values using a pyramid", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PYRAMID}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ { NULL } #define EXPONENT_MASK 0x7F800000 @@ -185,6 +187,56 @@ static inline struct rgbvec interp_trilinear(const LUT3DContext *lut3d, return c; } +static inline struct rgbvec interp_pyramid(const LUT3DContext *lut3d, + const struct rgbvec *s) +{ + const int lutsize2 = lut3d->lutsize2; + const int lutsize = lut3d->lutsize; + const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)}; + const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)}; + const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]}; + const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]]; + struct rgbvec c; + + if (d.g > d.r && d.b > d.r) { + const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]]; + + c.r = c000.r + (c111.r - c011.r) * d.r + (c010.r - c000.r) * d.g + (c001.r - c000.r) * d.b + + (c011.r - c001.r - c010.r + c000.r) * d.g * d.b; + c.g = c000.g + (c111.g - c011.g) * d.r + (c010.g - c000.g) * d.g + (c001.g - c000.g) * d.b + + (c011.g - c001.g - c010.g + c000.g) * d.g * d.b; + c.b = c000.b + (c111.b - c011.b) * d.r + (c010.b - c000.b) * d.g + (c001.b - c000.b) * d.b + + (c011.b - c001.b - c010.b + c000.b) * d.g * d.b; + } else if (d.r > d.g && d.b > d.g) { + const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]]; + + c.r = c000.r + (c100.r - c000.r) * d.r + (c111.r - c101.r) * d.g + (c001.r - c000.r) * d.b + + (c101.r - c001.r - c100.r + c000.r) * d.r * d.b; + c.g = c000.g + (c100.g - c000.g) * d.r + (c111.g - c101.g) * d.g + (c001.g - c000.g) * d.b + + (c101.g - c001.g - c100.g + c000.g) * d.r * d.b; + c.b = c000.b + (c100.b - c000.b) * d.r + (c111.b - c101.b) * d.g + (c001.b - c000.b) * d.b + + (c101.b - c001.b - c100.b + c000.b) * d.r * d.b; + } else { + const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + + c.r = c000.r + (c100.r - c000.r) * d.r + (c010.r - c000.r) * d.g + (c111.r - c110.r) * d.b + + (c110.r - c100.r - c010.r + c000.r) * d.r * d.g; + c.g = c000.g + (c100.g - c000.g) * d.r + (c010.g - c000.g) * d.g + (c111.g - c110.g) * d.b + + (c110.g - c100.g - c010.g + c000.g) * d.r * d.g; + c.b = c000.b + (c100.b - c000.b) * d.r + (c010.b - c000.b) * d.g + (c111.b - c110.b) * d.b + + (c110.b - c100.b - c010.b + c000.b) * d.r * d.g; + } + + return c; +} + /** * Tetrahedral interpolation. Based on code found in Truelight Software Library paper. * @see http://www.filmlight.ltd.uk/pdf/whitepapers/FL-TL-TN-0057-SoftwareLib.pdf @@ -337,26 +389,32 @@ static int interp_##nbits##_##name##_p##depth(AVFilterContext *ctx, void *arg, i DEFINE_INTERP_FUNC_PLANAR(nearest, 8, 8) DEFINE_INTERP_FUNC_PLANAR(trilinear, 8, 8) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 8, 8) +DEFINE_INTERP_FUNC_PLANAR(pyramid, 8, 8) DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 9) DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 9) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 9) +DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 9) DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 10) DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 10) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 10) +DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 10) DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 12) DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 12) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 12) +DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 12) DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 14) DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 14) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 14) +DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 14) DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 16) DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 16) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 16) +DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 16) #define DEFINE_INTERP_FUNC_PLANAR_FLOAT(name, depth) \ static int interp_##name##_pf##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ @@ -422,6 +480,7 @@ static int interp_##name##_pf##depth(AVFilterContext *ctx, void *arg, int jobnr, DEFINE_INTERP_FUNC_PLANAR_FLOAT(nearest, 32) DEFINE_INTERP_FUNC_PLANAR_FLOAT(trilinear, 32) DEFINE_INTERP_FUNC_PLANAR_FLOAT(tetrahedral, 32) +DEFINE_INTERP_FUNC_PLANAR_FLOAT(pyramid, 32) #define DEFINE_INTERP_FUNC(name, nbits) \ static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ @@ -475,10 +534,12 @@ static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, i DEFINE_INTERP_FUNC(nearest, 8) DEFINE_INTERP_FUNC(trilinear, 8) DEFINE_INTERP_FUNC(tetrahedral, 8) +DEFINE_INTERP_FUNC(pyramid, 8) DEFINE_INTERP_FUNC(nearest, 16) DEFINE_INTERP_FUNC(trilinear, 16) DEFINE_INTERP_FUNC(tetrahedral, 16) +DEFINE_INTERP_FUNC(pyramid, 16) #define MAX_LINE_SIZE 512 @@ -1086,6 +1147,7 @@ static int config_input(AVFilterLink *inlink) case INTERPOLATE_NEAREST: SET_FUNC(nearest); break; case INTERPOLATE_TRILINEAR: SET_FUNC(trilinear); break; case INTERPOLATE_TETRAHEDRAL: SET_FUNC(tetrahedral); break; + case INTERPOLATE_PYRAMID: SET_FUNC(pyramid); break; default: av_assert0(0); } From patchwork Wed Jan 27 17:52:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 25225 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 7267944A67C for ; Wed, 27 Jan 2021 19:52:33 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 54AFF68A0EF; Wed, 27 Jan 2021 19:52:33 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ej1-f52.google.com (mail-ej1-f52.google.com [209.85.218.52]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0B8446806FE for ; Wed, 27 Jan 2021 19:52:25 +0200 (EET) Received: by mail-ej1-f52.google.com with SMTP id g12so3891148ejf.8 for ; Wed, 27 Jan 2021 09:52:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=ms4n+Gr5j+S/VE0yu7G3qQHzM48rPaKiUQ9RAPd25YY=; b=QUWso3TJKT2jyOnCJA5tBDeqkOhXSSsOZP5fzpSyUTqjRNInH3VgNFbQbtyaiSnlt6 oSc9aUVG7HGT5GliHCc2LkgcwrXnnzdbfvcHJ4sAHVlRUcnyNY4+iORxOwLpHyZvR5Ak gojzRRmLcyANgrLjdCqJnDkahOZeoEDqIPjdAo67fRpWvfnFCHhMyJLVASHUZGljtd2j fLZIgkbZYP5yXOxzdlh/69yMYLrc7UrOLFZG3Unz/OOYgWSNYn/LsMKOvdX4iB7c4cQi SNDoQBvR9MYB2uMkdPU+wFOPi0SLkxPZJYVtrDKEGPZdYx3lWFHq+a5gXVk7FrXtPrOI jl4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=ms4n+Gr5j+S/VE0yu7G3qQHzM48rPaKiUQ9RAPd25YY=; b=ZFFacU8LxPpUgfs94gN9ZlalKSovXg4w19FfYz8CGfLgLEbjsVA3Lk78G+4PmFlgHb weglzmsv/zZ8k3dfYWjfjSiweY3jaEAiXWVU//M6EbagEBdP8UHYadeIMHXVAVgyZYef 4Lk/Y8nFZZ8JVxPDBoqBVdhRYYkZeX6iUk6eFAz7xHBGYlPO5K4BcINbbtXhiX4jwXm2 4tbcf2yUfK6/kBiK7J6fntpWft0rovr9yZ+Yb5FLP0hAbNDYotmEvpovR4CHvfsas+CO MsX8W5d2NS3nde2w+urjNgGTM0E7rro+72egpOQTTEzwyDN+rGaLRjo1fAq2/1CeA2jL o+fQ== X-Gm-Message-State: AOAM530hLBIMomzvuoOWeGiFhCPaX6np2iYoWDjV3+P0AvXvSwpJ7Hom N6w6V3AULfSbgdmlap2n8vTpZoUTvuhIYQ== X-Google-Smtp-Source: ABdhPJwVGwHvpA1XjY/KDVxS0VhVcyvyycIqctYkKZsSLOIAoqaEgllqJjOxZ2wKuwj/3Zi19Anysw== X-Received: by 2002:a17:906:2e04:: with SMTP id n4mr7721214eji.289.1611769944433; Wed, 27 Jan 2021 09:52:24 -0800 (PST) Received: from localhost.localdomain ([31.45.254.141]) by smtp.gmail.com with ESMTPSA id q22sm1180508ejx.3.2021.01.27.09.52.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Jan 2021 09:52:24 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Wed, 27 Jan 2021 18:52:12 +0100 Message-Id: <20210127175212.17869-2-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210127175212.17869-1-onemda@gmail.com> References: <20210127175212.17869-1-onemda@gmail.com> Subject: [FFmpeg-devel] [PATCH 2/2] avfilter/vf_lut3d: add prism interpolation X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- doc/filters.texi | 2 ++ libavfilter/vf_lut3d.c | 57 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index a38f9b4124..52458c116d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -13868,6 +13868,8 @@ Interpolate values using the 8 points defining a cube. Interpolate values using a tetrahedron. @item pyramid Interpolate values using a pyramid. +@item prism +Interpolate values using a prism. @end table @end table diff --git a/libavfilter/vf_lut3d.c b/libavfilter/vf_lut3d.c index 12eb15fe67..fb33c93c34 100644 --- a/libavfilter/vf_lut3d.c +++ b/libavfilter/vf_lut3d.c @@ -50,6 +50,7 @@ enum interp_mode { INTERPOLATE_TRILINEAR, INTERPOLATE_TETRAHEDRAL, INTERPOLATE_PYRAMID, + INTERPOLATE_PRISM, NB_INTERP_MODE }; @@ -105,6 +106,7 @@ typedef struct ThreadData { { "trilinear", "interpolate values using the 8 points defining a cube", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TRILINEAR}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ { "tetrahedral", "interpolate values using a tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_TETRAHEDRAL}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ { "pyramid", "interpolate values using a pyramid", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PYRAMID}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ + { "prism", "interpolate values using a prism", 0, AV_OPT_TYPE_CONST, {.i64=INTERPOLATE_PRISM}, INT_MIN, INT_MAX, FLAGS, "interp_mode" }, \ { NULL } #define EXPONENT_MASK 0x7F800000 @@ -237,6 +239,51 @@ static inline struct rgbvec interp_pyramid(const LUT3DContext *lut3d, return c; } +static inline struct rgbvec interp_prism(const LUT3DContext *lut3d, + const struct rgbvec *s) +{ + const int lutsize2 = lut3d->lutsize2; + const int lutsize = lut3d->lutsize; + const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)}; + const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)}; + const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]}; + const struct rgbvec c000 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + const struct rgbvec c010 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c101 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c111 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + next[2]]; + struct rgbvec c; + + if (d.b > d.r) { + const struct rgbvec c001 = lut3d->lut[prev[0] * lutsize2 + prev[1] * lutsize + next[2]]; + const struct rgbvec c011 = lut3d->lut[prev[0] * lutsize2 + next[1] * lutsize + next[2]]; + + c.r = c000.r + (c001.r - c000.r) * d.b + (c101.r - c001.r) * d.r + (c010.r - c000.r) * d.g + + (c000.r - c010.r - c001.r + c011.r) * d.b * d.g + + (c001.r - c011.r - c101.r + c111.r) * d.r * d.g; + c.g = c000.g + (c001.g - c000.g) * d.b + (c101.g - c001.g) * d.r + (c010.g - c000.g) * d.g + + (c000.g - c010.g - c001.g + c011.g) * d.b * d.g + + (c001.g - c011.g - c101.g + c111.g) * d.r * d.g; + c.b = c000.b + (c001.b - c000.b) * d.b + (c101.b - c001.b) * d.r + (c010.b - c000.b) * d.g + + (c000.b - c010.b - c001.b + c011.b) * d.b * d.g + + (c001.b - c011.b - c101.b + c111.b) * d.r * d.g; + } else { + const struct rgbvec c110 = lut3d->lut[next[0] * lutsize2 + next[1] * lutsize + prev[2]]; + const struct rgbvec c100 = lut3d->lut[next[0] * lutsize2 + prev[1] * lutsize + prev[2]]; + + c.r = c000.r + (c101.r - c100.r) * d.b + (c100.r - c000.r) * d.r + (c010.r - c000.r) * d.g + + (c100.r - c110.r - c101.r + c111.r) * d.b * d.g + + (c000.r - c010.r - c100.r + c110.r) * d.r * d.g; + c.g = c000.g + (c101.g - c100.g) * d.b + (c100.g - c000.g) * d.r + (c010.g - c000.g) * d.g + + (c100.g - c110.g - c101.g + c111.g) * d.b * d.g + + (c000.g - c010.g - c100.g + c110.g) * d.r * d.g; + c.b = c000.b + (c101.b - c100.b) * d.b + (c100.b - c000.b) * d.r + (c010.b - c000.b) * d.g + + (c100.b - c110.b - c101.b + c111.b) * d.b * d.g + + (c000.b - c010.b - c100.b + c110.b) * d.r * d.g; + } + + return c; +} + /** * Tetrahedral interpolation. Based on code found in Truelight Software Library paper. * @see http://www.filmlight.ltd.uk/pdf/whitepapers/FL-TL-TN-0057-SoftwareLib.pdf @@ -390,31 +437,37 @@ DEFINE_INTERP_FUNC_PLANAR(nearest, 8, 8) DEFINE_INTERP_FUNC_PLANAR(trilinear, 8, 8) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 8, 8) DEFINE_INTERP_FUNC_PLANAR(pyramid, 8, 8) +DEFINE_INTERP_FUNC_PLANAR(prism, 8, 8) DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 9) DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 9) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 9) DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 9) +DEFINE_INTERP_FUNC_PLANAR(prism, 16, 9) DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 10) DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 10) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 10) DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 10) +DEFINE_INTERP_FUNC_PLANAR(prism, 16, 10) DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 12) DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 12) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 12) DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 12) +DEFINE_INTERP_FUNC_PLANAR(prism, 16, 12) DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 14) DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 14) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 14) DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 14) +DEFINE_INTERP_FUNC_PLANAR(prism, 16, 14) DEFINE_INTERP_FUNC_PLANAR(nearest, 16, 16) DEFINE_INTERP_FUNC_PLANAR(trilinear, 16, 16) DEFINE_INTERP_FUNC_PLANAR(tetrahedral, 16, 16) DEFINE_INTERP_FUNC_PLANAR(pyramid, 16, 16) +DEFINE_INTERP_FUNC_PLANAR(prism, 16, 16) #define DEFINE_INTERP_FUNC_PLANAR_FLOAT(name, depth) \ static int interp_##name##_pf##depth(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ @@ -481,6 +534,7 @@ DEFINE_INTERP_FUNC_PLANAR_FLOAT(nearest, 32) DEFINE_INTERP_FUNC_PLANAR_FLOAT(trilinear, 32) DEFINE_INTERP_FUNC_PLANAR_FLOAT(tetrahedral, 32) DEFINE_INTERP_FUNC_PLANAR_FLOAT(pyramid, 32) +DEFINE_INTERP_FUNC_PLANAR_FLOAT(prism, 32) #define DEFINE_INTERP_FUNC(name, nbits) \ static int interp_##nbits##_##name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ @@ -535,11 +589,13 @@ DEFINE_INTERP_FUNC(nearest, 8) DEFINE_INTERP_FUNC(trilinear, 8) DEFINE_INTERP_FUNC(tetrahedral, 8) DEFINE_INTERP_FUNC(pyramid, 8) +DEFINE_INTERP_FUNC(prism, 8) DEFINE_INTERP_FUNC(nearest, 16) DEFINE_INTERP_FUNC(trilinear, 16) DEFINE_INTERP_FUNC(tetrahedral, 16) DEFINE_INTERP_FUNC(pyramid, 16) +DEFINE_INTERP_FUNC(prism, 16) #define MAX_LINE_SIZE 512 @@ -1148,6 +1204,7 @@ static int config_input(AVFilterLink *inlink) case INTERPOLATE_TRILINEAR: SET_FUNC(trilinear); break; case INTERPOLATE_TETRAHEDRAL: SET_FUNC(tetrahedral); break; case INTERPOLATE_PYRAMID: SET_FUNC(pyramid); break; + case INTERPOLATE_PRISM: SET_FUNC(prism); break; default: av_assert0(0); }