Blender V5.0
COM_algorithm_summed_area_table.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
7#include "BLI_math_vector.hh"
9
10#include "COM_context.hh"
11#include "COM_result.hh"
12
13namespace blender::compositor {
14
15/* Possible operations to apply on pixels before computing the summed area table. The Square
16 * operation, for instance, can be useful to compute image variance from sum of squares. */
17enum class SummedAreaTableOperation : uint8_t {
20};
21
22/* Computes a summed area table from the given input and write the table to the given output. A
23 * summed are table is an image where each pixel contains the sum of all pixels in the areas down
24 * and to its left toward the zero index, including the pixel itself. This table is particularly
25 * useful to accelerate filters that requires averaging large rectangular areas of the input, like
26 * a box filter. */
27void summed_area_table(Context &context,
28 Result &input,
29 Result &output,
31
32/* Computes the sum of the rectangular region defined by the given lower and upper bounds from the
33 * given summed area table. It is assumed that the given upper bound is larger than the given lower
34 * bound, otherwise, undefined behavior is invoked. Looking at the diagram below, in order to
35 * compute the sum of area X, we sample the table at each of the corners of the area X, to get:
36 *
37 * Upper Right -> A + B + C + X (1)
38 * Upper Left -> A + B (2)
39 * Lower Right -> B + C (3)
40 * Lower Left -> B (4)
41 *
42 * We start from (1) and subtract (2) and (3) to get rid of A and C to get:
43 *
44 * (A + B + C + X) - (A + B) - (B + C) = (X - B)
45 *
46 * To get rid of B, we add (4) to get:
47 *
48 * (X - B) + B = X
49 *
50 * ^
51 * |
52 * +-------+-----+
53 * | | |
54 * | A | X |
55 * | | |
56 * +-------+-----+
57 * | | |
58 * | B | C |
59 * | | |
60 * o-------+-----+------>
61 *
62 * The aforementioned equation eliminates the edges between regions X, C, and A since they get
63 * subtracted with C and A. To avoid this, we subtract 1 from the lower bound and fallback to zero
64 * for out of bound sampling. */
66 const int2 &lower_bound,
67 const int2 &upper_bound)
68{
69 int2 corrected_lower_bound = lower_bound - int2(1);
70 int2 corrected_upper_bound = math::min(table.domain().size - int2(1), upper_bound);
71 float4 addend = table.load_pixel_zero<float4>(corrected_upper_bound) +
72 table.load_pixel_zero<float4>(corrected_lower_bound);
73 float4 subtrahend =
74 table.load_pixel_zero<float4>(int2(corrected_lower_bound.x, corrected_upper_bound.y)) +
75 table.load_pixel_zero<float4>(int2(corrected_upper_bound.x, corrected_lower_bound.y));
76 return addend - subtrahend;
77}
78
79} // namespace blender::compositor
T load_pixel_zero(const int2 &texel) const
const Domain & domain() const
#define input
#define output
#define Square(a, x, y)
void summed_area_table(Context &context, Result &input, Result &output, SummedAreaTableOperation operation=SummedAreaTableOperation::Identity)
float4 summed_area_table_sum(const Result &table, const int2 &lower_bound, const int2 &upper_bound)
T min(const T &a, const T &b)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2