为图片框中的每个像素绘制颜色

时间:2015-04-29 23:59:40

标签: c# draw picturebox progress

有人可以帮助我:我想将每个像素的颜色绘制到图片框

这是我到目前为止所做的:

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));
            }
        }
    } 

}
}

我添加了一个Timer,因此我可以看到绘制每个像素的进度。

代码在内存中绘制的问题 - 延迟 - 然后放入图片框

我想要每个y = 0和x = 0到200,y = 1 x = 0到200,y = 2 x = 0到200等绘制颜色

2 个答案:

答案 0 :(得分:1)

每次你的计时器滴答时,你想用另一种颜色绘制另一个像素,对吧?

您需要做的是在timer1_Tick方法之外声明当前的x和y坐标,并在每次绘制时相应地增加它们的值。

要立即看到结果,您还应该在timer1_Tick()中调用pictureBox1.Refresh()。 这是我使用类似于此的模式绘制200x200位图的快速解决方案: 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();
        }
    }
}

您可以通过从currentX,currentY和partWidth计算它们来改变颜色。 注意:我假设您绘制一个方形位图。绘制成矩形需要更多的工作。同样的事情适用于不同的尺寸。

答案 1 :(得分:0)

您的代码将每个像素设置为相同的颜色。

如果你在写作时想要观看每种颜色的绘画,你应该进行两处修改:

  • 使Picturebox足够大,即内部256x256像素 (RGB色彩空间为256x256x256)
  • 使用不同颜色绘制每个像素

以下是一个例子:

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();
}

请注意,它使用Form级别变量作为蓝色值,并在Tick事件中递增。

这将为每个蓝色值绘制不同颜色的每个像素,并迭代所有蓝色值。所以经过256次迭代后你会看到RGB颜色。

如果你想观察每个像素的设置,你可以将x和y移动到表格级别,并在Tick中递增它们,如下所示:

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));

而不是双循环。为此,需要移动

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

到例如Form构造函数或Form_Load事件!

它会起作用,但会很慢; - )

要重复使用Bitmap,只需在Tick之外创建它,也许在构造函数中创建它!

如果您希望所有像素具有相同的Color,则不应逐个设置像素。相反,您可以为Graphics创建Bitmap并将其用于Clear所有像素到一种颜色:

    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();

或者您可以简单地绘制到控件的表面:

    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));
    }

这将是最快的,除了当然Tick会真正决定速度,除非你大大扩大控件的大小..

请注意,色彩空间是一个3D空间,所以没有明显的路径以最好的方式遍历每种颜色。

小决赛备注:如果您的PictureBoxBorder,则应将Image设置为(内部)CientSize而不是(外部)Size }!

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