To download NI software, including the products shown below, visit ni.com/downloads.
Overview
The example demonstrates how to capture the screen content with .NET functions and how to display the captured image in an IMAQ image control.
Description
The example uses .NET functions (e.g. Graphics.CopyFromScreen) to create a screenshot of the desktop. With a Map Pixel Pointer the screenshot is written to an IMAQ image buffer so the image can be used and possibly processed in LabVIEW without the need for further .NET functions.
Requirements
Software
Hardware
Steps to Implement or Execute Code
Additional Information or References
**The code for this example has been edited to meet the new Community Example Style Guidelines. The edited copy is marked with the text 'NIVerified'. Read here for more information about the new Example Guidelines and Community Platform.**
Example code from the Example Code Exchange in the NI Community is licensed with the MIT license.
I believe this is exactly what I am trying to do also:
Quickly convert an NI VisionImage object into a System.Drawing.Image or Bitmap
Unfortunately I do not have Labview and so am not able to follow this example. Is there a way to do this using only VDM in VB.Net?
Thanks for any comments.
Can you obtain pointer from IMAQ image in VB.Net?
If yes, than follow LabVIEW block diagram flow and use Bitmap constructor -> Bitmap (int width, int height, int stride, PixelFormat, IntPtr scan0)
It should be quite simple to re-produce that in VB.Net
P.S. I was able to get pointer from VisionImage constructor but it is not the same as LabVIEW's IMAQ Image, and StartPtr wasn't working the same. Let me know if VisionImage is not the correct control in VB.net.
Hi Griffin,
Thanks for the reply, sorry for being slow to answer (swamped and trying many different approaches).
No, I am not aware of any way to get a pointer to the data from the VisionImage object. It has ImageToArray which returns 2D arrays rather than the needed 1D array. Of course I could iterate through the data and copy the values one by one into an appropriately formatted byte array, but that would be very slow.
VisionImage.Flatten returns a 1D array of bytes but it does not seem to be correctly formatted for a Bitmap object, and I don't seem to be able to find documentation for what the output format of VisionImage.Flatten is: what is the structure of the byte().
I would have thought there would be a VisionImage.GetBitmap which would return a Bitmap of the image currently held ... but nothing like that appears to exist.
Thoughts?
Well, either there is a bug in .net assembly or there is a reason why "Image" doesn't work the way we expect it to.
Let's go from opposite end, what you are trying to do? I.e. do you use NI Vision tools to acquire image from camera and then manipulate with data or you have data which you would like to process with NI Vision tools...
-Artur
P.S. You can go a little bit further with AxCWIMAQControlsLib. ControlImage Method has methods "From file" and "From HBITMAP" but still. But creating initial Image always generates error. Maybe it requires camera input... Have you checked NI supplied examples?
To get a pointer to the IMAQ Image's data you should use : "vi.lib\Vision\Basics.llb\IMAQ GetImagePixelPtr" It's in palette as well under the External Library Support section of Image Management. You have to becareful with this guy, however. The data does not appear sequentially because there are border regions (which you'll probably want to set to zero), and alignment regions (used to make sure that the image uses integer blocks of memory). To make the data appear sequentially, you will want the alignment regions to be zero as well, and this means that the # of pixels per row will need to be a mulitple of 32 (or 64 if you running 64-bit LV).
We do not have problem in LabVIEW...
It is in VB.net where we cannot grab pointer or it doesn't work.
-Artur
Hey Guys,
I think I have a solution!
It turns out that there appears to be a 'hidden' or 'undocumented' property on the VisionImage object. Intellisense does NOT show it but if you type VisionImage.StartPtr you get a System.IntPtr to the first pixel value of the image data inside the VisionImage! I have used this in the constructor for a Bitmap successfully.
I am a bit concerned about whether the data is being copied into the Bitmap by the constructor or of the pointer is being used directly. I intend to do some checks.
--Duane
Can you share the code, I've tried it and it wasn't succesfull, would like to check what was wrong...
You are welcome,
This chunk of code uses the VisionImage image data to create a Bitmap object. Note though, that the Bitmap is now sharing memory with the VisionImage object so disposing of it before the bitmap would of course throw an exception. However I think this accomplishes what I needed.
Thanks again for your assistance and ideas.
'Declare Locals
Dim niviTestImage As New NationalInstruments.Vision.VisionImage
Dim bmpTestBitmap As System.Drawing.Bitmap
'Set the type of the VisionImag
niviTestImage.Type = NationalInstruments.Vision.ImageType.Rgb32
'Read the image from disk
niviTestImage.ReadFile("C:\TestImg.png")
'Create a Bitmap From it
bmpTestBitmap = New System.Drawing.Bitmap( _
niviTestImage.Width, _
niviTestImage.Height, _
niviTestImage.LineWidthInBytes, _
Imaging.PixelFormat.Format32bppRgb, _
niviTestImage.StartPtr _
)
Excellent,
-Artur
Guys,
I have this same need - visionimage -> bitmap (or other useful graphics object) I have an older vision app that I wrote the image processing for bmps, but with the newer IMAQ aquisition, I can't get the visionimage cast to a bmp. I suppose I could write to a bitmap and read it back in, but the whole point was keep it in memory and be quick about it.
I tried to implement the above, but I get errors on linewidthinbytes and startptr as not being members of vision.visionimage etc.
If I throw in values say 4 for linewidthinbytes and 0 for StartPtr, it will compile and run, but of course I don't get the image data succesfully. Am I missing something simple? Even though they are not documented members and don't show up in the intellisense, is there a way to force it?
pictureBox1.Image = New System.Drawing.Bitmap( _
niviTestImage.Width, _
niviTestImage.Height, _
niviTestImage.LineWidthInBytes, _
Imaging.PixelFormat.Format32bppRgb, _
niviTestImage.StartPtr _
)
Error 1 'LineWidthInBytes' is not a member of 'NationalInstruments.Vision.VisionImage'.
Error 2 'StartPtr' is not a member of 'NationalInstruments.Vision.VisionImage'.
Thanks,
James
Hi James,
I used the NI Vision Development Module 2010 SP1 (32 Bit) on Windows XP. I noticed that the two items in question (the useful ones: LineWidthInBytes and StartPtr) did NOT show up in intellisense, so I suspect they are not yet documented features of the object. It would not surprise me if they are not available in other versions of the visionimage object.
For clarity my code references:
NationalInstruments.Vision (.Net) 10.1.35.102 from NationalInstruments.Vision.dll
Oh ... maybe it is worth mentioning that the only way I found those properties was by setting a breakpoint in executing code and adding visionimage object to the watch window. Then I just dug around in the watch window and found the properties. They never showed up in intellisense nor did I find them in the documentation. However if I typed them in lowercase Visual Studio would camel case capitalize them for me so I could tell they were being resolved, and they did work.
Hope that helps.
Thanks,
Clever bit of sleuthing you did to find those objects. Version differences are most likely why it isn't working for me. When I type them, as noted before, I get errors. My dll is 9.X.X.X so older. I also only have the Aquisition Module from a March 2010 CD as well, not the full Development Module. I am also on 32bit XP SP1.
I may try to download the new version demo so I can get the 10.x.x.x dll and see if that indeed is the limitation. It seems like I struggled less with the CWImaq stuff of earlier days.
Thanks again for your help. If I can solve my issue with version update, I'll post here so people can make the most of your work.
James
Hi Artur,
I modified your code a little bit as follows.
The reason I am doing this is to dynamically load images in the loop and then doing the .net based image processing.
However, it seems that the orignal IMAQ image pointer had lost and I couldn't get any images showed in the IMAQ display.
I know we can always convert the IMAQ image into Bitmap in the loop, but in this way we cannot minimize the processing time in the loop.
Since the "IMAQ pointer to Bitmap object" takes some time in each loop, do you have any good suggestion to implement this application?
Thank you
Ting
I am confused with your code...you forcing .net and labview IMAQ to fight over pointer...use one or another or both over lock/unlock bits or map/unmap pointer otherwise you always end up loosing pointers or crashing.
Unless I am missing something.
I would use IMAQ at start and finish only, and never while processing bitmap to gain performance and flexibility. If you must have IMAQ during processing -> create another one but not the one you borrowing pointer from.
-Artur
Hi Artur,
The reason I am placing the IMAQ ReadFile.vi in the loop is because I have to dynamically change the image that are going to be processed.
The application I am looking for is using NI Vision Acquisition Software to acquire IMAQ images and then processing them using .NET's image prcessing function (Bitmap as input format).
According to your example, the IMAQ ReadFile has to be place before "IMAQ to Bitmap conversion".
However, in such case, I am not able to do the "acquistion-then-processing" in the loop.
Instead, I have to do "IMAQ acquistion --> imaq to bitmap --> .net processing" in the loop.
I have this structure worked though as follows, but as you said, never while processing bitmap to gain performance and flexibility.
So what I am actually asking is how to acquire IMAQ image rapidly in the loop but the convertion of IMAQ format to Bitmap falls outside of the loop.
Even if I implemented the producer consumer loop, I still have to convert the IMAQ to Bitmap after the acquisition right?
I hope this will give you more ideas about the application I am talking about. I am really sorry for bad English expression.
Thank you
Ting
Why not reading file directly with .net?
-Artur
Well, I am not even a rookie programmer to use .net.
That's the reason why I am still looking for these kind of "hybrid" solutions in LabVIEW.
I guess I have to learn more OOP and .net programming in the near future. lol.....
Thanks
Ting
-Artur