EDN Admin
Well-known member
Hello all!
Im a newbie in C# and .Net programming and need help. Im trying to understand how backgroundworkers, bitmap and lockbits method work together. In particular here is an example where a radio button pressed invokes background worker that generates random values and updates a bmp in a picturebox. The aim is to have a continuous generation until the button is clicked again.
The reason is that according to examples on this forum backgroundworkers are the easiest way to implement threading and avoiding the button to be "stuck" while the callback executes.
Im following examples found on this forum for generating random values to insert into a bitmap . That works fine until I place it in the background worker. At the moment no image is shown and the bmp value in backgroundworker1_progresschanged is empty (Im evidently not passing it out).
To add a level of complication, in the future I will need the bmp to have size set using the UI.
To follow is the relevant part of the code.
Can anyone suggest me where I am wrong?
I thank you in advance for all your 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;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
Random _rnd = new Random();
Byte[] pixels = new Byte[10000];
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
}
public Bitmap bmp;
Form2 new_form;
int stopper_value;
private void button1_Click(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
}
private void button2_Paint(object sender, PaintEventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
new_form = new Form2();
//bmp= new Bitmap(
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked == true)
{
// Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync();
//}
//while (checkBox1.Checked == true);
//do loop
}
else
{
// Cancel the asynchronous operation.
backgroundWorker1.CancelAsync();
MessageBox.Show("stopped");
//stop
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
byte[,] myMatrix = new byte[200, 200];
//fill with random (color-) values
for (int y = 0; y < myMatrix.GetLength(1); y++)
{
for (int x = 0; x < myMatrix.GetLength(0); x++)
{
myMatrix[x, y] = (byte)_rnd.Next(256);
}
}
//now we have to convert the 2 dimensional array into a one dimensional byte-array for use with 32bpp bitmaps
byte[] pixels = new byte[myMatrix.GetLength(0) * 4 * myMatrix.GetLength(1)];
for (int y = 0; y < myMatrix.GetLength(1); y++)
{
for (int x = 0; x < myMatrix.GetLength(0); x++)
{
for (int j = 0; j < 4; j++)
{
if (j < 3)
pixels[y * myMatrix.GetLength(0) * 4 + x * 4 + j] = myMatrix[x, y];
else
pixels[y * myMatrix.GetLength(0) * 4 + x * 4 + j] = 255;
}
}
}
//create a new Bitmap
Bitmap bmp = new Bitmap(myMatrix.GetLength(0), myMatrix.GetLength(1));//,System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);
//bmp.Palette=System.Drawing.Imaging.ColorMap
//lock it to get the BitmapData Object
System.Drawing.Imaging.BitmapData bmData =
bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
//copy the bytes
System.Runtime.InteropServices.Marshal.Copy(pixels, 0, bmData.Scan0, bmData.Stride * bmData.Height);
//never forget to unlock the bitmap
bmp.UnlockBits(bmData);
for (int i = 0; i < 1000; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
for (int y = 0; y < myMatrix.GetLength(1); y++)
{
for (int x = 0; x < myMatrix.GetLength(0); x++)
{
myMatrix[x, y] = (byte)_rnd.Next(256);
}
}
//now we have to convert the 2 dimensional array into a one dimensional byte-array
//byte[] pixels = new byte[myMatrix.GetLength(0) * myMatrix.GetLength(1)];
for (int y = 0; y < myMatrix.GetLength(1); y++)
{
for (int x = 0; x < myMatrix.GetLength(0); x++)
{
for (int j = 0; j < 4; j++)
{
if (j < 3)
pixels[y * myMatrix.GetLength(0) * 4 + x * 4 + j] = myMatrix[x, y];
else
pixels[y * myMatrix.GetLength(0) * 4 + x * 4 + j] = 255;
}
}
}
bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
//copy the bytes
System.Runtime.InteropServices.Marshal.Copy(pixels, 0, bmData.Scan0, bmData.Stride * bmData.Height);
//never forget to unlock the bitmap
bmp.UnlockBits(bmData);
worker.ReportProgress(i );
}
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
pictureBox1.Image = bmp;
pictureBox1.Refresh();
resultLabel.Text = (e.ProgressPercentage.ToString() + "frames");
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
resultLabel.Text = "Canceled!";
}
else if (e.Error != null)
{
resultLabel.Text = "Error: " + e.Error.Message;
}
else
{
resultLabel.Text = "Done!";
}
}
}
}
View the full article
Im a newbie in C# and .Net programming and need help. Im trying to understand how backgroundworkers, bitmap and lockbits method work together. In particular here is an example where a radio button pressed invokes background worker that generates random values and updates a bmp in a picturebox. The aim is to have a continuous generation until the button is clicked again.
The reason is that according to examples on this forum backgroundworkers are the easiest way to implement threading and avoiding the button to be "stuck" while the callback executes.
Im following examples found on this forum for generating random values to insert into a bitmap . That works fine until I place it in the background worker. At the moment no image is shown and the bmp value in backgroundworker1_progresschanged is empty (Im evidently not passing it out).
To add a level of complication, in the future I will need the bmp to have size set using the UI.
To follow is the relevant part of the code.
Can anyone suggest me where I am wrong?
I thank you in advance for all your 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;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
Random _rnd = new Random();
Byte[] pixels = new Byte[10000];
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
}
public Bitmap bmp;
Form2 new_form;
int stopper_value;
private void button1_Click(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
}
private void button2_Paint(object sender, PaintEventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
new_form = new Form2();
//bmp= new Bitmap(
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked == true)
{
// Start the asynchronous operation.
backgroundWorker1.RunWorkerAsync();
//}
//while (checkBox1.Checked == true);
//do loop
}
else
{
// Cancel the asynchronous operation.
backgroundWorker1.CancelAsync();
MessageBox.Show("stopped");
//stop
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
byte[,] myMatrix = new byte[200, 200];
//fill with random (color-) values
for (int y = 0; y < myMatrix.GetLength(1); y++)
{
for (int x = 0; x < myMatrix.GetLength(0); x++)
{
myMatrix[x, y] = (byte)_rnd.Next(256);
}
}
//now we have to convert the 2 dimensional array into a one dimensional byte-array for use with 32bpp bitmaps
byte[] pixels = new byte[myMatrix.GetLength(0) * 4 * myMatrix.GetLength(1)];
for (int y = 0; y < myMatrix.GetLength(1); y++)
{
for (int x = 0; x < myMatrix.GetLength(0); x++)
{
for (int j = 0; j < 4; j++)
{
if (j < 3)
pixels[y * myMatrix.GetLength(0) * 4 + x * 4 + j] = myMatrix[x, y];
else
pixels[y * myMatrix.GetLength(0) * 4 + x * 4 + j] = 255;
}
}
}
//create a new Bitmap
Bitmap bmp = new Bitmap(myMatrix.GetLength(0), myMatrix.GetLength(1));//,System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);
//bmp.Palette=System.Drawing.Imaging.ColorMap
//lock it to get the BitmapData Object
System.Drawing.Imaging.BitmapData bmData =
bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
//copy the bytes
System.Runtime.InteropServices.Marshal.Copy(pixels, 0, bmData.Scan0, bmData.Stride * bmData.Height);
//never forget to unlock the bitmap
bmp.UnlockBits(bmData);
for (int i = 0; i < 1000; i++)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else
{
for (int y = 0; y < myMatrix.GetLength(1); y++)
{
for (int x = 0; x < myMatrix.GetLength(0); x++)
{
myMatrix[x, y] = (byte)_rnd.Next(256);
}
}
//now we have to convert the 2 dimensional array into a one dimensional byte-array
//byte[] pixels = new byte[myMatrix.GetLength(0) * myMatrix.GetLength(1)];
for (int y = 0; y < myMatrix.GetLength(1); y++)
{
for (int x = 0; x < myMatrix.GetLength(0); x++)
{
for (int j = 0; j < 4; j++)
{
if (j < 3)
pixels[y * myMatrix.GetLength(0) * 4 + x * 4 + j] = myMatrix[x, y];
else
pixels[y * myMatrix.GetLength(0) * 4 + x * 4 + j] = 255;
}
}
}
bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
//copy the bytes
System.Runtime.InteropServices.Marshal.Copy(pixels, 0, bmData.Scan0, bmData.Stride * bmData.Height);
//never forget to unlock the bitmap
bmp.UnlockBits(bmData);
worker.ReportProgress(i );
}
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
pictureBox1.Image = bmp;
pictureBox1.Refresh();
resultLabel.Text = (e.ProgressPercentage.ToString() + "frames");
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
resultLabel.Text = "Canceled!";
}
else if (e.Error != null)
{
resultLabel.Text = "Error: " + e.Error.Message;
}
else
{
resultLabel.Text = "Done!";
}
}
}
}
View the full article