Draw color to every pixel in picturebox

15,304

Solution 1

Each time your timer ticks you want to draw another pixel with (different?) color, right?

What you need to do is declare current x and y coordinates outside of timer1_Tick method and increase their values accordingly every time you draw something.

To immediately see the results you should also call pictureBox1.Refresh() inside timer1_Tick(). Here's my quick solution to draw 200x200 bitmap with a pattern similar to this: All 24-bit RGB colors.

public partial class Form1 : Form
{
    private int bitmapWidth = 200;
    private int bitmapHeight = 200;
    private int currentX = 0;
    private int currentY = 0;

    public Form1()
    {
        InitializeComponent();
        pictureBox1.Image = new Bitmap(bitmapWidth, bitmapHeight);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (timer1.Enabled)
        {
            timer1.Stop();
        }
        else
        {
            timer1.Start();
        }
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        double partWidth = (bitmapWidth / (double)16);
        int r = (int)(255 * currentX / partWidth) % 256;
        int g = (int)(255 * (currentY % partWidth) / partWidth) % 256;
        int b = (int)(Math.Floor(currentX / partWidth) + Math.Floor(currentY / partWidth) * 16);

        ((Bitmap)pictureBox1.Image).SetPixel(currentX, currentY, Color.FromArgb(r, g, b));
        pictureBox1.Refresh();
        if (currentX < bitmapWidth - 1)
        {
            currentX++;
        }
        else if (currentY < bitmapHeight - 1)
        {
            currentX = 0;
            currentY++;
        }
        else
        {
            timer1.Stop();
        }
    }
}

You can alter colors produced by calculating them off of currentX, currentY and partWidth. Note: I assumed you draw a square bitmap. Drawing to a rectangle would require some more work. Same thing applies to different sizes.

Solution 2

Your code sets each pixel to the same color.

If, as you wrote you want to watch every color is being be painted you should make two changes:

  • Make the Picturebox large enough, ie 256x256 pixels inside (RGB color space is 256x256x256)
  • Draw every pixel with a different color

Here is an example:

int blue = 0;
private void timer1_Tick(object sender, EventArgs e)
{
    // either dispose of the old Bitmap or simply reuse it!
    if (pictureBox1.Image != null) pictureBox1.Image.Dispose();
    pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
    int x, y;
    blue = (blue+1) % 256;
    Text = blue + "";
    for (y = 0; y < 256; y++)
    {
        for (x = 0; x < 256; x++)
        {
            ((Bitmap)pictureBox1.Image).SetPixel(x, y, Color.FromArgb(y, x, blue));
        }
    }
    pictureBox1.Refresh();
}

Note that is uses a Form level variable for the blue value and increments it in the Tick event.

This will draw each pixel in a different color for one value of Blue and will iterate over all values for blue. So after 256 iteration you will ahve seen ever RGB color there is.

If you want to watch each pixel being set, you would move x and y to form level and increment them in the Tick like this:

x = x + 1;
if (x >= 256) { x = 0; y = y + 1;}
if (y >= 256) { y = 0; x = 0; blue = blue + 1;}
((Bitmap)pictureBox1.Image).SetPixel(x, y, Color.FromArgb(x, y, blue));

instead of the double loop. For this to work you need to move the

pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);

line to e.g. the Form constructor or the Form_Load event!

It will work but it will be slow ;-)

To reuse the Bitmap simply create it outside of the Tick, maybe in the constructor!

If instead you want all pixels to have the same Color you should not set the pixels one by one. Instead you can create a Graphics for the Bitmap and use it to Clear all pixels to one Color:

    int argb = 255 << 24;  // we want to start with fully opaque colors!
    private void timer1_Tick(object sender, EventArgs e)
    {
       // I have move the Bitmap creation to the Form contructor
       argb += 1;
       using (Graphics G = Graphics.FromImage(pictureBox1.Image))
       {
           G.Clear(Color.FromArgb(argb));
       }

       pictureBox1.Refresh();

Or you could simply draw to the surface of the control:

    private void timer1_Tick(object sender, EventArgs e)
    {
       pictureBox1.Invalidate();
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        argb += 1;
        e.Graphics.Clear(Color.FromArgb(argb));
    }

This would be the fastest, except that of course the Tick will really determine the speed, unless you enlarge the size of the control a lot..

Note the Color space is a 3D space, so there is no obvious path to go through each color in the nicest way..

Small final note: If your PictureBox has a Border you should set the Image to the (inner) CientSize not to the (outer) Size!

Size cs = pictureBox1.ClientSize;
pictureBox1.Image = new Bitmap(cs.Width, cs.Height); 
Share:
15,304
usr6969
Author by

usr6969

Updated on June 04, 2022

Comments

  • usr6969
    usr6969 almost 2 years

    Can someone help me: I want to draw colors every pixel to picturebox

    This is what I have done so far:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication25
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }
    
        private void timer1_Tick(object sender, EventArgs e)
        {
            pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
            int x, y;
            for (y = 0; y < 200; y++)
            {
                for (x = 0; x < 200; x++)
                {
                    ((Bitmap)pictureBox1.Image).SetPixel(x, y, Color.FromArgb(255, 255, 0));
                }
            }
        } 
    
    }
    }
    

    I have added a Timer so i can see the progress in drawing every pixel.

    The problem the code do draw in memory - delay - then put in picture box

    I want draw color every y = 0 and x = 0 to 200 , y =1 x = 0 to 200, y=2 x=0 to 200 etc

  • usr6969
    usr6969 almost 9 years
    yay great this is what i mean
  • usr6969
    usr6969 almost 9 years
    how to make the draw speed more quickly?? i alredy set timer to 1 but it's not enough