The basic algorithm for getting a value at a certain position (in the range 0..1) between 2 values is:
value_at_position = value_at_0 + (value_at_1 - value_at_0) * position
Concretely, this means for a gradient between 2 RGB colors:
red_at_position = red_at_0 + ( red_at_1 - red_at_0) * position green_at_position = green_at_0 + (green_at_1 - green_at_0) * position blue_at_position = blue_at_0 + ( blue_at_1 - blue_at_0) * position
The same principle can be applied to any color model. However for models like HSV or HSL, since Hue is an angular value (0° is the same as 360°), you could also choose the sense of rotation:
Clockwise (descending)
if hue_at_1 < hue_at_0: hue_at_position = hue_at_0 - (hue_at_0 - hue_at_1) * position else: hue_at_position = hue_at_0 - (360° - (hue_at_1 - hue_at_0)) * position if hue_at_position < 0: hue_at_position += 360°
Counterclockwise (ascending)
if hue_at_0 < hue_at_1: hue_at_position = hue_at_0 + (hue_at_1 - hue_at_0) * position else: hue_at_position = hue_at_0 + (360° - (hue_at_0 - hue_at_1)) * position if (hue_at_position > 360°): hue_at_position -= 360°
The technology used in monitors makes them render luminance in a nonlinear way. Therefore electronic images are usually encoded in a way that compensate that characteristic. This is called Gamma correction. One could apply that correction to gradients. This applies of course only to RGB interpolated gradients. R,G and B need to be expressed in the 0..1 range.
red = pow( red, gamma) green = pow(green, gamma) blue = pow( blue, gamma)
If you're working in a linear RGB space, you could approximate sRGB by using a gamma of 2.2. On the other hand, if you're working in sRGB, using a gamma of 1/2.2 approximates a linear interpolation.
Real sRGB uses slightly more complex algorithm.
Instead of “simply” multiply the difference by the position, you could also use other algorithms as a multiplication factor. You should then change "position" to "factor" in the base algorithm.
The midpoint is used by some softwares as a control point. It means the value normally reached at position 0.5 should be reached at another position.
if seg_pos <= midpoint: factor = 0.5 * position / midpoint else: midpoint = 1.0 - midpoint factor = 0.5 + 0.5 * (position - midpoint) / midpoint
factor = pow(position, log(0.5) / log(midpoint))
factor = (sin ((-pi / 2.0) + pi * linear_factor) + 1.0) / 2.0
factor = sqrt (1.0 - (linear_factor - 1.0) * (linear_factor - 1.0))
factor = 1.0 - sqrt(1.0 - linear_factor * linear_factor)
You can find some file formats descriptions on another page of this web site.
All that's described before (except for gamma correction) is based on Gimp's implementation of gradients. It can interpolate gradients in RGB, HSV CW and HSV CCW. A specific point in Gimp is you can choose a different interpolation between each stop.
Its source code may give you some more hints.
For the gradients in SVG, you can choose for the color interpolation space. SVG1.1 knows about sRGB and LinearRGB and the 1.2 draft introduces CIE-Lab and CIE-LCHab.
Same as SVG1.1 (see documentation).
Even though Scribus supports CMYK, gradients are always interpolated in RGB. Uses the basic algorithm.
Photoshop gradients have the midpoint parameter and use the sinusoidal algorithm
IDML's documentation (p. 261) says “When mixing gradients that contain gradient stops with different color spaces, In Design looks through all of the gradient stops for the widest gamut color space and uses it as a unified color space. However, if CMYK color space is one of the gradient stops, then CMYK color space is always the preferred unified space. All process color gradient stops that are not in the unified color space are converted to the unified space before blending.”
Like Illustrator, the algorithm used is the curved one with the midpoint parameter.
Within PDF, color gradients are called “Shading patterns” (see documentation p. 181). Interpolation is fully customizable. Sample code in the PostScript SDK (“Smooth Shading”).