How can I read a normal map efficent? - c#

I wrote a code that reads an image and calculates the normal vector for every pixel out of the RGB-Values. The Problem is even if I choose a 256x256 image c# will take too long to operate and sometimes it shuts down. Can someone show me another method or a different solution?
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Aufgabe17NormalMapping
{
public partial class Form1 : Form
{
public delegate void TextManagerDelegate(string text);
TextManagerDelegate TextHandler;
Bitmap img;
public Form1()
{
InitializeComponent();
TextHandler = new TextManagerDelegate(TextManager);
}
public void TextManager(string txt)
{
textBox1.AppendText(txt + Environment.NewLine);
}
public void RunProcess()
{
string filePath = #"C:\Users\USerName\Documents\Visual Studio 2017\Projects\Aufgabe17NormalMapping\images.jpg";
using (img = new Bitmap(filePath))
{
var height = img.Height;
var width = img.Width;
double[,] ArrayR = new double[width, height];
double[,] ArrayG = new double[width, height];
double[,] ArrayB = new double[width, height];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
Color pixel = img.GetPixel(i, j);
ArrayR[i, j] = (((double)Convert.ToDouble(pixel.R.ToString())) + 0.5) * 2;
ArrayG[i, j] = (((double)Convert.ToDouble(pixel.G.ToString())) + 0.5) * 2;
ArrayB[i, j] = (((double)Convert.ToDouble(pixel.B.ToString())) + 0.5) * 2;
Debug.WriteLine(ArrayR[i, j].ToString(), "Array R");
//Debug.Print(ArrayR[i, j].ToString(), "Array Rsdsd");
BeginInvoke(TextHandler, ArrayR[i, j].ToString());
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Task T = new Task(RunProcess);
T.Start();
}
}
}

Your code is really fast, it is the "reporting" that takes a long time. Remove the Debug.WriteLine and TextHandler and I got the following time (in debug mode)
ImgSize 532x1280
Lasted: 0:00:01,181845
Code snippet:
static void Main(string[] args)
{
var watch = Stopwatch.StartNew();
RunProcess();
Console.WriteLine($"Lasted: {watch.Elapsed.ToString("g")}");
}
public static void RunProcess()
{
var str = new StringBuilder();
string filePath = #"C:\Users\Wouter\Desktop\gamez.jpg";
using (var img = new Bitmap(filePath))
{
var height = img.Height;
var width = img.Width;
Console.WriteLine($"ImgSize {width}x{height}");
double[,] ArrayR = new double[width, height];
double[,] ArrayG = new double[width, height];
double[,] ArrayB = new double[width, height];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
Color pixel = img.GetPixel(i, j);
ArrayR[i, j] = (((double)Convert.ToDouble(pixel.R.ToString())) + 0.5) * 2;
ArrayG[i, j] = (((double)Convert.ToDouble(pixel.G.ToString())) + 0.5) * 2;
ArrayB[i, j] = (((double)Convert.ToDouble(pixel.B.ToString())) + 0.5) * 2;
str.AppendLine(ArrayR[i, j].ToString());
}
}
}
BeginInvoke(TextHandler, str.ToString());
}
Try working with a StringBuilder and once you've got the entire image processed, update the UI once.

Related

C# - 2d matrix - is guess left/right/up/down of point

Using a 2d array of buttons implemented and placed on a form.
Button[,] tmpButton = new Button[x, y];
private void DrawGrid()
{
int ButtonWidth = 48;
int ButtonHeight = 48;
int start_x = 88;
int start_y = 200;
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
tmpButton[i, j] = new Button();
tmpButton[i, j].Top = start_x + (i * ButtonHeight);
tmpButton[i, j].Left = start_y + (j * ButtonWidth);
tmpButton[i, j].Width = ButtonWidth;
tmpButton[i, j].Height = ButtonHeight;
tmpButton[i, j].Click += new EventHandler(BTN_Grid_Click);
this.Controls.Add(tmpButton[i, j]);
}
}
}
If a random location (x,y) is set true within the grid with the intention of guessing (by clicking on the surrounding grid buttons) it's location. If the location is !true it should return left right up down pointing to the random location we set earlier. If the true location is up and left, it should return whichever it is closest too.
What would be the best way to implement something like this?
This is getting close, but something I can't see is off a bit ...
public String GetDirection()
{
int xd = Guess.X - Clue.X;
int yd = Guess.Y - Clue.Y;
if(Math.Abs(xd) <= Math.Abs(yd))
return (xd <= 0) ? "Left" : "Right";
else
return (yd <= 0) ? "Down" : "Up";
}
Here is a visual representation of what is happening ...
Alright so you had most of it right however you made a easy mistake. When you create the buttons you're rendering from left to right then top to bottom which creates the height as the x position then the width as the y position. So when you go and correlate the guess to the correct position you forget that you did this and assume x is the width.
Here's my implementation which fixed this:
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;
namespace UpDownLeftRight {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
this.Load += new System.EventHandler(this.Form1_Load);
}
public int[] winner = new int[2];
public Button[,] tmpButton = new Button[10, 10];
private void Form1_Load(object sender, EventArgs e) {
Random r = new Random();
int ButtonWidth = 48;
int ButtonHeight = 48;
int start_x = 0;
int start_y = 0;
winner = new int[] { r.Next(0, 10), r.Next(0, 10) };
this.Size = new Size((ButtonWidth * 11), (ButtonHeight * 11));
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
tmpButton[i, j] = new Button();
tmpButton[i, j].Left = start_x + (i * ButtonWidth);
tmpButton[i, j].Top = start_y + (j * ButtonHeight);
tmpButton[i, j].Width = ButtonWidth;
tmpButton[i, j].Height = ButtonHeight;
tmpButton[i, j].Font = new Font(FontFamily.GenericMonospace, 17);
tmpButton[i, j].Click += new EventHandler(BTN_Grid_Click);
this.Controls.Add(tmpButton[i, j]);
}
}
}
public void BTN_Grid_Click(object o, EventArgs e) {
int[] guess = new int[2];
for (int i = 0; i != tmpButton.GetLength(1); i++) {
for (int j = 0; j != tmpButton.GetLength(0); j++) {
if (tmpButton[i, j] == o) {
guess = new int[] { i, j };
}
}
}
int xDist = guess[0] - winner[0];
int yDist = guess[1] - winner[1];
string possible = "˂˃˄˅";
if (xDist > 0) { possible = possible.Replace("˃", ""); }
if (xDist < 0) { possible = possible.Replace("˂", ""); }
if (xDist == 0) { possible = possible.Replace("˂", ""); possible = possible.Replace("˃", ""); }
if (yDist > 0) { possible = possible.Replace("˅", ""); }
if (yDist < 0) { possible = possible.Replace("˄", ""); }
if (yDist == 0) { possible = possible.Replace("˄", ""); possible = possible.Replace("˅", ""); }
((Button)o).Text = possible;
}
}
}

How to display large amounts of points(rectangles) in real time ? (visual C#)

I'm currently working on a project which is digitalization of analog radar. I have a PCI card which acquires data that I use. I need to do a PPI indicator, like on the picture radar PPI
But I have a problem: The data display is very slow. I'm currently displaying data point-by-point (if signal is detected it'll draw a small rectangle at the calculated position). The azimuth discrete is 0,1° so that's 3600 discretes of angles and the radius is 500 discretes, so that makes it 3600*500 = 1 800 000 points max. Which is a lot.
Here is the part of the code where display of data is done:
private void kreslenie()
{
for (int i = 0; i < bufferCH1.Length - 1; i++)
{
if (bufferCH0[i] > 4000)
{
if (azimutR >= 0 && azimutR <= Math.PI)
{
surX = (int)(sx + (i) * azimutX);
surY = (int)(sy - (i) * azimutY);
}
else
{
surX = (int)(sx - (i) * azimutX);
surY = (int)(sy - (i) * azimutY);
}
this.CreateGraphics().DrawRectangle(p, surX, surY, 1, 1);
}
}
}
Is there any other way to display such big amount of points in real-time (or near real-time)
One thing you could try is using a PictureBox control, and dynamically generating a Bitmap to display. You can do this by maintaining an array of the raw pixel data and updating it when information you want to display changes. Use the Bitmap.LockBits method to get a pointer to the raw image data, and then use Marshal.Copy to update it with the array of image data you are maintaining. Here is rough example that just randomly generates an image with points filled at a given location.
Edited:
To draw shapes you could just create a second array of image data for the background. You can create a Bitmap the same size as the other image, and draw to it using GDI. Next, save the background image as a byte array. When you generate your whole image, you first set it to the background image, and then draw your points over the background.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace PointDrawTest
{
public partial class Form1 : Form
{
public struct BoundingArea
{
public int x;
public int y;
public int width;
public int height;
}
public struct Point
{
public int x;
public int y;
}
int bytesPerPixel;
byte[] backgroundImageRgbData;
byte[] imageRgbData;
private Bitmap displayImage;
private BoundingArea area;
private List<Point> points = new List<Point>();
public Form1()
{
InitializeComponent();
LoadPoints();
}
private void LoadPoints()
{
this.points = new List<Point>();
this.area = new BoundingArea();
this.area.x = 0;
this.area.y = 0;
this.area.width = 1200;
this.area.height = 800;
displayImage = new Bitmap(this.area.width, this.area.height, PixelFormat.Format24bppRgb);
//There are three bytes per pixel in format PixelFormat.Format24bppRgb
bytesPerPixel = 3;
//Rgb byte data for the image
int rgbDataSize = this.area.width * this.area.height * bytesPerPixel;
imageRgbData = new byte[rgbDataSize];
GenerateRandomPoints();
GenerateBackgroundImage();
UpdateBitmap();
}
private void GenerateBackgroundImage()
{
Bitmap backgroundImage = new Bitmap(this.area.width, this.area.height, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(backgroundImage);
int gridSize = 40;
int rowCount = this.area.height / gridSize;
int columnCount = this.area.width / gridSize;
//Set background color to white
g.Clear(System.Drawing.Color.White);
int penWidth = 1;
Pen linePen = new Pen(System.Drawing.Color.Gray, penWidth);
//Draw horizontal lines
for (int i = 0; i < rowCount; i++)
{
float y = i * gridSize;
g.DrawLine(linePen, this.area.x, y, this.area.x + this.area.width, y);
}
//Draw vertical lines
for (int i = 0; i < columnCount; i++)
{
float x = i * gridSize;
g.DrawLine(linePen, x, this.area.y, x, this.area.y + this.area.height);
}
//Get rgb data from drawn background image and save it to array
var backgroundData = backgroundImage.LockBits(new Rectangle(this.area.x, this.area.y, this.area.width, this.area.height),
ImageLockMode.ReadWrite,
backgroundImage.PixelFormat);
IntPtr ptrFirstPixel = backgroundData.Scan0;
int rgbDataSize = this.area.width * this.area.height * bytesPerPixel;
backgroundImageRgbData = new byte[rgbDataSize];
Marshal.Copy(ptrFirstPixel, backgroundImageRgbData, 0, backgroundImageRgbData.Length);
backgroundImage.UnlockBits(backgroundData);
}
private void GenerateRandomPoints()
{
int pointCount = 100000;
var r = new Random();
for (int i = 0; i < pointCount; i++)
{
int pointX = r.Next(this.area.x, this.area.x + this.area.width);
int pointY = r.Next(this.area.y, this.area.y + this.area.height);
points.Add(new Point() { x = pointX, y = pointY });
}
}
private void UpdateBitmap()
{
var bmpData = this.displayImage.LockBits(new Rectangle(this.area.x, this.area.y, this.area.width, this.area.height),
ImageLockMode.ReadWrite,
this.displayImage.PixelFormat);
IntPtr ptrFirstPixel = bmpData.Scan0;
//Set image array to default background image
for (int i = 0; i < imageRgbData.Length; i++)
{
imageRgbData[i] = backgroundImageRgbData[i];
}
Color pixelColor = System.Drawing.Color.LightGreen;
for (int i = 0; i < this.points.Count; i++)
{
Point p = this.points[i];
int bitmapRgbIndex = (p.y * this.area.width + p.x) * bytesPerPixel;
//Apply color at a specific pixel
imageRgbData[bitmapRgbIndex] = pixelColor.B;
imageRgbData[bitmapRgbIndex + 1] = pixelColor.G;
imageRgbData[bitmapRgbIndex + 2] = pixelColor.R;
}
//Copy your bitmap byte array to the image
Marshal.Copy(imageRgbData, 0, ptrFirstPixel, imageRgbData.Length);
this.displayImage.UnlockBits(bmpData);
pbDisplay.Image = this.displayImage;
}
}
}

argument out of range exception in a memory puzzle game

I'm following along a course on udemy which is for free it's a memory game (https://www.udemy.com/xamarin-native-ios-memory-game-csharp/learn/v4/overview)
Now with the randomizer method i get a new problem with the same out of range error
using System;
using System.Collections;
using System.Collections.Generic;
using UIKit;
namespace iOSMemoryGame
{
public partial class ViewController : UIViewController
{
#region vars
List<String> imgArr = new List<String>();
float gameViewWidth;
int gridSize = 6;
ArrayList tilesArr = new ArrayList();
ArrayList coordsArr = new ArrayList();
#endregion
public ViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
// make sure Game View is Laid Out
gameView.LayoutIfNeeded();
gameViewWidth = (float)gameView.Frame.Size.Width;
// let's load all of our images into an array
for (int i = 1; i <= 18; i++)
{
imgArr.Add("img_" + i.ToString() + ".png");
}
// let's make a call to tileMaker
tileMaker();
// let's call the randomizer
randomizer();
}
private void randomizer()
{
// we are gonna go through our tiles in ORDER
// and we are gonna assign a new center to them RANDOMLY
foreach (UIView any in tilesArr)
{
// UIImageView thisTile = (UIImageView)tilesArr[i];
Random myRand = new Random();
int randomIndex = myRand.Next(0, coordsArr.Count);
CoreGraphics.CGPoint newRandCenter = (CoreGraphics.CGPoint)coordsArr[randomIndex];
any.Center = newRandCenter;
coordsArr.RemoveAt(randomIndex);
}
}
private void tileMaker()
{
float tileWidth = gameViewWidth / gridSize;
float xCenter = tileWidth / 2;
float yCenter = tileWidth / 2;
int imgCounter = 0;
for (int h = 0; h < gridSize; h++)
{
for (int v = 0; v < gridSize; v++)
{
UIImageView tileImgView = new UIImageView();
CoreGraphics.CGPoint newCenter = new CoreGraphics.CGPoint(xCenter, yCenter);
tileImgView.Frame = new CoreGraphics.CGRect(0, 0, tileWidth - 5, tileWidth - 5);
String imgName = imgArr[imgCounter];
tileImgView.Image = new UIImage(imgName);
tileImgView.Center = newCenter;
// user CAN interact with this image view
tileImgView.UserInteractionEnabled = true;
// adding the new image view to the array
tilesArr.Add(tileImgView);
gameView.AddSubview(tileImgView);
xCenter = xCenter + tileWidth;
imgCounter++;
if (imgCounter == gridSize * gridSize / 2)
{
imgCounter = 0;
}
}
xCenter = tileWidth / 2;
yCenter = yCenter + tileWidth;
}
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
partial void Rst4Button_TouchUpInside(UIButton sender)
{
throw new NotImplementedException();
}
partial void Rst6Button_TouchUpInside(UIButton sender)
{
throw new NotImplementedException();
}
}
}
Something is wrong with the randomizer method but i dont know what.
it gives me again a out of range error.
without the randomizer method it works fine
This line
for (int i = 1; i < 18; i++)
creates 17 images, not 18 as expected by the following loops.
// 0-5 = 6 loops
for (int h = 0; h < gridSize; h++)
{
// 0-5 = 6 loops (h*v=18)
for (int v = 0; v < gridSize; v++)
{
....
You need to write
for (int i = 0; i < 18; i++)
imgArr.Add("img_" + (i+1).ToString() + ".png");

Massive for loop on a image file, frames dipping around 7 fps, I need that to be higher

I am currently trying new techniques for going through every pixel on a image and doing some minor process for each. Here is my active code:
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;
}
}
}
}
I need to get the FPS to around, say, 90 fps. How can I do this? Do I need to use something other than C#? The current fps is about 7.
EDIT 1
Stack overflow edited out some of my text.. weird...
Here is the real unsafe code.
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;
}
}
}
Edit 2
Wow... it did it again... I am replacing the less than symbols with (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;
}
}
}
Edit 3
Tried changing the format to PixelFormat.Format32bppPArgb. Didn't work. Got this:
Click to view image
Edit 4
Plenty of changes to the code. Here is the current code:
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;
}
}
}
}
Unfortunately, this only gets me 5 fps. I am starting to believe that painting on a bitmap then putting it onto the screen is not the way to quickly render games. Does anybody know another way?
Considering the code you're benchmarking:
rnd is useless (wrong copy/paste?)
you're doing way too much multiplication, consider using:
Code:
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;
}
}
This will reduce multiplication with y from Height*Width*3 to Height and reduce multiplication with x by 3.

Drawing images in c# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to draw an image in my Windows Form Application. I drew instead of the picture some rectangles but I want to replace them somehow with a certain image.
I added the whole code and the problem is in the draw function. Can anybody help?
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.Threading;
using System.Drawing.Drawing2D;
using Microsoft.Win32;
namespace kiralyno
{
public partial class Form2 : Form
{
public static int p = 1;
public static int o = 1;
public float[] x1 = new float[80000];
public float[] y1 = new float[80000];
public string hely = " ";
public int db = 0;
public int[] v = new int[80000];
public static string a;
public string s = " ";
public static int n = Form1.n;
public float x = 0, y = 0, w = 450 / n, h = 450 / n;
public int helyes(int i, int k)
{
for (int j = 1; j <= k - 1; j++)
if ((v[j] == i) || (Math.Abs(k - j) == Math.Abs(i - v[j])))
return 0;
return 1;
}
public void kiir(int k)
{
for (int j = 1; j <= k; j++)
{
s += Convert.ToString(v[j]);
if (j != n) s += " ";
}
a = s;
megoldas.Items.Add(a);
s = "";
a = "";
}
public void back(int k)
{
for (int i = 1; i <= n; i++)
{
if (helyes(i, k) == 1)
{
v[k] = i;
if (k == n)
{
kiir(k);
draw();
Thread.Sleep(500);
sakktabla(0, 0, w, h);
db++;
}
else back(k + 1);
}
}
}
public void draw()
{
// Image newImage = Image.FromFile("D:/Akos/Visual/Projects/kiralyno/kir.png");
Graphics g = panel1.CreateGraphics();
for (int m = 1; m <= n; m++)
{
g.DrawRectangle(new Pen(Brushes.Blue), x1[v[m]], y1[m], w, h);
g.FillRectangle(Brushes.Blue, x1[v[m]], y1[m], w, h);
Thread.Sleep(200);
}
}
public Form2()
{
InitializeComponent();
}
public void sakktabla(float x, float y, float w, float h)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if ((i + j) % 2 == 0)
{
Graphics g = panel1.CreateGraphics();
g.DrawRectangle(new Pen(Brushes.Black), x, y, w, h);
g.FillRectangle(Brushes.Black, x, y, w, h);
x1[p] = x;
x = x + 450 / n;
}
else
{
Graphics g = panel1.CreateGraphics();
g.DrawRectangle(new Pen(Brushes.White), x, y, w, h);
g.FillRectangle(Brushes.White, x, y, w, h);
x1[p] = x;
x = x + 450 / n;
}
p++;
}
y1[o] = y;
for (int m = 1; m <= n; m++)
{
y1[n * m + o] = y1[o];
}
o++;
y = y + 450 / n;
x = 0;
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
sakktabla(0, 0, w, h);
}
private void Form2_Deactivate(object sender, EventArgs e)
{
Application.Exit();
}
private void megoldas_Click(object sender, EventArgs e)
{
label1.Text = "";
back(1);
if (db == 0) megoldas.Items.Add("Nincs megoldas!");
string c = Convert.ToString(db);
megoldas.Items.Add(c+" db megoldas van");
megoldas.Enabled = false;
}
private void label1_Click(object sender, EventArgs e)
{
label1.Text = "";
back(1);
if (db == 0) megoldas.Items.Add("Nincs megoldas!");
string c = Convert.ToString(db);
megoldas.Items.Add(c + " db megoldas van");
megoldas.Enabled = false;
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
}
}
Source: http://msdn.microsoft.com/en-us/library/yws82c40%28v=vs.110%29.aspx
private void DrawImageRect(PaintEventArgs e)
{
// Create image.
Image newImage = Image.FromFile("SampImag.jpg");
// Create rectangle for displaying image.
Rectangle destRect = new Rectangle(100, 100, 450, 150);
// Draw image to screen.
e.Graphics.DrawImage(newImage, destRect);
}
If you really need to draw it yourself, use: DrawImage.
In general it's usually easier to use a PictureBox, though.

Categories