473,407 Members | 2,320 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,407 software developers and data experts.

Editing Bitmap objects while on screen

I'm writing an application that draws custom fractal images, so I'm currently creating an empty bitmap, drawing to that, and then drawing that on the screen using a form's OnPaint. This lets me do quick transformations like rotations and panning while still calculating the fractal. I want to update the bitmap while its on the screen, so the fractal updates itself even while you're panning or rotating.

Problem is, Visual Studio gets really angry (I don't remember the exact error) if I try to call SetPixel() while the bitmap is on the screen. How do I get around this? Is there another Image subclass I should use, or a buffer I need to clear? Java does this easily with the BufferedImage class. Is there a similar functionality in C#?

Thanks,

haven1433
May 17 '10 #1
5 3785
GaryTexmo
1,501 Expert 1GB
I just did a test where I was calling SetPixel on a bitmap that was on screen and I'm not having any troubles... is there possibly more to your problem?

Expand|Select|Wrap|Line Numbers
  1.     public partial class Form1 : Form
  2.     {
  3.         private Bitmap m_bmp = new Bitmap(100, 100);
  4.         private Color m_drawColor = Color.Blue;
  5.         private ColorDialog m_colorDialog = new ColorDialog();
  6.  
  7.         public Form1()
  8.         {
  9.             InitializeComponent();
  10.  
  11.             pictureBox1.Image = m_bmp;
  12.             m_colorDialog.Color = m_drawColor;
  13.             UpdateColor();
  14.         }
  15.  
  16.         public void UpdateColor()
  17.         {
  18.             button1.BackColor = m_drawColor;
  19.             button1.ForeColor = Color.FromArgb(255 - m_drawColor.R, 255 - m_drawColor.G, 255 - m_drawColor.B);
  20.  
  21.             for (int x = 0; x < m_bmp.Width; x++)
  22.                 for (int y = 0; y < m_bmp.Height; y++)
  23.                     m_bmp.SetPixel(x, y, m_drawColor);
  24.  
  25.             pictureBox1.Invalidate();
  26.             pictureBox1.Update();
  27.         }
  28.  
  29.         private void button1_Click(object sender, EventArgs e)
  30.         {
  31.             if (m_colorDialog.ShowDialog() == DialogResult.OK)
  32.             {
  33.                 m_drawColor = m_colorDialog.Color;
  34.                 UpdateColor();
  35.             }
  36.         }
  37.     }
If you can, post an example program that demonstrates the error and perhaps we can help!
May 17 '10 #2
Here's a code example:

I've left a lot of details in, so here is the jist.

First of all, the program assumes that the form has a single button somewhere tied to button1_Click. It creates a form (preferably large) and then waits around, doing nothing. The form is set to refresh itself every 10 seconds, though really I'm more interested in it refreshing every .1 seconds: I just dialed up the value for the example.

Once you push the button, a worker frantically makes a fractal as fast as it can and the refresh paints it at the specified interval. The error occurs when I try to draw it to the screen and update the bitmap pixels at the same time. But I want to be able to update the image often, showing more image as it's completed. I also don't want to force the user to wait until the entire fractal is drawn to see it or force the SetPixel() to pause while drawing. Is there a thread-safe way to do this without adversely effecting performance?

Expand|Select|Wrap|Line Numbers
  1.  
  2. public partial class Form1 : Form {
  3.  
  4.         private int x2;
  5.         private int y2;
  6.         private int iter_max;
  7.         private Bitmap bm = null;//new Bitmap(DisplayRectangle.Width, DisplayRectangle.Height);
  8.         private double bailout;
  9.  
  10.         private Timer update;
  11.  
  12.  
  13.         public Form1() {
  14.             InitializeComponent();
  15.  
  16.             //create the bitmap
  17.             bm = new Bitmap(DisplayRectangle.Width, DisplayRectangle.Height);
  18.  
  19.  
  20.             //init other constants
  21.             x2 = DisplayRectangle.Width / 2;
  22.             y2 = DisplayRectangle.Height / 2;
  23.             iter_max = 50;
  24.             bailout = 1000000;
  25.  
  26.             //create a timer to update the form at 10fps
  27.             update = new Timer();
  28.             update.Tick += new EventHandler(update_Tick);
  29.             update.Interval = 10000;
  30.             update.Enabled = true;
  31.  
  32.  
  33.         }
  34.  
  35.         void update_Tick(object sender, EventArgs e) {
  36.             Refresh();
  37.         }
  38.  
  39.         void  DoWork(object sender, DoWorkEventArgs e){
  40.              Run();
  41.         }
  42.  
  43.  
  44.  
  45.         public void Run() {
  46.  
  47.             double zoom = .0045; // smaller number = bigger fractal
  48.  
  49.             for (int x = 0; x < DisplayRectangle.Width; x++){
  50.                 for (int y = 0; y < DisplayRectangle.Height; y++) {
  51.  
  52.                     int iter = 0;
  53.                     double zr = (x2 - x) * zoom, zi = (y - y2) * zoom;
  54.                     double cr = .5, ci = .25;
  55.  
  56.                     //iterative formula
  57.                     while (iter < iter_max && Math.Sqrt(zr*zr+zi*zi) < bailout) {
  58.  
  59.                         double a = zr * zr - zi * zi;
  60.                         double b = zr * zi * 2;
  61.                         zr = a + cr;
  62.                         zi = b + ci;
  63.                         iter++;
  64.  
  65.                     }
  66.  
  67.                     //color formula
  68.                     double r = Math.Sqrt(zr * zr + zi * zi);
  69.                     double d = 1 + Math.Log(Math.Log(bailout) / Math.Log(r)) / Math.Log(2);
  70.  
  71.                     double colVal = (d + iter) / (iter_max + 1);
  72.                     colVal = Math.Abs(colVal - .5) * 2;
  73.  
  74.                     byte val = (byte)(colVal * 255);
  75.                     if (r < bailout) val = 0;
  76.  
  77.                     //set a pixel according to the color formula
  78.                     bm.SetPixel(x, y, Color.FromArgb(val,val,val));
  79.                 }
  80.             }
  81.         }
  82.  
  83.  
  84.         protected override void OnPaint(PaintEventArgs e) {
  85.              base.OnPaint(e);
  86.             if (bm == null) return;
  87.  
  88.             e.Graphics.DrawImage(bm, new Point(0, 0));
  89.  
  90.         }
  91.  
  92.         private void button1_Click(object sender, EventArgs e) {
  93.             BackgroundWorker worker = new BackgroundWorker();
  94.             worker.DoWork += new DoWorkEventHandler(DoWork);
  95.             worker.RunWorkerAsync();
  96.         }
  97.  
  98.     }
  99.  
  100.  
May 17 '10 #3
GaryTexmo
1,501 Expert 1GB
The exception I got was "Object currently in use" which suggests to me that the generation of the fractal doesn't finish before the next tick of the timer. Throwing a lock around the drawing stops the exception, but of course that doesn't get you the desired result ;)

I have an idea of what you might be able to do here but I need to finish up something and then play around. I'll get back to you!

*Edit: Ok, so I'm dumb :D I was envisioning elaborate array access to draw when it occurred to me I could just lock when I access the variable, not for the whole draw process (as you should anyway!!).

So, put...

Expand|Select|Wrap|Line Numbers
  1. lock (bm) { ... }
... around both your SetPixel call and your DrawImage call and you should actually be golden. Then you can set the update interval to whatever you like.

That said, WinForms drawing isn't exactly known for it's speediness! On my machine, I'd get form flicker on update intervals less than 1000 milliseconds. But this is fairly easy to get around... create a bool and an object (for a lock since you can only lock on reference types), then set the flag to true when you're finished generating the fractal. In the next update, if the bool is true, change the interval to something higher (like 1000 milliseconds, or more if you want)
May 18 '10 #4
Thanks for the response, and sorry I wasn't able to test your solution earlier. You're right - using the lock() clears up the access / modification problem I'm having. Unfortunately, the image isn't going to be static once I draw it to the screen, so I still need a way to draw it quickly.

I'm still new to C#, but I've used Java for quite a while, which is why I brought up BufferedImage as an example. Once the image is drawn, it would be nice to dial back the refresh timer as per your suggestion. However, I plan on implementing commands allowing the user to grab and drag or rotate the image around the screen, and I would like the image to move as the user drags it. Obviously this requires a rather speedy update rate, and flickering would be ... bad.

I suppose drawing a Bitmap to a Form wouldn't work then. What would be a better way to accomplish this? Is there an easy way to do double buffering on the Form's drawing surface?
May 27 '10 #5
GaryTexmo
1,501 Expert 1GB
Why don't you try XNA? You can just draw your fractal right in the default XNA window, or you can embed an XNA panel in a windows form so you can have buttons and such too.

It's actually fairly easy to deal with, though there are a few quirks. For instance, it's not really meant for drawing 2D, per se... the way one would normally draw 2D would be to stamp Texture2D objects as sprites. However, a Texture2D object is simply an array of Color data, so it's quite possible to manipulate it on the fly. XNA will take care of the update and draw loops automatically and you can always write logic to maximize the amount of time you have available in that update loop, though I'm pretty sure a 100x100 buffer will process in no time.

Have a look around google for some basic tutorials and feel free to ask me if you need any help. All of my XNA experience is in 2D so hopefully I can help you out ;)
May 27 '10 #6

Sign in to post your reply or Sign up for a free account.

Similar topics

1
by: someone | last post by:
Please bear with me, since I'm an ASP guy, and not a .NET guy. On my site, I dynamically resize/resample images so they're not too large. GetThumbnail resulted in very poor quality, so I create a...
11
by: Prashant | last post by:
Hi, I have a huge problem. I have a data file which looks something like this -: ..1 .5 .9 -1 .2 .5 ...... ..2 .9 .1 .4 .3 -1 ...... ..2 .4 .5 .7 .6 .2 ...... ........
2
by: alex | last post by:
I hade some problems with file locking and did a simple test using process explorer tool from sysinternals. Bitmap BitmapInWork = new Bitmap(Server.MapPath(fileFullPath)); //at this point file...
5
by: Ron Mexico | last post by:
I have written a graphing engine (very similar to what BigCharts.com offers). Basically, it's an ASPX page that accepts parameters and calls back-end business objects (dlls) to create a graph. ...
1
by: bongoo | last post by:
I'm reading pixel values (RGB) from a bitmap object using function from system.drawing namespace & vb.net (.net framework 1.1) But I would like to make it faster, so is there any another way of...
10
by: pcnerd | last post by:
I'm a VB.NET newbie. I've created a program that plots pixels at random on the form. I have a 19" LCD monitor with a resolution set to 1280 by 1024. If you do the math, that means that there are...
3
by: Iwanow | last post by:
Hello! My goal is to develop a program that opens a bitmap, copies its pixels to an ArrayList in order to perform some complex calculations (edge detection, Hough transform etc.), and save...
0
by: amit | last post by:
I am getting following error when I click ok. I have got this error while writting images in windows application.I am using visual studio 2005 I tried to get the exact error by putting my...
1
by: =?Utf-8?B?RWR1YXJkbw==?= | last post by:
I would like to have a hint to solve this problem: I have a simple user control (myControl) and I'm writing a custom OnPaint event. I have the Graphics object passed through PaintEnventArgs. Now...
2
by: =?Utf-8?B?cm9kY2hhcg==?= | last post by:
hey all, if i have a Graphics object or Bitmap object how do i get it to display on my web page? thanks, rodchar
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.