Example Code

From VisionImage to BITMAP (.NET)

Products and Environment

This section reflects the products and operating system used to create the example.

To download NI software, including the products shown below, visit ni.com/downloads.

    Software

  • Vision Development Module
  • LabVIEW

Code and Documents

Attachment

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

  • LabVIEW 2012 Base Development System (or compatible) (Windows operating system)
  • Vision Development Module 2012 (or compatible)

 Hardware

  • No hardware is necessary to use this example VI

 

Steps to Implement or Execute Code

  1. Open the attached file
  2. Run the VI 

 

Additional Information or References

Capture screen with .NET and display the captured image as an IMAQ image - Front Panel.png

 

Capture screen with .NET and display the captured image as an IMAQ image - Block Diagram.png

 

 

**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.

Comments
D*
Member
Member
on
What kind of performance improvements have you found?
GriffinRU
Member
Member
on
Key performance is not creating copies of the same data. Performance gain to expect - depends on application. Image manipulation in dot.net environment allows programmer to apply wide range of tools and functions, without creating data overhead associated with LabVIEW data flow. This is a cutting-edge programming and familiarity with other programming languages or windows programming requires, otherwise memory leaks and crashes would kill your project. LabVIEW creates excellent environment for dot.net programming with all the benefits of dataflow and documenting.
NewNIVisionUser
Member
Member
on

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.

GriffinRU
Member
Member
on

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.

NewNIVisionUser
Member
Member
on

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?

GriffinRU
Member
Member
on

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?

D*
Member
Member
on

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).

GriffinRU
Member
Member
on

We do not have problem in LabVIEW...

It is in VB.net where we cannot grab pointer or it doesn't work.

-Artur

NewNIVisionUser
Member
Member
on

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

GriffinRU
Member
Member
on

Can you share the code, I've tried it and it wasn't succesfull, would like to check what was wrong...

Imageptr.png

You are welcome,

NewNIVisionUser
Member
Member
on

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 _

                                                 )

GriffinRU
Member
Member
on

Excellent,

-Artur

vb.net.hell
Member
Member
on

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

NewNIVisionUser
Member
Member
on

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

NewNIVisionUser
Member
Member
on

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.

vb.net.hell
Member
Member
on

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

Ting1224
Active Participant
Active Participant
on

Hi Artur,

I modified your code a little bit as follows.

IMAQ_Bitmap_Sequence.png

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 

GriffinRU
Member
Member
on

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

Ting1224
Active Participant
Active Participant
on

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.

IMAQ_Bitmap_In the Loop.png

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

GriffinRU
Member
Member
on

Why not reading file directly with .net?

-Artur

Ting1224
Active Participant
Active Participant
on

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

GriffinRU
Member
Member
on

https://decibel.ni.com/content/servlet/JiveServlet/showImage/102-15165-6-21084/Load+Bitmap+from+File.png

-Artur