LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

RGBQUAD issue

Hello, I am writing a DLL with Visual C++ to be used with LabVIEW's Call External Library Node.  In it, I must set up BITMAPINFO information and I run into problems when trying to alter the RGBQUAD information.  Here are the exact lines of code that I have found to be causing issues:
 
BITMAPINFO* bminfo;
bminfo = new BITMAPINFO();
for(int j=0; j<256;j++)
{

(bminfo->bmiColors[j]).rgbBlue = j;

(bminfo->bmiColors[j]).rgbGreen = j;

(bminfo->bmiColors[j]).rgbRed = j;

(bminfo->bmiColors[j]).rgbReserved = 0;

}

delete bminfo;

There is much more processing here but even when commenting out the entire file except for these lines the same things happen.  These lines were copied from an SDK provided by the makers of the camera that we are using LabVIEW to control.  With this code, the program works fine and produces a great image.  However, a memory error occurs at runtime in the VI with the following information:

Debug Error!

Program: C:\Program Files\National Instruments\LabVIEW 7.0\LanView.exe

DAMAGE: after Normal Block (#47) at 0x05182188

 

Upon clicking ignore, the program executes and produces an image from the camera.  Yet if I try to click run again, the following error message occurs:

LABVIEW: An exception occurred within the external code called by the Call Library Node.  This might have corrupted LabVIEW's memory.  Save any work to a new location and restart LabVIEW.

VI "RUNCAM.vi" was stopped at Call Library Function Node 0x188 of SubVI "RUNCAM.vi".

 

Whether I run the VI again or not, about 10 seconds after these error messages LabVIEW crashes to the desktop without a prompt.  If I remove the "delete bminfo;" line, the first error message does not occur, but the second one does if I attempt to run the VI again without restarting LabVIEW.  This method also crashes LabVIEW to the desktop.  It seems that when I change the RGBQUAD information, LabVIEW cannot properly release the bitmapinfo's memory and crashes with a memory overflow.  Is there any reason why this code would do this?  When I remove the code everything runs fine except the image is quite distorted.  Is there any other way to set up the RGBQUAD information?  Thanks in advance for any help on this matter.

 

Andy Briggs

Department of Physics and Astronomy

Johns Hopkins University

0 Kudos
Message 1 of 14
(5,106 Views)
Hey Andy,
 
According to an API reference a BITMAPINFO structure is the following:
 
typedef struct tagBITMAPINFO { // bmi 
   BITMAPINFOHEADER bmiHeader;
   RGBQUAD          bmiColors[1];
} BITMAPINFO;
 
Where bmiHeader is:
typedef struct tagBITMAPINFOHEADER{ // bmih 
   DWORD  biSize;
   LONG   biWidth;
   LONG   biHeight;
   WORD   biPlanes;
   WORD   biBitCount
   DWORD  biCompression;
   DWORD  biSizeImage;
   LONG   biXPelsPerMeter;
   LONG   biYPelsPerMeter;
   DWORD  biClrUsed;
   DWORD  biClrImportant;
} BITMAPINFOHEADER;
 
and bmiColors is
typedef struct tagRGBQUAD { // rgbq 
    BYTE    rgbBlue;
    BYTE    rgbGreen;
    BYTE    rgbRed;
    BYTE    rgbReserved;
} RGBQUAD;
 
However in your code you do a loop from 0 to 255..
I confess to not know alot about the DLL you are using but it should be obvious from the declarations that you are over-writing memory (did not allocate enough).  Perhaps you need to allocate an array of 256 RGBQUADs instead?
0 Kudos
Message 2 of 14
(5,090 Views)

Thank you for your quick replay Chaos.  I thought I would provide some information about the DLL.  It controls a Camera connected to the computer by use of a DLL (called Pcclib.dll) provided by the manufacturer.  However, I must write my own DLL that can be run in LabVIEW and calls functions from Pcclib.dll to control the camera and record images.  Before I can store images from the camera I must set up the bitmap information.  For image processing a class called CImageData is used so setting up image processing would be done as such:

CImageData* m_imagedata;

m_imagedata = new CImageData();

m_imagedata->Init(imagesize); //secures image data buffer and sets up BITMAPFILEHEADER information

 

BITMAPINFO* bminfo;
bminfo = new BITMAPINFO();

//set up BITMAPINFO structure

bminfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bminfo->bmiHeader.biWidth = im_width;
bminfo->bmiHeader.biHeight = im_height;
bminfo->bmiHeader.biPlanes = 1;
bminfo->bmiHeader.biBitCount = 8;
bminfo->bmiHeader.biCompression = 0;
bminfo->bmiHeader.biSizeImage = 0;
bminfo->bmiHeader.biXPelsPerMeter = 0;
bminfo->bmiHeader.biYPelsPerMeter = 0;
bminfo->bmiHeader.biClrUsed = 256;
bminfo->bmiHeader.biClrImportant = 0;

//now must set up RGBQUAD information, problems here
for(int j=0; j<256;j++)
{
(bminfo->bmiColors[j]).rgbBlue = j;
(bminfo->bmiColors[j]).rgbGreen = j;
(bminfo->bmiColors[j]).rgbRed = j;
(bminfo->bmiColors[j]).rgbReserved = 0;

}

//setup bitmap info

m_imagedata->SetBmpInfo(bminfo);

From here I transfer the frame and save it to disk.  However, I must use the type BITMAPINFO* for the SetBmpInfo function.  I could do something like this:

RGBQUAD bmRGBquad [256];
for(int i=0;i<256;i++)
{
 bmRGBquad[i].rgbBlue = i;
 bmRGBquad[i].rgbGreen = i;
 bmRGBquad[i].rgbRed = i;
 bmRGBquad[i].rgbReserved = 0;
}

But this:

bminfo->bmiColors = bmRGBquad;

will not work since as you pointed out, bmiColors has size 1.  This does not make sense as I specifically entered:

bminfo->bmiHeader.biBitCount = 8;

so as can be seen here: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_1rw2.asp when it talks about biBitCount it says that bmicolors should contain 256 entries.  It doesn't seem possible to dynamically allocate more memory for bmiColors though.  Yet I must be able to change this property before passing bminfo into the SetBmpInfo function.  I admit I am somewhat new to programming and LabVIEW, yet sadly I am the most experienced in my lab.  Again, thank you for your help.

 

Andy Briggs

Department of Physics and Astronomy

Johns Hopkins University

0 Kudos
Message 3 of 14
(5,084 Views)
Value:
8
Meaning:
The bitmap has a maximum of 256 colors, and the bmiColors member of BITMAPINFO contains up to 256 entries. In this case, each byte in the array represents a single pixel.
 
I read the above line as represented below... (an array of up to 256 bytes)
 
typedef struct tagBITMAPINFO {
   BITMAPINFOHEADER bmiHeader; 
   BYTE             bmiColors[256];
} BITMAPINFO2;
0 Kudos
Message 4 of 14
(5,079 Views)
I actually interpreted it a different way.  A DIB consists of two aprts, a BITMAPINFO structure specifying the information of the bmp file followed by an array of bytes defining the pixels of the image, something such as this:
 
typedef struct tagBITMAP {
  LONG   bmType;
  LONG   bmWidth;
  LONG   bmHeight;
  LONG   bmWidthBytes;
  WORD   bmPlanes;
  WORD   bmBitsPixel;
  LPVOID bmBits;
} BITMAP, *PBITMAP;
 
with bmBits being a pointer to a 1-D array of bytes specifying the character values of the bitmap image.  By setting biBitcount value to 8 every pixel is represented by one byte here, as opposed to a 4-bit image.  But even still shouldn't the value 8 force the rgbquad array to contain 256 values?
0 Kudos
Message 5 of 14
(5,078 Views)
Ive never used this structure before so I am making an educated guess 😃
 
Heres another way to look at it from my point of view:
From MSDN - each byte in the array represents a single pixel
 
If I re-arange the above I get:
each pixel in the array is represented by each byte
 
And if there are 256 entries thats an array of 256 bytes.  But, like I said above, this is new ground for me so I could very well be mistaken... since your way (seems) not to work, if you had the time and nothing else to loose you could try it and see... hopefully someone else might shed some much needed light on the subject.
0 Kudos
Message 6 of 14
(5,071 Views)
Muah ha!
 
Ok, looks like we both might be right.  You seem to be right on MSDNs wording.  But I still think you are over-writing memory because its not being declared properly.  From this site for VB they have this declaration sequence.
 
Smiley above = : D (without middle space)
 
Type RGBQUAD
    rgbBlue As Byte
    rgbGreen As Byte
    rgbRed As Byte
    rgbReserved As Byte
End Type
Type BITMAPINFO
    bmiHeader As BITMAPINFOHEADER
    bmiColors(0 To 255) As RGBQUAD
End Type
 

Message Edited by Chaos on 08-05-2005 03:29 PM

0 Kudos
Message 7 of 14
(5,067 Views)
This definately seems to be the issue, but I'm afraid I know virtually no VB.  How might I make this declaration in C++?  If instead of looping from 0 to 255 I just assign rgbGreen[0] = 0 and so on, which is the first iteration of the loop, and then stop so there are no memory issues the resulting image is just a flat grey.  It seems weird that it will allow me to assign the larger values of the array in the first place because, disregarding the memory issues, it gives me a perfect image when I do this.
0 Kudos
Message 8 of 14
(5,059 Views)
I cannot quite figure out what MSDN is saying sometimes.  This is the latest information that confuses me:
Under remarks it says:

Note  The bmiColors member should not contain palette indexes if the bitmap is to be stored in a file or transferred to another application.

Unless the application has exclusive use and control of the bitmap, the bitmap color table should contain explicit RGB values.

Saving it is exactly what I need to do so am I right in interpretting this as I need to give specific RGB values?

0 Kudos
Message 9 of 14
(5,058 Views)
From C it should look like
 
typedef struct tagBITMAPINFO { // bmi 
   BITMAPINFOHEADER bmiHeader;
   RGBQUAD          bmiColors[256];
} BITMAPINFO;
0 Kudos
Message 10 of 14
(5,055 Views)