<p>So taking source over as an example, the math works out to:</p>

<blockquote>
  <p>dst = a * src + (1 - a) * dst</p>
</blockquote>

<p>Taking Nathan Reed's suggestion of replacing <code>(1 - a)</code> with <code>b</code>, that gives us:</p>

<blockquote>
  <p>dst = a * src + b * dst</p>
</blockquote>

<p>If we perform the next iteration, it becomes:</p>

<blockquote>
  <p>dst = a * src + ab * src + b^2 * dst</p>
</blockquote>

<p>Doing it again, we get:</p>

<blockquote>
  <p>dst = a * src + ab * src + ab^2 * src + b^3 * dst</p>
</blockquote>

<p>And then:</p>

<blockquote>
  <p>dst = a * src + ab * src + ab^2 * src + ab^3 * src + b^4 * dst</p>
</blockquote>

<p>The pattern appears to be:</p>

<pre><code>int exponent;
for (exponent = 0; exponent &lt; numIterations; exponent++)
{
    newDst += a * pow(b, exponent) * src;
}
newDst += pow(b, exponent) * dst;
</code></pre>

CC BY-SA 4.0
2018-09-07T20:43:27.523Z
Are you sure to plug the result of the first alpha over into `src` of the next one? As I understand it, I would put it into `dst` instead. This lines up with some quick tests of the final equation with black `src`, white `dst` and an a>0. Overlaying black over white should darken the color but ` + dst` prevents this.
piegames
CC BY-SA 4.0
2018-09-08T02:37:14.697Z
I agree that substituting into `dst` is the correct thing to do here. If you imagine doing `n` separate blends on top of each other, the `src` would be the same for all, and result of each blend would be the following blend's `dst`. I think you should be able to simplify the result to a single blend using alpha of `1 - (1 - a)^n` though. (Try defining a new variable `b = 1 - a`, and repeating the derivation you used for the first part of the answer.)
Nathan Reed
CC BY-SA 4.0
2018-09-08T05:30:34.773Z
Great idea! I've updated it with your suggestion. Let me know how it works.
user1118321
CC BY-SA 4.0
2018-09-08T05:48:23.037Z
How about `dst := (1 - b)*src + b*dst`, and then rewrite that as `src + b*(dst - src)`. Then it works out similarly to your original derivation. :)
Nathan Reed
CC BY-SA 4.0
2018-09-08T06:18:41.850Z
Ah,  I see what you mean. I'll give that a try in the morning. I'm getting sleepy now and would probably screw it up.
user1118321
CC BY-SA 4.0
2018-09-08T08:09:50.203Z
Whoa, that looks really good. Am I allowed to bracket out `src` in that sum, to avoid multiplicating with `src` n times and reduce it to once at the end? Because if so, this becomes a geometric series which can be optimized even further.
piegames
CC BY-SA 4.0
2018-09-08T14:48:15.747Z
Absolutely! If it works, go for it!
user1118321
CC BY-SA 4.0
2018-09-07T20:28:32.237Z
2018-09-08T05:28:58.053Z
2018-09-08T05:28:58.053Z
user1118321
<p>I have two RGBA colors in linear [0..1] space, <code>src</code> and <code>dst</code> and I want to alpha blender <code>src</code> over/under <code>dst</code> n times. Of course, I could call the respective operation n times using the result from the previous one (which is what I am currently doing), but I want to optimize it into a single operation. I think just calculating the correct alpha on <code>src</code> should be sufficient, but I may be wrong. Here's what I currently use:</p>

<pre><code>public static final Color alphaOver(Color dst, Color src) {
    float src1A = 1 - src.a;
    float outA = src.a + dst.a * src1A;

    if (outA == 0)
        return Color.TRANSPARENT;
    return new Color(
            outA,
            (src.r * src.a + dst.r * dst.a * src1A) / outA,
            (src.g * src.a + dst.g * dst.a * src1A) / outA,
            (src.b * src.a + dst.b * dst.a * src1A) / outA);
}

public static final Color alphaUnder(Color dst, Color src) {
    return alphaOver(src, dst);
}

public static final Color alphaOver(Color dst, Color src, int times) {
    Color ret = dst;
    for (int i = 0; i &lt; times; i++)
        ret = alphaOver(ret, src);
    return ret;
}

public static final Color alphaUnder(Color dst, Color src, int times) {
    Color ret = dst;
    for (int i = 0; i &lt; times; i++)
        ret = alphaUnder(ret, src);
    return ret;
}
</code></pre>

<p>How can I optimize the last two functions?</p>

<color><blending><alpha>
Repeating alpha over/under operation multiple times
piegames
# Repeating alpha over/under operation multiple times

(Asked by: username_0 on 2018-09-07)

I have two RGBA colors in linear [0..1] space, `src` and `dst` and I want to alpha blender `src` over/under `dst` n times. Of course, I could call the respective operation n times using the result from the previous one (which is what I am currently doing), but I want to optimize it into a single operation. I think just calculating the correct alpha on `src` should be sufficient, but I may be wrong. Here's what I currently use:

```
public static final Color alphaOver(Color dst, Color src) {
    float src1A = 1 - src.a;
    float outA = src.a + dst.a * src1A;

    if (outA == 0)
        return Color.TRANSPARENT;
    return new Color(
            outA,
            (src.r * src.a + dst.r * dst.a * src1A) / outA,
            (src.g * src.a + dst.g * dst.a * src1A) / outA,
            (src.b * src.a + dst.b * dst.a * src1A) / outA);
}

public static final Color alphaUnder(Color dst, Color src) {
    return alphaOver(src, dst);
}

public static final Color alphaOver(Color dst, Color src, int times) {
    Color ret = dst;
    for (int i = 0; i < times; i++)
        ret = alphaOver(ret, src);
    return ret;
}

public static final Color alphaUnder(Color dst, Color src, int times) {
    Color ret = dst;
    for (int i = 0; i < times; i++)
        ret = alphaUnder(ret, src);
    return ret;
}

```

How can I optimize the last two functions?

**Tags:** color, blending, alpha


---

## 1 answers

### Answer by username_1 on 2018-09-07. Score: 1 | Accepted answer

So taking source over as an example, the math works out to:

> dst = a \* src + (1 - a) \* dst

Taking username_2 username_2's suggestion of replacing `(1 - a)` with `b`, that gives us:

> dst = a \* src + b \* dst

If we perform the next iteration, it becomes:

> dst = a \* src + ab \* src + b^2 \* dst

Doing it again, we get:

> dst = a \* src + ab \* src + ab^2 \* src + b^3 \* dst

And then:

> dst = a \* src + ab \* src + ab^2 \* src + ab^3 \* src + b^4 \* dst

The pattern appears to be:

```
int exponent;
for (exponent = 0; exponent < numIterations; exponent++)
{
    newDst += a * pow(b, exponent) * src;
}
newDst += pow(b, exponent) * dst;

```

> **Comments:**
> **username_0**: Are you sure to plug the result of the first alpha over into `src` of the next one? As I understand it, I would put it into `dst` instead. This lines up with some quick tests of the final equation with black `src`, white `dst` and an a>0. Overlaying black over white should darken the color but ` + dst` prevents this.  
> **username_2**: I agree that substituting into `dst` is the correct thing to do here. If you imagine doing `n` separate blends on top of each other, the `src` would be the same for all, and result of each blend would be the following blend's `dst`. I think you should be able to simplify the result to a single blend using alpha of `1 - (1 - a)^n` though. (Try defining a new variable `b = 1 - a`, and repeating the derivation you used for the first part of the answer.)  
> **username_1**: Great idea! I've updated it with your suggestion. Let me know how it works.  
> **username_2**: How about `dst := (1 - b)*src + b*dst`, and then rewrite that as `src + b*(dst - src)`. Then it works out similarly to your original derivation. :)  
> **username_1**: Ah,  I see what you mean. I'll give that a try in the morning. I'm getting sleepy now and would probably screw it up.  
> **username_0**: Whoa, that looks really good. Am I allowed to bracket out `src` in that sum, to avoid multiplicating with `src` n times and reduce it to once at the end? Because if so, this becomes a geometric series which can be optimized even further.  
> **username_1**: Absolutely! If it works, go for it!  

---

