09-21-2021 12:27 PM - edited 09-21-2021 12:50 PM
I have a frame grabber that acquires 16bit grayscale image data as a 1d array of unsigned short. Now I need to convert this raw U16 data to a LabVIEW Vision Image for further processing.
Before proceeding with the actual acquisition, I thought of experimenting with the NI Vision Library Support for C++. I have slightly modified example code from NI to copy a Grayscale U8 image using memcpy(). When I run, for Grayscale U8 , It works.
For the initial test, I created a Grayscale U8 type Image Buffer in LabVIEW and passed the pointer to the Image Handle:
The Parameter Configuration
C++ Function:
#include "nivision.h"
//Image Data as LabVIEW Cluster
typedef struct {
    char* name;
    Image* address;
}IMAQ_Image;
int __stdcall copyImageToLV(IMAQ_Image *LVImage) 
{
  Image* myImage, *lvImage;
  PixelValue pixel;
  ImageInfo myImageInfo, lvImageInfo;
  int y, LVHeight, LVWidth;
  lvImage = LVImage->address;
  pixel.grayscale = 128;
  //Create a New Image buffer and fill it with grey.
  myImage = imaqCreateImage(IMAQ_IMAGE_U8, 3);
  imaqGetImageSize(lvImage, &LVWidth, &LVHeight);
  imaqSetImageSize(myImage, LVWidth, LVHeight);
  imaqFillImage(myImage,pixel, NULL);
  imaqGetImageInfo(myImage, &myImageInfo);
  imaqGetImageInfo(lvImage, &lvImageInfo);
  //LVImage->address = myImage;
  //Copy filled Image to Buffer created from LabVIEW
  for (y = 0; y < LVHeight; ++y)
  {
    memcpy((char *)lvImageInfo.imageStart + y * lvImageInfo.pixelsPerLine,
           (char *)myImageInfo.imageStart + y * myImageInfo.pixelsPerLine, LVWidth);
  }
  imaqDispose(myImage);
  return 0;
}
The Output:
Then I tried to implement the same for Grayscale U16 by changing the following lines:
pixel.grayscale = 32000;
myImage = imaqCreateImage(IMAQ_IMAGE_U16, 3);
.
.
.
for(y=0;y<LVHeight;++y)
{
memcpy((unsigned short*)lvImageInfo.imageStart + y * lvImageInfo.pixelsPerLine,
            (unsigned short*)myImageInfo.imageStart + y * myImageInfo.pixelsPerLine, LVWidth);
}
I get the following Image with a pixel value of 32000 from 0 to 49th columns and pixel value of 0 from 50 to 99 as output!
Then I tried the following:
pixel.grayscale = 32000;
myImage = imaqCreateImage(IMAQ_IMAGE_U16, 3);
.
.
.
for(y=0;y<LVHeight*2;++y)
{
  memcpy((char*)lvImageInfo.imageStart + y * lvImageInfo.pixelsPerLine,
            (char*)myImageInfo.imageStart + y * myImageInfo.pixelsPerLine, LVWidth*2);
}
I get the following Blank Image with a pixel value of 32000 as output:
I even tried instead of copying the data, I just swapped the address and removing the Dispose part:
LVImage->address = myImage;
//for(y=0;y<LVHeight*2;++y)
//{
//memcpy((char*)lvImageInfo.imageStart + y * lvImageInfo.pixelsPerLine,
//            (char*)myImageInfo.imageStart + y * myImageInfo.pixelsPerLine, LVWidth*2);
//ImaqDispose(myImage);
Still, I'm getting the same blank Image!
Can anyone help me in copying the data? Any help would be really appreciated... Thanks!
Solved! Go to Solution.
09-22-2021 10:25 AM
Using an image to a function in a dll is not that straightforward.
For such tasks, we use IMAQ GetImagePixelPtr.vi
You can check this example.
Sami
09-26-2021 04:16 AM
Hi Sami,
Thank you for your time and effort. 🙂
I totally understand that this isn't a straightforward approach. But the method I used here is almost the same. There are many threads confirming this method.
Here, Take a look at this thread.
Also, I figured out why the Image is blank! It's because I haven't used the16-Bit Display Mappingoption. Once I chose theMost Significant Bitoption. I was able to see the actual pixels with the appropriate gray values.
09-26-2021 02:00 PM
Now, I'm trying to actually acquire the images from Framegrabber. It writes the pixel data into a .raw file. I need to read the pixel data from the file and then copy that to LabVIEW's Image Buffer.
#include <iostream>
#include "nivision.h"
#include<fstream>
using namespace std;
int readRawFile(unsigned short* pSrc, int Width, int Height)
{
  ifstream file;
  file.open("test.raw", ios::in | ios::binary);
  if (file.is_open() == true)
  {
    file.read(reinterpret_cast<char*>(pSrc), Width * Height * 2);
    file.close();
    return 1;
  }
  else return 0;
}
int main()
{
  Image* myImage;
  PixelValue pixel;
  ImageInfo myImageInfo;
  int LVHeight, LVWidth, i,handle,y;
  LVHeight = 3052;
  LVWidth = 2500;
  pixel.grayscale = 65535;
  unsigned short* psrc=new unsigned short(LVHeight * LVWidth);
  readRawFile(pSrc, LVWidth, LVHeight);
  myImage = imaqCreateImage(IMAQ_IMAGE_U16, 3);
  imaqSetImageSize(myImage, LVWidth, LVHeight);
  imaqFillImage(myImage, pixel, NULL);
  imaqGetImageInfo(myImage, &myImageInfo);
  //Display Filled Image.
  imaqGetWindowHandle(&handle);
  imaqDisplayImage(myImage, handle, 1);
  std::cin >>i;
  std::cout << "Height = " <<LVHeight << "\tWidth = " << LVWidth 
            <<std::endl;
  std::cout << "PixelsPerLine = " << 
  myImageInfo.pixelsPerLine<<std::endl;
  for (y = 0; y < LVHeight; ++y)
  {
      memcpy((unsigned short*)myImageInfo.imageStart + y * 
              myImageInfo.pixelsPerLine, pSrc + LVWidth * y, LVWidth 
               *sizeof(unsigned short));
  }
  imaqDisplayImage(myImage, handle, 1);
  std::cin >>i;
  imaqDispose(myImage);
  delete pSrc;
} 
When I run this code, I get the following Access Violation Error:
Exception thrown at 0x00007FFF9D821470 (vcruntime140.dll) in
TestApplication.exe: 0xC0000005: Access violation reading location 
0x0000019EA712F320.
After about 180 Iterations, I'm getting this error! Of course, from the error description, the problem is with the pSrc pointer... But I have no idea how to resolve this!
I Observed that Vision DLL allocates some extra memory based on the given image width. If the image width is 2500 pixels, The pixelsPerLine returns 2560 pixels. When I tried printing, The unused pixels were filled with 0.
Kindly help me to resolve this issue... Thanks!
09-28-2021 02:34 AM
Image lines include "your pixels" but also borders and padding bytes.
You will have full explanation in the NI Vision Concept manuals that is usually located in C:\Program Files (x86)\National Instruments\Vision\Help .
Below is a creenshot of the chapter dealing with image representation in memory :
Hope this helps,
Sami
09-29-2021 02:16 AM
@Achuthaperumal wrote:When I run this code, I get the following Access Violation Error:
Exception thrown at 0x00007FFF9D821470 (vcruntime140.dll) in TestApplication.exe: 0xC0000005: Access violation reading location 0x0000019EA712F320.After about 180 Iterations, I'm getting this error! Of course, from the error description, the problem is with the
pSrcpointer... But I have no idea how to resolve this!
Turns out, The issue is because of an invalid memory allocation!
unsigned short *psrc=new unsigned short[LVWidth * LVHeight];
 Once I changed this, I was able to see the image. Also, an additional note, add imaqSetWindowThreadPolicy(IMAQ_SEPARATE_THREAD)  at the start of the function to stop your display windows from appearing to be unresponsive.
C++ - How to Copy raw U8 | U16 data to LabVIEW Vision Image Buffer using memcpy - Stack Overflow