我目前正在尝试新技术来浏览图像上的每个像素并为每个像素执行一些小的处理。这是我的有效代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace ImageProcessingExmp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Timer timer = new Timer();
private void Form1_Load(object sender, EventArgs e)
{
timer.Tick += ChangeColor;
timer.Interval = 1;
timer.Start();
pictureBox1.Width = this.Width;
pictureBox1.Height = this.Height;
pictureBox1.Left = 0;
pictureBox1.Top = 0;
this.WindowState = FormWindowState.Maximized;
}
int timerinc = 0;
public void ChangeColor(object sender, EventArgs e)
{
if (timerinc>=240)
{
timer.Stop();
}
timerinc+=10;
Bitmap bmp = (Bitmap)new Bitmap(this.Width,this.Height);
Benchmark.Start();
///////////////////////////////////////////////////////////////////////////////
// Get the area to be painted
Rectangle areaToPaint = new Rectangle();
BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = data.Stride;
Random rnd = new Random(DateTime.Now.Millisecond);
unsafe
{
byte* ptr = (byte*)data.Scan0;
// Check this is not a null area
// Go through the draw area and set the pixels as they should be
for (int y = 0; y < bmp.Height; y++)
{
for (int x = 0; x < bmp.Width; x++)
{
// layer.GetBitmap().SetPixel(x, y, m_colour);
byte x2 = Convert.ToByte(x > 255 ? 0 : x);
byte y2 = Convert.ToByte(y > 255 ? 0 : y);
ptr[(x * 3) + y * stride] = x2;
ptr[(x * 3) + y * stride + 1] = y2;
ptr[(x * 3) + y * stride + 2] = 255;
}
}
}
bmp.UnlockBits(data);
/////////////////////////////////////////////////////////////////////////////////
Benchmark.End();
double seconds = Benchmark.GetSeconds();
//MessageBox.Show(seconds.ToString());
richTextBox1.Text += seconds.ToString()+'\n' ;
richTextBox2.Text += DateTime.Now.Second.ToString()+'\n';
pictureBox1.Image= bmp;
String[] lines = richTextBox1.Text.Split('\n');
double avg = 0;
double sum = 0;
double num = 0;
foreach (var line in lines)
{
// MessageBox.Show(line);
double tet = 0;
Double.TryParse(line, out tet);
sum += tet;
num++;
}
avg = sum / num;
label1.Text = "fps = " + (1/avg).ToString();
}
public class Benchmark
{
private static DateTime startDate = DateTime.MinValue;
private static DateTime endDate = DateTime.MinValue;
public static TimeSpan Span { get { return endDate.Subtract(startDate); } }
public static void Start() { startDate = DateTime.Now; }
public static void End() { endDate = DateTime.Now; }
public static double GetSeconds()
{
if (endDate == DateTime.MinValue) return 0.0;
else return Span.TotalSeconds;
}
}
}
}
我需要将FPS提升至90 fps左右。我怎样才能做到这一点?我需要使用C#以外的东西吗?目前的fps约为7。
编辑1 堆栈溢出编辑出我的一些文字..很奇怪...... 这是真正不安全的代码。
unsafe
{
byte* ptr = (byte*)data.Scan0;
// Check this is not a null area
// Go through the draw area and set the pixels as they should be
for (int y = 0; y< bmp.Height; y++)
{
for (int x = 0; x < bmp.Width; x++)
{
// layer.GetBitmap().SetPixel(x, y, m_colour);
byte x2 = Convert.ToByte(x > 255 ? 0 : x);
byte y2 = Convert.ToByte(y > 255 ? 0 : y);
ptr[(x * 3) + y * stride] = x2;
ptr[(x * 3) + y * stride + 1] = y2;
ptr[(x * 3) + y * stride + 2] = 255;
}
}
}
编辑2 哇......它又做了......我用(LESSTHAN)替换少于符号
unsafe
{
byte* ptr = (byte*)data.Scan0;
// Check this is not a null area
// Go through the draw area and set the pixels as they should be
for (int y = 0; y < bmp.Height; y++)
{
for (int x = 0; x < bmp.Width; x++)
{
// layer.GetBitmap().SetPixel(x, y, m_colour);
byte x2 = Convert.ToByte(x > 255 ? 0 : x);
byte y2 = Convert.ToByte(y > 255 ? 0 : y);
ptr[(x * 3) + y * stride] = x2;
ptr[(x * 3) + y * stride + 1] = y2;
ptr[(x * 3) + y * stride + 2] = 255;
}
}
}
编辑3 尝试将格式更改为PixelFormat.Format32bppPArgb。没有工作。明白啦: Click to view image
编辑4 对代码进行了大量更改。这是当前的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace ImageProcessingExmp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Timer timer = new Timer();
private void Form1_Load(object sender, EventArgs e)
{
timer.Tick += ChangeColor;
timer.Interval = 1;
timer.Start();
pictureBox1.Width = this.Width;
pictureBox1.Height = this.Height;
pictureBox1.Left = 0;
pictureBox1.Top = 0;
this.WindowState = FormWindowState.Maximized;
bmp=(Bitmap)new Bitmap(this.Width, this.Height);
}
int timerinc = 0;
int stride;
Bitmap bmp;
BitmapData data;
public void ChangeColor(object sender, EventArgs e)
{
timerinc+=10;
Benchmark.Start();
///////////////////////////////////////////////////////////////////////////////
data= bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
stride = data.Stride;
unsafe
{
byte* ptr = (byte*)data.Scan0;
// Check this is not a null area
// Go through the draw area and set the pixels as they should be
for (int y = 0; y < bmp.Height; y++)
{
int yTimeStride = y * stride;
byte y2 = (byte)(y > 255 ? 0 : y);
for (int x = 0; x < bmp.Width; x++)
{
int addressToAssign = (x * 3) + yTimeStride;
byte x2 = (byte)(x > 255 ? 0 : x);
ptr[addressToAssign] = x2;
ptr[addressToAssign + 1] = y2;
ptr[addressToAssign + 2] = x2;
}
}
}
bmp.UnlockBits(data);
/////////////////////////////////////////////////////////////////////////////////
Benchmark.End();
double seconds = Benchmark.GetSeconds();
//MessageBox.Show(seconds.ToString());
richTextBox1.Text += seconds.ToString()+'\n' ;
richTextBox2.Text += DateTime.Now.Second.ToString()+'\n';
pictureBox1.Image= bmp;
String[] lines = richTextBox1.Text.Split('\n');
double avg = 0;
double sum = 0;
double num = 0;
foreach (var line in lines)
{
// MessageBox.Show(line);
double tet = 0;
Double.TryParse(line, out tet);
sum += tet;
num++;
}
avg = sum / num;
label1.Text = "fps = " + (1/avg).ToString();
tst1.Add(1/avg*20);
if (timerinc >= 500)
{
timer.Stop();
Bitmap bmp2 = new Bitmap(pictureBox2.Width,pictureBox2.Height);
data = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
stride = data.Stride;
unsafe
{
byte* ptr = (byte*)data.Scan0;
// Check this is not a null area
// Go through the draw area and set the pixels as they should be
for (int x = 0; x < tst1.Count; x++)
{
for (int y = 0; y < (int)tst1[x]; y++)
{
//MessageBox.Show(x.ToString());
if (y<bmp2.Height)
{
ptr[(x * 3) + (int)y * stride] = 255;//b
ptr[(x * 3) + (int)y * stride + 1] =0;//g
ptr[(x * 3) + (int)y * stride + 2] = 255;//r
}
}
}
}
bmp2.UnlockBits(data);
pictureBox2.Image = bmp2;
}
}
public List<double> tst1 = new List<double>();
public class Benchmark
{
private static DateTime startDate = DateTime.MinValue;
private static DateTime endDate = DateTime.MinValue;
public static TimeSpan Span { get { return endDate.Subtract(startDate); } }
public static void Start() { startDate = DateTime.Now; }
public static void End() { endDate = DateTime.Now; }
public static double GetSeconds()
{
if (endDate == DateTime.MinValue) return 0.0;
else return Span.TotalSeconds;
}
}
}
}
不幸的是,这只能让我获得5 fps。我开始相信在位图上绘画然后将它放到屏幕上并不是快速渲染游戏的方法。有人知道另一种方式吗?
答案 0 :(得分:0)
考虑您正在进行基准测试的代码:
代码:
for (int y = 0; y < bmp.Height; y++)
{
int yTimeStride = y * stride;
byte y2 = Convert.ToByte(y > 255 ? 0 : y);
for (int x = 0; x < bmp.Width; x++)
{
int addressToAssign = (x * 3) + yTimeStride;
byte x2 = Convert.ToByte(x > 255 ? 0 : x);
ptr[addressToAssign] = x2;
ptr[addressToAssign + 1] = y2;
ptr[addressToAssign + 2] = 255;
}
}
这会减少y
从Height*Width*3
到Height
的乘法,并将x
乘以3减少。