1 Attachment(s)
Fastest matrix painting for VB
Hello,
I have running program on VB that interfaces with hamamatsu x ray sensor.
it is 2340x2368 with 14b intensity ( BW )
I made dll that will generate array of 2340x2368 long, 1D using labview
my painting function is running on new thread but it takes around 4s to process this image, this is too long for me.
Code:
Dim DCAM_Image(5541120) As UInt16
Dim myBitmap As New Bitmap(2368, 2340)
While y < 2340
x = 0
While x < 2368
Data = DCAM_Image(index)
If Data < min Then
Data = min
End If
If Data > max Then
Data = max
End If
Data = (Data - min) / ((max - min) / 255) ' scaling to 8b
myBitmap.SetPixel(x, y, Color.FromArgb(Data, Data, Data)) ' this is what use nearly all the time in the thread
x = x + 1
index += 1
End While
y = y + 1
End While
How can i speed this up, sure i should be able to get at least 10-20FPS.
And at the same time, how could i save this image in 14b color depth ? since scaling to 256 /8b will lose lot of information :/
Attachment 149839
Re: Fastest matrix painting for VB
There are a few things you can do to get minor gains, here they are:
Code:
Dim mm255 = (max - min) / 255
For y as Integer = 0 To 2340 -1
For x as Integer = 0 to 2368 - 1
Data = DCAM_Image(index)
If Data < min Then
Data = min
ElseIf Data > max Then
Data = max
End If
Data = (Data - min) / mm255 ' scaling to 8b
myBitmap.SetPixel(x, y, Color.FromArgb(Data, Data, Data)) ' this is what use nearly all the time in the thread
index += 1
Next
Next
(the ElseIf assumes that max will be bigger than min, if it isn't then that change wont give the same results as your version)
You can probably get a big speed speed boost if you are currently running a Debug build, as opposed to a Release build. Using Debug slows lots of things down, and this is the kind of situation where the difference of simply switching to Release can be huge.
If you still need more speed after all of the above, I recommend taking a look at FastPix:
http://www.vbforums.com/showthread.p...mies-and-Dudes
Re: Fastest matrix painting for VB
Why i can't simply create byte array(4*width*hight) , and manually place correct values, like data, data, data,0,data2, data2, data2, data2,0 ... and so on ( aka rgba)? I know it should be possible, and should work just as fast.
Code:
Dim picture(4 * 2368 * 2340) As Byte
Dim DCAM_Image(5541120) As UInt16
While y < 2340
x = 0
While x < 2368
Data = DCAM_Image(Index)
If Data < min Then
Data = min
End If
If Data > max Then
Data = max
End If
Data = (Data - min) / ((max - min) / 255)
picture(ii) = Data
ii += 1
picture(ii) = Data
ii += 1
picture(ii) = Data
ii += 1
picture(ii) = 0
ii += 1
x = x + 1
Index += 1
End While
y = y + 1
End While
PictureBox1.Image = Image.FromStream(New MemoryStream(picture))
but last line give error, like wrong parameter, how to fix that ?
some people doing like this, but i just get error :/
System.Runtime.InteropServices.Marshal.Copy(picture, 0, myBitmap, 4 * 2368 * 2340)
Re: Fastest matrix painting for VB
That line is doing multiple things (including creating a MemoryStream, and creating an Image from it), so the first thing to do is split it out to multiple lines so that you can find out which of them is causing the problem.
I would guess that Image.FromStream is having the problem, because it presumably expects an image file rather than just a long list of bytes (while an image file contains a list of bytes for the pixels, it contains other important things too). Even if you already know how to get it all set up right, it will almost certainly be quicker and easier to use FastPix as I previously suggested.
Re: Fastest matrix painting for VB
For some reason i don't understand it, maybe because straight 14h of coding today...
can you write example for 2x2 matrix, it should take very little of your time ;/
( strange thing, some times i can do complex things, but sometimes i can't understand rudimentary peace of code :/)
Re: Fastest matrix painting for VB
Quote:
Originally Posted by
kilohercas
For some reason i don't understand it, maybe because straight 14h of coding today...
can you write example for 2x2 matrix, it should take very little of your time ;/
( strange thing, some times i can do complex things, but sometimes i can't understand rudimentary peace of code :/)
It can be useful to keep the size small for debugging purposes, but I would design the code as a method with image parameters (width and height) so it will work with whatever image size you need. You are right that processing an array is much faster that SetPixel. You get an error because your stream doesn't contain the correct header data for the Image or Bitmap class. That's why people use Bitmap.Lockbits to convert bitmap data to an array (of Bytes or Integers). FastPix was originally design to do that in an easy form for beginners, but I still use it regularly myself because it works well. It is limited to 32 bpp format which is the default for System.Drawing and normally the fastest option, but it should be fine for your present purpose.
I think it's a mistake to calculate the minimum and maximum inside the main loop. Besides being inefficient, it means the minimum and/or maximum are likely change every time you process another pixel of the image. If you need a minimum and maximum, it would make more sense to calculate them first in a separate loop.
But as far as I can see, you don't need a minimum and maximum at all for compressing the 14-bit data to 8 bits. You just need to get rid of the last 6 (least significant) bits of each value in the array. You can do that by doing an integer division by 64 or by bit shifting. I'll post an example.
BB
Re: Fastest matrix painting for VB
how about PixelFormat.Format16bppGrayScale
Quote:
The pixel format is 16 bits per pixel. The color information specifies 65536 shades of gray.
that is pretty much what you want with 14bpp monochrom data. you could directly transfer your array to the bitmap, or more clever: make whatever reads the values from the device, write to the same memory as your Format16bppGrayScale bitmap is sourced from.
Re: Fastest matrix painting for VB
Here's an example of how you can display your 14-bit image data in a PictureBox, using FastPix. Download the FastPix class from the CodeBank (see link in my signature below) and add it to your project in Visual Studio with Project/Add Existing Item.
First of all, here's the Function which returns a bitmap (32bpp) from an array of 14-bit grayscale data:
Code:
Private Function GetBitmapFrom14BitData(imageData As UInt16(), ImageWidth As Integer, ImageHeight As Integer) As Bitmap
'validate the arguments:
If imageData.Count <> ImageWidth * ImageHeight Then
Throw New ArgumentException("Width and Height do not match pixel data sizé")
End If
'image processing:
Dim bmp As New Bitmap(ImageWidth, ImageHeight)
Using fp As New FastPix(bmp)
Dim pixels As Integer() = fp.PixelArray
For i As Integer = 0 To pixels.Count - 1
Dim pix As Integer = imageData(i)
pix \= 64 'integer divide by 64 to eliminate 6 low-end bits
pixels(i) = &HFF000000 Or (pix << 16) Or (pix << 8) Or pix
Next
End Using
Return bmp
End Function
Here's an example of using the function to display the image in a PictureBox. It includes a stopwatch to check the performance. The results appear in the Output Window.
Code:
Dim DCAM_Image(2340 * 2368 - 1) As UInt16 'Note the correct dimensioning of the array!
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim sw = Stopwatch.StartNew
PictureBox1.Image = GetBitmapFrom14BitData(DCAM_Image, DCAM_Image.Width, DCAM_Image.Height)
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds)
End Sub
With a data array slightly larger than yours yours (2330 * 2520) I measure a processing time varying around 53 milliseconds. It depends on the computer performance, of course, but it's clear that your required frame rate should be in reach.
Note that converting the data to 32bpp doesn't change how you store the data. The above code temporarily copies it into a 32bpp Image for display purposes. You could use a 24bpp bitmap instead, but not with FastPix. The 16bppGrayScale format is totally useless for this purpose because it's not supported by gdi+ (it throws an Argument Exception when you try to draw it).
BB