|
-
Sep 10th, 2011, 10:46 AM
#1
Re: Fast update of bitmap from polar coordinate data
Hi chriscross,
Unfortunately I was mistaken about the XNA example. I found the demo that Jenner made (it was from this thread, post#10) but unfortunately the link is now dead. I dug out the code but I think it will take a lot of work to convert it to something you can use; there is too much I don't know about XNA.
Still, I made my own attempt at a "radar" screen which you might find interesting for comparison. With an angular resolution of 1 degree it takes me about 3-4 seconds to do a full 360 degree sweep. It uses random data for each echo line.
It seems that most of the time goes into updating the bitmap with the new line (not the rendering after all). I almost doubled the performance up by drawing 2 lines in each pass, and the speed could be further improved by increasing that to 3 or more.
I widened the line bitmap to 3 pixels to provide a kind of anti-aliasing. (The middle line has the data at full opacity, and the first and third lines the same data partly transparent). It seems this costs little extra time and the resulting scan is much smoother.
If you want to try it you can just copy the code below into a default form. There's no need to do anything in the designer. You can resize the form to enlarge the scan. The timing results are shown in the Output window.
Code:
Public Class Form1
Private WithEvents tim As New Timer With {.Interval = 15}
Private WithEvents pictureBox1 As New PictureBox
Private sw As Stopwatch
Private echo1() As Integer 'echo data array 1
Private echo2() As Integer 'echo data array 2
Private echoResolution As Integer 'was "scale"
Private angleResolution As Single = 1
Private rnd As New Random
Private scanBitmap As Bitmap 'was "bm"
Private echoLine1 As Bitmap
Private echoLine2 As Bitmap
Private angle As Single
Private refreshInterval As Integer = 1
Private fadeInterval As Integer = 4
Private refreshCount As Integer
Private fadeCount As Integer
'setup in the load event:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.ClientSize = New Size(600, 600)
PictureBox1.BackColor = Color.FromArgb(0, 50, 20)
pictureBox1.Dock = DockStyle.Fill
Me.Controls.Add(pictureBox1)
tim.Start()
End Sub
'some setup in the SizeChanged event, to allow user resizing
Private Sub PictureBox1_SizeChanged(sender As Object, e As System.EventArgs) Handles pictureBox1.SizeChanged
scanBitmap = New Bitmap(pictureBox1.Width, pictureBox1.Height)
echoResolution = pictureBox1.Width \ 2 - 5
ReDim echo1(echoResolution - 1)
ReDim echo2(echoResolution - 1)
echoLine1 = New Bitmap(echoResolution, 3)
echoLine2 = New Bitmap(echoResolution, 3)
End Sub
Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles pictureBox1.Paint
'draw a sweep indicator line
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Dim centre As New Point(pictureBox1.Width \ 2, pictureBox1.Height \ 2)
Using mtx As New Drawing2D.Matrix
mtx.RotateAt(angle + 0.2F, centre)
e.Graphics.Transform = mtx
Using pn As New Pen(Color.LightGreen, 1)
e.Graphics.DrawLine(pn, centre, New Point(pictureBox1.Width - 5, centre.Y))
End Using
End Using
End Sub
Private Sub Timer1_Tick(sender As Object, e As System.EventArgs) Handles tim.Tick
'update the bitmap and depending on the refreshinterval, put it in the picture box
UpdateScanBitmap()
refreshCount = (refreshCount + 1) Mod refreshInterval
If refreshCount = 0 Then pictureBox1.Image = scanBitmap
fadeCount = (fadeCount + 1) Mod fadeInterval
If fadeCount = 0 Then scanBitmap = FadeImage(scanBitmap, 98)
End Sub
'Update the scan:
Private Sub UpdateScanBitmap()
If sw Is Nothing Then sw = Stopwatch.StartNew
'create a set of simulated data for the echo line:
For d As Integer = 0 To echo1.Count - 1
echo1(d) = rnd.Next(0, 255)
echo2(d) = rnd.Next(0, 255)
Next
'conver the data to a line bitmap:
echoLine1 = GetEchoBitmap(echo1, echoLine1)
echoLine2 = GetEchoBitmap(echo2, echoLine2)
'draw the echo lines on the scan
Using g As Graphics = Graphics.FromImage(scanBitmap)
Dim centre As New Point(pictureBox1.Width \ 2, pictureBox1.Height \ 2)
Using mtx As New Drawing2D.Matrix
mtx.RotateAt(angle, centre) '
g.Transform = mtx 'rotate the Graphics
g.DrawImageUnscaled(echoLine1, centre.X, centre.Y - 1)
mtx.RotateAt(angleResolution, centre)
g.Transform = mtx
g.DrawImageUnscaled(echoLine2, centre.X, centre.Y - 1)
End Using
End Using
'update the angle
angle = (angle + 2 * angleResolution) Mod 360.0F
'provide feedback in the Output window:
If angle < angleResolution Then
angle = angle Mod 360.0F
Console.WriteLine("360 deg. sweep time = " & ((sw.ElapsedMilliseconds / 1000).ToString("N4")))
sw = Stopwatch.StartNew
End If
End Sub
Private Function GetEchoBitmap(echo As Integer(), echoLine As Bitmap) As Bitmap
Using fp As New FastPix(echoLine)
Dim pixels() As Integer = fp.PixelArray
For radius As Integer = 0 To echoResolution - 1
Dim data As Integer = echo(radius) * 256
pixels(radius) = &HAF000000 + data
pixels(radius + echoResolution) = &HFF000000 + data
pixels(radius + 2 * echoResolution) = &HAF000000 + data
Next
End Using
Return echoLine
End Function
Private Function FadeImage(bmp As Bitmap, opacityPercent As Double) As Bitmap
'set the opacity of an image:
If opacityPercent >= 0 AndAlso opacityPercent <= 100 Then
Dim alphaRatio = opacityPercent / 100
Using fp As New FastPix(bmp)
Dim pixels() = fp.PixelArray
For i As Integer = 0 To pixels.Count - 1
Dim pixel = pixels(i)
Dim alpha As Integer = (pixel >> 24) And &HFF
alpha = CInt(alphaRatio * alpha) << 24
pixels(i) = pixel And &HFFFFFF Or alpha
Next
End Using
Return bmp
Else
Console.WriteLine("FadeImage: opacityPercent must be in the range 0-100.")
Return Nothing
End If
End Function
End Class
BB
Last edited by boops boops; Sep 10th, 2011 at 10:53 AM.
-
Oct 9th, 2011, 03:08 PM
#2
Thread Starter
New Member
Re: Fast update of bitmap from polar coordinate data
Hi,
Apologies for not updating to this thread sooner - thanks to everyone for their input, particularly BB for taking the time to produce an example radar.
I now have a system that works well on my development machine, I now need to optimise it for slower processors (the target is an Intel Atom based single board computer)
I am currently working through the best way to implement BB's multiple lines in each pass with the real data I am processing - I will post back with the results and my code when I have got a bit further with it.
Thanks
Chris
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|