




The Art of Noise / Graphics / C# 
IntroductionDo you want to know how the above image was created? Then read on... First, let's take the simple approach: we assign to each pixel in the 256x256 bitmap, a random value. We only assign a value to the blue component: for each row in the bitmap
for each column in the bitmap
N = a random value in the range [0,1]
Color = (Red = 0, Green = 0, Blue = N * 255)
end for
end for
Here's the result: As you can see, it's not that bad, but it's not what we want either. In fact, what do we want? We don't want a bitmap with random colors, we want a bitmap with more or less random colors. But what does that mean? It means that if we take, for example, pixel (0,1), the color of pixel (0,2) will be more or less the same color of pixel (0,1). So, if the color of pixel (0,1) is (0,0,255), the color of pixel (0,2) cannot be (0,0,0). No, it should be, let's say, (0,0,250). Ok, how do we do that? Instead of assigning a random color to each and every pixel in the bitmap, we assign a random color to only some of the pixels in the bitmap. We could, for example, assign a random color to every 10 pixels. So, the pixels (0,0), (0,10), (0,20), ... (10,0), (10,10), (10,20), ... (20,0), (20,10), (20,20), ... will have a random color. All other pixels will be calculated based on the color of the neighboring pixels. Here's some code: ...
void Ran()
{
Random r = new Random();
_Random = new Double[_Width * _Height];
for (Int32 i = 0; i < _Width * _Height; i++)
_Random[i] = r.NextDouble();
}
public void Create(Bitmap bmp)
{
_Width = bmp.Width;
_Height = bmp.Height;
Ran();
for (Int32 y = 0; y < bmp.Height; y++) {
for (Int32 x = 0; x < bmp.Width; x++) {
Double N = 0.0;
N += GetColor(x, y, 40);
Byte b = (Byte)(N * 255.0);
Color c = Color.FromArgb(255, 0, 0, b);
bmp.SetPixel(x, y, c);
}
}
}
...
The method Here's the result: But what does There are several ways to calculate a value for (0,12). We can draw a straight line between the points, or maybe a curved line: A curved line is more natural, so this is what we're going to use. We have to write a function which takes as input two points ...
Double f(Double x0, Double y0, Double x1, Double y1, Double x)
{
return (1.0 + Math.Cos(Math.PI +
(Math.PI / (x1x0)) * (xx0))) / 2.0 * (y1y0) + y0;
}
...
Whoa, I hear you cry! Where does that formula come from? I'll explain. Remember, we want to put a smooth, curved line between two points, right? Take a look at the following picture: Interesting, isn't? This picture is a plot of the function x > [x0,x1]
x / (x1  x0) > 1
x / (x1  x0) * pi > pi
(x / (x1  x0) * pi) + pi > [pi,2pi]
We have converted y > [1,1]
y + 1 > [0,2]
(y + 1) / 2 > [0,1]
(y + 1) / 2 * (y1  y0) > (y1  y0)
((y + 1) / 2 * (y1  y0)) + y0 > [y0, y1]
If you replace ...
Double f(Double x0, Double y0, Double x1, Double y1, Double x)
{
return (1.0 + Math.Cos(Math.PI +
(Math.PI / (x1x0)) * (xx0))) / 2.0 * (y1y0) + y0;
}
...
Back to The first thing we have to do is to take the value of the neighboring pixels. Well, these pixels are not really neighbors, they are the pixels which were assigned a random value and lay closest to the pixel we want to calculate. So, we look up the value of pixels (0,0), (0,40), (40,0) and (40,40). Then we have to find the value for Note that this picture has nothing to do with our data, I only show it to make things clear. So, the first step is to calculate the value for Here's the code for Double GetColor(Int32 x, Int32 y, Int32 M)
{
Int32 x0 = x  (x % M);
Int32 x1 = x0 + M;
Int32 y0 = y  (y % M);
Int32 y1 = y0 + M;
Double x0y0 = Noise(x0, y0);
Double x1y0 = Noise(x1, y0);
Double x0y1 = Noise(x0, y1);
Double x1y1 = Noise(x1, y1);
Double xx0 = Interpolate(x0, x0y0, x1, x1y0, x);
Double xx1 = Interpolate(x0, x0y1, x1, x1y1, x);
Double N = Interpolate(y0, xx0, y1, xx1, y);
return N;
}
Double Noise(Int32 x, Int32 y)
{
if (x < _Width && y < _Height)
return _Random[y * _Width + x];
else
return 0.0;
}
The method We're almost there. Take a look at the following pictures:
These pictures are generated using the same algorithm as before, except in the call to public void Create(ref Bitmap bmp)
{
_Width = bmp.Width;
_Height = bmp.Height;
Ran();
for (Int32 y = 0; y < bmp.Height; y++) {
for (Int32 x = 0; x < bmp.Width; x++) {
Double N = 0.0;
N += GetColor(x, y, 40/32);
N += GetColor(x, y, 40/2);
N += GetColor(x, y, 40/4);
N += GetColor(x, y, 40/8);
N += GetColor(x, y, 40/16);
N += GetColor(x, y, 40/32);
N /= 6.0;
Byte b = (Byte)(N * 255.0);
Color c = Color.FromArgb(255, 0, 0, b);
bmp.SetPixel(x, y, c);
}
}
}
See? We add the values together and divide the result by 6 to get again a value between 0 and 1. Well, that's it! You've learned to create art with noise. 
