Skip to content

Commit

Permalink
Tweaked linear interpolation routines. Integer lerp is now branch fre…
Browse files Browse the repository at this point in the history
…e, and floating-point lerp is more accurate.

git-svn-id: https://agg.svn.sourceforge.net/svnroot/agg@77 ab9de31f-a152-4fe9-8809-95f286f9ca89
  • Loading branch information
jim_barry committed Jan 30, 2013
1 parent a4b1659 commit b12782e
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 42 deletions.
42 changes: 22 additions & 20 deletions agg-2.4/include/agg_color_gray.h
Expand Up @@ -249,7 +249,7 @@ namespace agg
}

//--------------------------------------------------------------------
// fixed-point multiply, exact over uint8
// Fixed-point multiply, exact over int8u.
static AGG_INLINE value_type multiply(value_type a, value_type b)
{
calc_type t = a * b + base_MSB;
Expand All @@ -270,8 +270,8 @@ namespace agg
}

//--------------------------------------------------------------------
// fixed-point multiply, exact over uint8
// specifically for multiplying a color component by a cover
// Fixed-point multiply, exact over int8u.
// Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, value_type b)
{
return multiply(a, b);
Expand All @@ -284,19 +284,18 @@ namespace agg
}

//--------------------------------------------------------------------
// linear interpolate q over p by a, assuming q is pre-muliplied by a
// Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}

//--------------------------------------------------------------------
// linear interpolate q over p by a
// Interpolate p to q by a.
static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
{
if (p < q) return p + multiply(q - p, a);
else if (p > q) return p - multiply(p - q, a);
else return p;
int t = (q - p) * a + base_MSB - (p > q);
return value_type(p + (((t >> base_shift) + t) >> base_shift));
}

//--------------------------------------------------------------------
Expand Down Expand Up @@ -557,7 +556,7 @@ namespace agg
}

//--------------------------------------------------------------------
// fixed-point multiply, exact over uint16
// Fixed-point multiply, exact over int16u.
static AGG_INLINE value_type multiply(value_type a, value_type b)
{
calc_type t = a * b + base_MSB;
Expand All @@ -578,8 +577,8 @@ namespace agg
}

//--------------------------------------------------------------------
// fixed-point multiply, almost exact over uint16
// specifically for multiplying a color component by a cover
// Fixed-point multiply, almost exact over int16u.
// Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return multiply(a, b << 8 | b);
Expand All @@ -592,19 +591,18 @@ namespace agg
}

//--------------------------------------------------------------------
// linear interpolate q over p by a, assuming q is pre-muliplied by a
// Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}

//--------------------------------------------------------------------
// linear interpolate q over p by a
// Interpolate p to q by a.
static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
{
if (p < q) return p + multiply(q - p, a);
else if (p > q) return p - multiply(p - q, a);
else return p;
int t = (q - p) * a + base_MSB - (p > q);
return value_type(p + (((t >> base_shift) + t) >> base_shift));
}

//--------------------------------------------------------------------
Expand Down Expand Up @@ -917,17 +915,21 @@ namespace agg
}

//--------------------------------------------------------------------
// linear interpolate q over p by a, assuming q is pre-muliplied by a
// Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
return (1 - a) * p + q; // more accurate than "p + q - p * a"
}

//--------------------------------------------------------------------
// linear interpolate q over p by a
// Interpolate p to q by a.
static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
{
return p + multiply(q - p, a);
// The form "p + a * (q - p)" avoids a multiplication, but may produce an
// inaccurate result. For example, "p + (q - p)" may not be exactly equal
// to q. Therefore, stick to the basic expression, which at least produces
// the correct result at either extreme.
return (1 - a) * p + a * q;
}

//--------------------------------------------------------------------
Expand Down
46 changes: 24 additions & 22 deletions agg-2.4/include/agg_color_rgba.h
Expand Up @@ -363,7 +363,7 @@ namespace agg
}

//--------------------------------------------------------------------
// fixed-point multiply, exact over uint8
// Fixed-point multiply, exact over int8u.
static AGG_INLINE value_type multiply(value_type a, value_type b)
{
calc_type t = a * b + base_MSB;
Expand All @@ -384,8 +384,8 @@ namespace agg
}

//--------------------------------------------------------------------
// fixed-point multiply, exact over uint8
// specifically for multiplying a color component by a cover
// Fixed-point multiply, exact over int8u.
// Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return multiply(a, b);
Expand All @@ -398,23 +398,22 @@ namespace agg
}

//--------------------------------------------------------------------
// linear interpolate q over p by a, assuming q is pre-muliplied by a
// Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}

//--------------------------------------------------------------------
// linear interpolate q over p by a
// Interpolate p to q by a.
static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
{
if (p < q) return p + multiply(q - p, a);
else if (p > q) return p - multiply(p - q, a);
else return p;
int t = (q - p) * a + base_MSB - (p > q);
return value_type(p + (((t >> base_shift) + t) >> base_shift));
}

//--------------------------------------------------------------------
self_type& clear()
self_type& clear()
{
r = g = b = a = 0;
return *this;
Expand Down Expand Up @@ -734,7 +733,7 @@ namespace agg
}

//--------------------------------------------------------------------
// fixed-point multiply, exact over uint16
// Fixed-point multiply, exact over int16u.
static AGG_INLINE value_type multiply(value_type a, value_type b)
{
calc_type t = a * b + base_MSB;
Expand All @@ -755,8 +754,8 @@ namespace agg
}

//--------------------------------------------------------------------
// fixed-point multiply, almost exact over uint16
// specifically for multiplying a color component by a cover
// Fixed-point multiply, almost exact over int16u.
// Specifically for multiplying a color component by a cover.
static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
{
return multiply(a, (b << 8) | b);
Expand All @@ -769,19 +768,18 @@ namespace agg
}

//--------------------------------------------------------------------
// linear interpolate q over p by a, assuming q is pre-muliplied by a
// Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
}

//--------------------------------------------------------------------
// linear interpolate q over p by a
// Interpolate p to q by a.
static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
{
if (p < q) return p + multiply(q - p, a);
else if (p > q) return p - multiply(p - q, a);
else return p;
int t = (q - p) * a + base_MSB - (p > q);
return value_type(p + (((t >> base_shift) + t) >> base_shift));
}

//--------------------------------------------------------------------
Expand Down Expand Up @@ -1116,21 +1114,25 @@ namespace agg
}

//--------------------------------------------------------------------
// linear interpolate q over p by a, assuming q is pre-muliplied by a
// Interpolate p to q by a, assuming q is premultiplied by a.
static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
{
return p + q - multiply(p, a);
return (1 - a) * p + q; // more accurate than "p + q - p * a"
}

//--------------------------------------------------------------------
// linear interpolate q over p by a
// Interpolate p to q by a.
static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
{
return p + multiply(q - p, a);
// The form "p + a * (q - p)" avoids a multiplication, but may produce an
// inaccurate result. For example, "p + (q - p)" may not be exactly equal
// to q. Therefore, stick to the basic expression, which at least produces
// the correct result at either extreme.
return (1 - a) * p + a * q;
}

//--------------------------------------------------------------------
self_type& clear()
self_type& clear()
{
r = g = b = a = 0;
return *this;
Expand Down

0 comments on commit b12782e

Please sign in to comment.