## Introduction

In my previous article (for more info, please visit www.publishing.unicadinc.com), I have shown you how to draw color bars by associating the y data with the indices of the color map matrix. In some graphics applications, you may want to directly map the color of a surface object according to a given set of color data. In this article, I will show you how to create such a custom color shading.

## Background

Consider a situation involving the color map matrix with the name "Jet" , as defined in `ColorMap`

class of the previous project, with the default color map length = 64. Suppose we have a 3-by-3 color data matrix:

In this case, the maximum and minimum of the color data are 4 and -3 respectively. We can easily determine the color map index numbers using the formula given in the previous article to be:

Up to this point, we have not been supplying the x- and y- coordinate data. We believe that the color data values along the row (x data) and column (y data) specify 9 vertices where each neighboring set of four elements is connected by means of a quadrilateral. As shown in Figure 1, in terms of the elements within the color data matrix, there are four quadrilaterals. You might wonder why we need nine indices in the color map when there are only four quadrilaterals. With surface objects, each vertex can be assigned a color. This allows you to perform a bilinear interpolation among four vertex colors to determine the color at any point within the quadrilateral.

Figure 1: Color matrix and color map.

If you do not want to use color interpolation, the color data can also be a 2-by-2 matrix, as shown in Figure 1 with the circled elements. Basically, you can take the top-left vertex color data to fill the corresponding quadrilateral. Combining this with the color indices, you obtain the direct color map for these four quadrilaterals, as shown in the right of Figure 1.

You can see from this figure that the color changes very dramatically from one quadrilateral to another. To obtain a better color shading effect, you need to perform a bilinear color interpolation. Bilinear interpolation uses the four vertex values surrounding each quadrilateral to obtain any value inside the quadrilateral. Suppose you want to get the value at (x, y), and the vertices of the quadrilateral are located at (x0, y0), (x1, y0), (x0, y1), and (x1, y1), where they have the color data values C00, C10, C01, and C11, respectively, as show in Figure 2:

Figure 2: Coordinates used for bilinear interpolations.

Linear interpolations on the top row of neighbors, between (x0, y0) and (x1, y0), estimate the value C0 at (x, y0) as:

Likewise, linear interpolation on the bottom row of neighbors, between (x0, y1) and (x1, y1), estimates the value C1 at (x, y1) as:

Finally, linear interpolation between C0 and C1 estimates the value C at (x, y) as:

By substituting the expressions for C0 and C1 into the above equation, we obtain:

You can see that the equation for C is a polynomial involving powers of x and y no greater than 1, and with four coefficients: C = a1+ a2*x + a3*y + a4*x*y. Because these four coefficients were determined by four values (C00, C01, C10, and C11), they are usually uniquely determined by the data. This immediately implies that the comparable procedure of first interpolating along columns (in the y-direction) and then interpolating the results in the x-direction will give the same result, because it, too, will have a similar formula with a unique solution.

Note that the term "bilinear" derives from the process of linear interpolation (twice in one direction, then once in the perpendicular direction), **not** from the formula for C. The formula involves a term with x * y, which is not linear.

We now can implement the color shading using the above equations. You need to add the `ColorMap`

class from my previous article, and a new point class, `PointC`

, to the current project. `PointC`

contains the color data and a color `ARGBArray`

. Here is its code list:

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Example1_9
{
public class PointC
{
public PointF pointf = new PointF();
public float C = 0;
public int[] ARGBArray = new int[4];
public PointC()
{
}
public PointC(PointF ptf, float c)
{
pointf = ptf;
C = c;
}
public PointC(PointF ptf, float c, int[] argbArray)
{
pointf = ptf;
C = c;
ARGBArray = argbArray;
}
}
}

This class is very simple; we just associate the color data and the `ARGBArray`

with the point.

All the rest of the code has been implemented in the `Form1`

class. The method `Interp`

in the `Form1`

class takes four vertex points and the corresponding color data values of a given quadrilateral as inputs, and interpolates the color data values within the quadrilateral using the bilinear interpolation approach. The color shading quality is controlled by the number of the interpolation points: `npoints`

.

In the `DrawObjects`

method, we first draw the objects using the direct map approach, and then using the bilinear interpolation by calling the `Interp `

method.

## Using the Code

The enclosed ZIP file includes all source code and binary files, which were built on Visual Studio 2005. Running the project generates the output, as shown in Figure 3:

Figure 3: Direct (left) and interpolated (right) color maps.

The bilinear interpolated color map has found wide applications in image processing and 3D surface chart applications.

This project is taken from the examples (example1-9 in Chapter 1) of the new book "Practical C# Charts and Graphics", where you can find more advanced chart and graphics programming for real-world .NET applications. For more information, please visit the Web site.

## About the Author

Dr. Jack Xu has a Ph.D in theoretical physics. He has over 15 years programming experience in Basic, Fortran, C, C++, Matlab, and C#, specializing in numerical computation methods, algorithms, physical modeling, computer-aided design (CAD) development, graphics user interface, and 3D graphics. Currently, he is responsible for developing commercial CAD tools based on Microsoft .NET Framework.

Please read my other articles: