3

I am trying to implement the vivid light color blend in code (I guess c# for now). I found two pages that say how to do it, but I don't understand their notation.

http://www.deepskycolors.com/archive/2010/04/21/formulas-for-Photoshop-blending-modes.html https://en.wikipedia.org/wiki/Blend_modes

Does anyone understand how to convert it into code? From my end, I have two Color objects with r, g, b values. Can anyone show the algorithm but using r, g, b values?

Thanks

Here is my non-working implementation:

using System;
using System.Drawing;

namespace CardMaker
{
    class VividLight : ColorFilter
    {
        public override Color GetFilteredColor(Color p1, Color p2)
        {
            int newR = Math.Max(0, Math.Min(255, Convert.ToInt32(GetColor(p1.R, p2.R))));
            int newG = Math.Max(0, Math.Min(255, Convert.ToInt32(GetColor(p1.G, p2.G))));
            int newB = Math.Max(0, Math.Min(255, Convert.ToInt32(GetColor(p1.B, p2.B))));

            return Color.FromArgb(newR, newG, newB);
        }

        private static double GetColor(int c1, int c2)
        {
            if (c2 > 128)
            {
                return 256 - ((256 - c1) / (512 * (c2 - 128)));
            }
            else
            {
                return c1 / (256 - 512 * c2);
            }
        }
    }
}
omega
  • 30,811
  • 68
  • 188
  • 388

1 Answers1

0

The formula is in terms of floating-point numbers in [0, 1], and you have converted it to [0,255]. You've also scaled the constants used in the formula accordingly.

However, some of those constants had an additive role and some of them had a multiplicative role. What you should do between these cases differs. Numbers that will be added can be scaled as you have done, but numbers that will be multiplied should not (the result will already be scaled correctly as the other multiplicand (one of the color values) will already have been scaled). This is in direct analogy to the issues one faces when implementing multiplication in fixed point arithmetic.

Here, everywhere you've said 512, you should say 2.

As a side note, you should be mindful of a possible speed/precision tradeoff between integer and floating-point division. Your method says it's returning a double, but the expression in the return statement evaluates to an int (and uses integer division, rounding down). That result is then widened by the compiler to a double after evaluation. It is possible that your results would be more precise (and slower) by using floating point division instead (to do this, use the constant 2.0 instead of 2)- though since there isn't any multiplication happening after your division, it might not make a big difference. Try it both ways.

    private static double GetColor(int c1, int c2)
    {
        if (c2 > 128)
        {
            return 256 - ((256 - c1) / (2 * (c2 - 128)));
        }
        else
        {
            return c1 / (256 - 2 * c2);
        }
    }
Jerry Federspiel
  • 1,484
  • 10
  • 14