【问题标题】:Draw color to every pixel in picturebox为图片框中的每个像素绘制颜色
【发布时间】:2015-04-29 23:59:39
【问题描述】:

谁能帮帮我:我想为图片框的每个像素绘制颜色

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

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

}
}

我已经添加了一个计时器,所以我可以看到绘制每个像素的进度。

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

我想在每个 y = 0 和 x = 0 到 200、y =1 x = 0 到 200、y=2 x=0 到 200 等处绘制颜色

【问题讨论】:

  • 一个简单的解决方案是三个嵌套循环来生成所有可能值的范围。这是 O(n^3),但 800 万次迭代还不错。
  • 实际上可以生成 (R,B,G) = (0..200, 0..200, 0..200) 之间的每种颜色。我建议了一种方法。

标签: c# draw picturebox progress


【解决方案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,但这还不够
【解决方案2】:

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

如果,正如您所写的,您想查看正在绘制的每种颜色,您应该进行两项更改:

  • 使图片框足够大,即内部为 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 来形成 level 并在 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,则不应逐个设置像素。相反,您可以为Bitmap 创建一个Graphics 并将其用于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 空间,因此没有明显的路径可以以最好的方式遍历每种颜色。..

最后的小提示:如果您的PictureBox 有一个Border,您应该将Image 设置为(内部)CientSize 而不是(外部)Size

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

【讨论】:

    猜你喜欢
    • 2019-03-18
    • 2010-11-09
    • 1970-01-01
    • 2019-07-24
    • 2017-09-20
    • 2016-05-10
    • 1970-01-01
    • 1970-01-01
    • 2015-03-29
    相关资源
    最近更新 更多