GetPixel,SetPixel和DrawImage对我来说效果不佳

时间:2011-01-21 20:11:05

标签: c# graphics bitmap

我试图创建一个简单的程序,用给定的图像执行一些简单的操作。 出于某种原因,它仅适用于第一次(启动应用程序时):

//伪代码

Bitmap im=Bitmap.FromFile("D:\\x.BMP");
Color [,] ColorArray=new [im.Width,im.Height];
private override voide OnPaint(EventArgs e)
{

  for(int X=0;X<im.Width;X++)
  {
      for(int Y=0;Y<im.Height;Y++)
      {
        ColorArray[X,Y]=im.GetPixel[X,Y];
      }

  }
  for(int X=0;X<im.Width;X++)
  {
      for(int Y=0;Y<im.Height;Y++)
      {
        Color c=ColorArray[X,Y];
        ...
        //some code that adds 100 to R,G,B
        im.SetPixel(X,Y,c);
      }

  }


  e.Graphics.DrawImage(im);
}

2 个答案:

答案 0 :(得分:0)

<强> [编辑]

我修改了示例代码。对于以前的版本,可能很难看到从一次迭代到下一次迭代的差异(特别是我用于测试的bmp)。这个允许您通过按Num Pad上的1,2或3逐渐更改颜色。正如其他人所提到的,SetPixel / GetPixel很慢,因此每个KeyUp事件确实需要一些时间才能运行。

这对我来说很好。

创建一个新的Windows窗体项目。删除此代码。确保您有“x.bmp”可用。每次在数字键盘上按1,2或3(您可能需要打开Num Lock)时,位图的颜色会略有变化:

  public partial class Form1 : Form
  {
    Bitmap bm;
    Color [,] colors;

    public Form1()
    {
      bm = (Bitmap)Bitmap.FromFile("x.bmp");
      colors = new Color[bm.Width, bm.Height];

      InitializeComponent();
    }

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
      e.Graphics.DrawImage(bm,new Point(0,0));
    }

    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
      //Change the colors a little bit on each KeyUp.
      //On NumPad1, change red.
      //On NumPad2, change green.
      //On NumPad3, change blue.
      //Mod with 256 to ensure a value between 0 and 255.
      int rInc = 0;
      int gInc = 0;
      int bInc = 0;

      switch (e.KeyCode)
      {
        case Keys.NumPad1:
          rInc = 20;
          break;
        case Keys.NumPad2:
          gInc = 20;
          break;
        case Keys.NumPad3:
          bInc = 20;
          break;
        default:
          break;
      }

      for (int x = 0; x < bm.Width; x++)
      {
        for (int y = 0; y < bm.Height; y++)
        {
          colors[x, y] = bm.GetPixel(x, y);
        }
      }

      for (int x = 0; x < bm.Width; x++)
      {
        for (int y = 0; y < bm.Height; y++)
        {
          Color c = colors[x, y];

          int r = (c.R + rInc) % 256;
          int g = (c.G + gInc) % 256;
          int b = (c.B + bInc) % 256;

          c = Color.FromArgb(255, r, g, b);
          bm.SetPixel(x, y, c);
        }
      }

      Invalidate();
    }

  }

它并不是非常复杂,但是它使用与您的伪代码非常匹配的实际代码执行的操作。

答案 1 :(得分:0)

您可以在循环像素时提高性能,排列循环以在内循环中以行顺序(x坐标)访问像素。这最符合图像内存布局,因此它将提高CPU缓存性能

for ( y = 0, y < bm.Height; y++)
{
    ...

    for ( x = 0, x < bm.Width; x++)
    {
        ...
    }
}