0

I've created a 2d array of 1024 x 1024 values ranging from -1 to 1, but I do not know how I am supposed to change this to a greyscale image.

What I have been doing is assigning a certain color to certain values, but this is not what I was going for.

What I have:

enter image description here

Specific ranges of values between -1 and 1 are mapped to distinct colors in a noncontinuous way (see the code snippet below)

What I want:

enter image description here

Values between -1 and 1 are mapped to greyscale varying uniformly from black at -1 to white at 1 or vice-versa

Code for the current version

private void button1_Click(object sender, EventArgs e)
{
    sw.Start();
    LibNoise.Perlin perlinMap = new LibNoise.Perlin();
    perlinMap.Lacunarity = lacunarity + 0.01d;
    perlinMap.NoiseQuality = LibNoise.NoiseQuality.High;
    perlinMap.OctaveCount = octaveCount;
    perlinMap.Persistence = persistence;
    perlinMap.Frequency = frequency;
    perlinMap.Seed = 1024;

    if (radioButton1.Checked)
        perlinMap.NoiseQuality = LibNoise.NoiseQuality.Low;
    else if (radioButton2.Checked)
        perlinMap.NoiseQuality = LibNoise.NoiseQuality.Standard;
    else if (radioButton3.Checked)
        perlinMap.NoiseQuality = LibNoise.NoiseQuality.High;

    double sample = trackBar6.Value * 10;

    double[,] perlinArray = new double[resolutieX, resolutieY];
    for (int x = 0; x < resolutieX; x++)
    {
        for (int y = 0; y < resolutieY; y++)
        {
            perlinArray[x, y] = perlinMap.GetValue(x / sample, y / sample, 1d);
        }
    }
    draw(perlinArray);
    textBox12.Text = sw.ElapsedMilliseconds.ToString() + "ms";
    sw.Reset();
}

public void draw(double[,] array)
{
    Color color = Color.DarkBlue;
    // Bitmap b = new Bitmap(1, 1);


    Color[,] colorArray = new Color[resolutieX, resolutieY];
    Bitmap afbeelding = new Bitmap( 1024, 1024);

    // int tileSize = 1024 / resolutieY;

    for (int y = 1; y < resolutieY; y++)
    {
        for (int x = 1; x < resolutieX; x++)
        {

            colorArray[x, y] = array[x, y] <= 0.0 ? Color.DarkBlue :
                array[x, y] <= 0.1 ? Color.Blue :
                array[x, y] <= 0.2 ? Color.Beige :
                array[x, y] <= 0.22 ? Color.LightGreen :
                array[x, y] <= 0.40 ? Color.Green :
                array[x, y] <= 0.75 ? Color.DarkGreen :
                array[x, y] <= 0.8 ? Color.LightSlateGray :
                array[x, y] <= 0.9 ? Color.Gray :
                array[x, y] <= 1.0 ? Color.DarkSlateGray :
                Color.DarkSlateGray;

            //   colorArray[]
            // afbeelding.SetPixel(x, y, color);


        }
    }
    for (int y = 1; y < resolutieY; y++)
    {
        for (int x = 1; x < resolutieX; x++)
        {
            afbeelding.SetPixel(x, y, colorArray[x, y]);
        }
    }

    pictureBox1.Image = afbeelding;
}
Ben Aaronson
  • 6,955
  • 2
  • 23
  • 38
user3376217
  • 35
  • 3
  • 9
  • 4
    They are completely different.. this is not a simple grayscale conversion. – Simon Whitehead Jun 13 '14 at 10:06
  • @SimonWhitehead The image I have is created out of an array ranging from -1 to 1. If i use this values and assign the color white to -1, and black to 1, and greyscale in between, that sort of gradient should come out of it. I'm not sure how to do this though – user3376217 Jun 13 '14 at 10:15

2 Answers2

2

Ohhh, lovely fractals... :) As you are using a 2d vector from -1 to 1, you have to recalculate it to 0..255. Your function is

f(x) = 255 * (x+1)/2

Then all you have to do, is to create a 2D Color vector with f(x)

foreach (int value in 2dVector) { 2dColorVector.add(new Color.fromArgb(255, f(x), f(x), f(x)); }

Is pseudocode, but i think you could understand it clearly :)

Kaitiff
  • 416
  • 3
  • 9
0

You can get a grayscale image by setting the primary colors (RGB) to equal values.

One way of achieving this is to make a function that calculates the average of the RGB components of the colors you have, and then set each of the components to the average value.

Example - Average method:

Color ToGrayscale(Color c)
{
    int avg = (c.R + c.G + c.B)/3;
    return Color.FromArgb(avg, avg, avg);
}

Then apply that function for each output pixel:

for (int y = 1; y < resolutieY; y++)
{
    for (int x = 1; x < resolutieX; x++)
    {
        afbeelding.SetPixel(x, y, ToGrayscale(colorArray[x, y]));
    }
}

Luminosity

A more sophisticated version of grayscaling is the Luminosity method. It also averages the values, but it is a weighted average that takes human perception into account.

The formula is: 0.2126*Red + 0.7152*Green + 0.0722*Blue.

You can see how the formula is weighted towards which colors the human eye is most sensitive to.

To see if this alternate approach looks better for your project you simply use the Luminosity formula for calculating the average instead:

Color ToGrayscaleLuminosity(Color c)
{
    var avg = (int)Math.Round(0.2126 * c.R + 0.7152 * c.G + 0.0722 * c.B);
    return Color.FromArgb(avg, avg, avg);
}
Stokke
  • 1,871
  • 2
  • 13
  • 18