Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

DrawImage(..) Method decrease the performance too much

Posted on 2006-04-28
33
Medium Priority
?
619 Views
Last Modified: 2008-02-01
Hello,

Ima using the DrawImage Method to drow multi Images on a pictureBox control using a timer but i found that this method make the performance too bad,
There is another method in .Net i can use instead???

Please help,

Thanks
0
Comment
Question by:amrelgarhy81
  • 17
  • 8
  • 5
  • +1
33 Comments
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16565803
Can you give us a bigger picture of what you are doing so we can suggest possible different approaches?
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16565858
What iam doing is a user control:
It is inherited from pictureBox control and i use a timer to change the images in the picture box and i do some effects while changing beween images so i use the drawImage method to do that effects.
And that made me see the lake in performance.
Please ask if you need more.
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16565956
Understood me??
0
What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16566120
Yes...but it's too vague to really make any good suggestions off of...

How big are your images?
How often are you changing them?
Where are you storing the different images?
What kind of effects are you making?

Etc...

There are many things that can affect "performance"...
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16566172
Yes i Know tha manythings can affect the performance but what iam asking about is that the drawImage method make decrease in performance, there is another function in .Net that can replace it?

Some effects like:
Draw a new image moving and scaling from left to right or up to left
You know somthing near to powerPoint effects.
0
 
LVL 3

Accepted Solution

by:
Pigtor earned 260 total points
ID: 16566305
Do not use the PictureBox control, use a Panel control or a UserControl instead.

About PictureBox:
- The PictureBox control is for displaying images. It is not a handy placeholder for a graphics surface.

- Windows is an event driven system in which each event must be serviced in the correct context and events destined to handle button click or mouse move events must not be used to do drawing on screen or other weird stuff.

- The PictureBox refreshes itself by drawing the System.Drawing.Image based object stored in it's Image property. If there is no image, it will show the background colour.

- Stealing and drawing upon the Graphics object of any control is not good practice, should be strongly discouraged and breaks the rules of handling events in the right place at the right time. Basically if you do this it will cause you pain. When you bang your head against a wall it causes you pain. that is a sign that you should stop doing it. It's the same for the PictureBox.CreateGraphics call.


Check this link for more information:
http://www.bobpowell.net/picturebox.htm



0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16566390
So Pigtor
Should i draw on another control or donn't use the drawImage method,
Note i need it to be a control because i will deal with it  as a user control later,
And i found that the big performance problem is in the DrawImage method.
0
 
LVL 3

Expert Comment

by:Pigtor
ID: 16567422
DrawImage is not slow, GDI+ is slow
You could find a lot of information on bobpowell website:
http://www.bobpowell.net/why_so_slow.htm

If your component demand a lot of graphics, you should better use DirectX.

Answering your question, DrawImage is not slow, but you should better use DrawImageUnscaled, because scaling an image can slow down the rendering.

I hope that information helps.

Victor
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16572348
Ok, but small question:
PowerPoint and flash uses directx?
I tryed the DrawImageUnscaled method but nothing happened new

What can i do?
0
 
LVL 2

Expert Comment

by:CuSo4
ID: 16689181
On wich thread are you calling DrawImage? I believe it shouldn't be used in the timer-thread itself, as it will result in semi-freezing windows. Can you give us a sample of your code?
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16689857
Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick

            Dim mx As New Matrix()
            mx.Translate(0, mH, MatrixOrder.Append)
            g.Transform = mx
            mH = mH + (Me.Height / 10)
            g.DrawImage(Me.currentImage, 0, 0, Me.Width, Me.Height)
            If mH > 0 Then
                Me.Image = Me.currentImage
                mH = -Me.Height              
                Me.Timer2.Enabled = False
            End If


End Sub
0
 
LVL 2

Assisted Solution

by:CuSo4
CuSo4 earned 80 total points
ID: 16689982
It seems like you are trying to draw from within the timer-thread. This is probably the reason for the poor performance.
Try using the following structure:

 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        AddHandler Me.Image.Paint, New PaintEventHandler(AddressOf Image_OnPaint)
    End Sub

    Private Sub Image_OnPaint(ByVal sender As Object, ByVal e As PaintEventArgs)
        Dim mx As New Matrix()
        mx.Translate(0, mH, MatrixOrder.Append)
        e.Graphics.Transform = mx
        mH = mH + (Me.Height / 10)
        e.Graphics.DrawImage(Me.currentImage, 0, 0, Me.Width, Me.Height)

        If mH > 0 Then
            Me.Image = Me.currentImage
            mH = -Me.Height
            Me.Timer2.Enabled = False
        End If

    Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
        Me.Image.Invalidate()
    End Sub


This way the Timer will request a redraw of the image with the Invalidate() method, and the Painting itself will happen on the right thread.
         
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16690136
I found no diffrence in the performance.
0
 
LVL 86

Assisted Solution

by:Mike Tomlinson
Mike Tomlinson earned 160 total points
ID: 16690307
CuSo4...

It was already running on the same thread as the main UI thread.  The code clearly shows that Timer2 has a Tick() event indicating that it is a System.Windows.Forms.Timer and therefore runs in the same thread as the form containing it.  You are correct that you should use the Paint() event instead of storing a "global" graphics object to use in other subroutines.  You're just off base with the different thread comments...

amrelgarhy81...

Out of curiousity, what is the Interval on your Timer set to?
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16690359
Timer  Interval  = 1
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16690424
we can use e-mails here to sent the sample i have?
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16690432
You won't get the Timer control to fire properly with an Interval of 1!

The lowest you will likely see "proper" timing is somewhere around 25, but it may be as high as 50 on some older systems.
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16690453
by the way thats not the problem
the problem the my processor get very hight while running the draw image method, in a timer , on a new thread, or on the main thread.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16690479
Of course...your processor is probably pinged at 100% because there isn't any "pause" between events with a Timer interval that low.  The events are all stacked up against each other in your message queue making them run essentially as if they were in an inifinite loop.  

The same would be true if you placed the code into a different thread but did not provide a "pause" inbetween paints via the Sleep() method.

Just to prove it...bump up your interval to 100 and see if your processor usage drops down.  If it doesn't then you are attempting to do too much processing in the timer event.
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16690483
I heared from someone is that the problem is in the GDI+ its self becuase it dosn't work directly with the hardware like the previous GDI in vb6 and heared too that GDI+ is not a managed classes it is just API methods called from the .net
0
 
LVL 2

Expert Comment

by:CuSo4
ID: 16690497
Idle_Mind is right about the Timer Interval, and that's probably also why your processor utilisation gets that high.

@Idle_Mind: Sorry about the thread-confusion, I didn't know Timer events ran on the Form's main thread...
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16690523
"I didn't know Timer events ran on the Form's main thread"

The System.Windows.Forms.Timer (it is the only one with a Tick event) runs on the main UI thread.

The other two Timers (System.Timers.Timer and System.Threading.Timer) run in their own thread.
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16690545
Ok, good experts
I will try but small question:
suppose i used it without any timeres or threads, i used it in a loop it will be worest performance right?

And if i made "pause" between events the animation of the image will cut and continue, cut and continue.



0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16690628
That may just depend on how long the pause is.  There may not be that much noticeable difference to the end user.  It just depends on what you're doing.  Experiment with the Interval property...



A small call to Sleep() can greatly reduce CPU usage:

    System.Threading.Thread.Sleep(25)

The problem with moving the painting to a different thread is that you need a delegate to properly marshal the call from your thread back onto the main UI thread.  This causes additional overhead on the application, especially if you are "firing events" in rapid succession as you are.

A common misconception is that threading "frees up" the main UI.  If a thread does NOT pause, and continually fires an event that the main UI must handle, then the main UI will be continually process the threads event.  This essentially nullifies the benefit of creating the thread in first place...
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16690693
ok, i will try and send what will happen
0
 
LVL 3

Expert Comment

by:Pigtor
ID: 16691212
Using timers and sleep is not a good idea.

You can use a Threading.Timer, but you will get the "Object is already in use" exception.  To correct this behavior you should use the SyncLock <Bitmap> statement, where <Bitmap> is a reference to the Bitmap you are drawing.
The best performance you will get is using a timer of 100 ms.  I have posted before the reason GDI+ is so slow.

You could use a non threading timer like System.Windows.Forms.Timer or a LOOP, but it will not help you so much, because when another process slows down the computer, your GDI+ graphics will have a strange behavior.
For example, your image draws in 200 ms, and your sleep or timer is 100 ms, this interval will hang your computer.  Other example, your image draws in 200 ms and your timer is in 300 ms., the same will happen when another process slows down the machine.

Other consideration you should take is the size of the image, a small image draws faster than a large image.  Try testing a large image (for exaple 4x the small image size)  The result will be more or less the same behavior it will have in slower machines.
Now, try using a larger image (16x the size of the small image) on your timer and you will understand what I'm talking about.

My sugestion, use GDI+ for images that doesn't change frequently and DirectX for advanced image manipulation like animations.
If you don't have no choice but using GDI+, I suggest using a Threading.Timer rather than Windows.Forms.Timer Or Sleep.

0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16691520
Thanks Pigtor for your comment i will try all what you said Pigtor,  Idle_Mind  and will tell you both what i got,
Thanks alot for your effort experts.
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16694391
Pigtor...

How can i use the Threading.Timer?
Using events like the Windows.Timer?
Or should i use it like this sample in the .Net 2.0 Documentaion:
ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref12/html/T_System_Threading_Timer.htm
0
 
LVL 3

Expert Comment

by:Pigtor
ID: 16699610
Use the following code. Call the StartTimer and StopTimer.
The TimerProc method is the event you are looking for.

-------------------------------------------------------------------------------------------------------

Private hTimer As System.Threading.Timer

Private Sub StartTimer(ByVal Interval As Integer)
     If Not hTimer Is Nothing Then Return
     hTimer = New System.Threading.Timer(New System.Threading.TimerCallback(AddressOf TimerProc), Nothing, Interval, Interval)
End Sub

Private Sub StopTimer()
     If Not hTimer Is Nothing Then
          hTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite)
          hTimer.Dispose()
          hTimer = Nothing
     End If
End Sub

Private Sub TimerProc(ByVal obj As Object)
'...Put here the code ...
End Sub

0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16699686
Thanks, Will try and tell you the result, but small question:
Using this timer will give diffrent performance results than using normal threading, using sleep?
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16699694
I really don't see how using a System.Threading.Timer will be any different than the current implementation using a System.Windows.Forms.Timer.

You won't be able to get any "faster" firing interval.

Additionally you now have the overhead of marshalling the call from your thread back onto the main UI using Delegates and the Invoke() methods.

?
0
 
LVL 1

Author Comment

by:amrelgarhy81
ID: 16699878
right, I will try and get the results,
Thanks alot
0
 
LVL 3

Expert Comment

by:Pigtor
ID: 16700088
The timer interval can be changed using the Interval parameter in the StartTimer method.
You will not find differences between both timers, because both does the same.  But the difference is in the performance with big images, slow machines or faster timers.

To get the best performance for your graphics, you should make your own tests using bigger images and faster timers.  When you get an acceptable performance on your bigger images, change your images to their normal size and you will see a very good performance.

Or maybe the reason of the bad performance is the technique you are using to draw the window.
GDI+ is very extensive to be answered in one question.  Please go to this link:
http://www.bobpowell.net
On this site you will find a lot of tricks for performance and what to NOT do in GDI+


0

Featured Post

NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A basic question.. “What is the Garbage Collector?” The usual answer given back: “Garbage collector is a background thread run by the CLR for freeing up the memory space used by the objects which are no longer used by the program.” I wondered …
For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
Suggested Courses
Course of the Month20 days, 22 hours left to enroll

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question