Machine Vision

cancel
Showing results for 
Search instead for 
Did you mean: 

C++ : Writing 16bit PNG files appear dark

In my Visual C++ application I call imaqWritePNGFile() to save image to disk acquired from another source. The image is 16 bit unsigned data that I have to first convert to a signed value by subtracting 32768 from each unsigned short in the data buffer. I have verified that the resulting value is correct. It appears that when the image has very little dynamic range, lets say 8k right around 75% gray, the resulting image appears very dark. If I take that same image and add a single full white and full black pixel the image it turns out correct after saving it. Below is the code I am using with the hack that makes the image look correct.

I have attached 2 PNG files that show the problem I am seeing.

Thanks,
Ala
n Spurgeon
Synapse
206-919-3585




void VisionClass::WritePNGImage( unsigned short *pBuffer, int width, int height, const char *pFileName )
{
unsigned short *tempDataPtr = pBuffer;
long counter = width * height;

// If we don't have a cached Image create one.
if( NULL == m_pWriteImage )
if( NULL == (m_pWriteImage = imaqCreateImage( IMAQ_IMAGE_I16, 0 )) )
{
// Something went wrong. Figure it out.
assert( false );
}

// Hack to make image appear correct when saved out.
pBuffer[0] = 0xffff;
pBuffer[1] = 0;

// IMAQ requires that the image data be signed so we have to shift the
// values down by 32768. That makes zero the equivelent to 50% gray.
while( counter-- )
*tempDataPtr++ = stemp;

// Let IMAQ fill out the image structure for the source.
if( imaqArrayToImage( m_pWriteImage, pBuffer, width, height ) == 0 )
{
// Something went wrong. Figure it out.
assert( false );
}

// Write image out in PNG format with stand
ard compression.
if( imaqWritePNGFile( m_pWriteImage, pFileName, 750, NULL ) == 0 )
{
// Something went wrong. Figure it out.
assert( false );
}
}
Download All
0 Kudos
Message 1 of 4
(3,908 Views)
The above code was incorrect due to my fiddling. Here is the correct code that shows the problem..

void VisionClass::WritePNGImage( unsigned short *pBuffer, int width, int height, const char *pFileName )
{
unsigned short *tempDataPtr = pBuffer;
long counter = width * height;

// If we don't have a cached Image create one.
if( NULL == m_pWriteImage )
if( NULL == (m_pWriteImage = imaqCreateImage( IMAQ_IMAGE_I16, 0 )) )
{
// Something went wrong. Figure it out.
assert( false );
}

// Hack to make image appear correct when saved out.
pBuffer[0] = 0xffff;
pBuffer[1] = 0;

// IMAQ requires that the image data be signed so we have to shift the
// values down by 32768. That makes zero the equivelent to 50% gray.
while( counter-- )

*tempDataPtr++ -= 32768;

// Let IMAQ fill out the image structure for the source.
if( imaqArrayToImage( m_pWriteImage, pBuffer, width, height ) == 0 )
{
// Something went wrong. Figure it out.
assert( false );
}

// Write image out in PNG format with standard compression.
if( imaqWritePNGFile( m_pWriteImage, pFileName, 750, NULL ) == 0 )
{
// Something went wrong. Figure it out.
assert( false );
}
}
0 Kudos
Message 2 of 4
(3,908 Views)
Hello,
I was looking at your code and one suggestion I would give is to change the pixel data type from a unsigned unshort to long. This will accommodate the signed 16 bit converted data.

Regards

R. Blake
Applications Engineering
National Instruments
Director of Engineering
G Systems, www.gsystems.com
Certified LabVIEW Architect
Certified LabVIEW Embedded Systems Developer
Certified Professional Instructor
GCentral
0 Kudos
Message 3 of 4
(3,908 Views)
Thanks for the suggestion but I tried it earlier and it made no difference. I wrote a sample program to verify that the conversion was working as expected in the end if I use the long method or the short method the data is still the same.

For some reason setting one pixel to white and another to black gives me a good image. However this is a hack and I end up with 2 pixels that are artifical.
0 Kudos
Message 4 of 4
(3,908 Views)