How can I save a 16 bit image (PNG or TIFF) without any compression? What is the syntax?
After 2 years OpenCV can save 16-bit TIFFs (2.4.x versions) with compression (LZW). But it also supports undocumented parameter TIFFTAG_COMPRESSION in function
bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector<int>() )
It can be set to COMPRESSION_LZMA, for example (and working correctly).
You can use COMPRESSION_NONE as a value for this parameter (also you have to set TIFFTAG_ROWSPERSTRIP parameter to image height).
But OpenCV still generates incorrect TIFF in that case (trying to set TIFFTAG_COMPRESSION to COMPRESSION_NONE) even in 2.4.9 version.
After looking at OpenCV sources I found 2 ways to overcome this restriction:
Recompile OpenCV with changes in "opencv/modules/imgcodecs/src/grfmt_tiff.cpp" - guys from OpenCV added parameter for compression, but forgot about the fact that libtiff can't set predictor in TIFF handle if we don't want compression. You should find this code
if ( !TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width)
|| !TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height)
|| !TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, bitsPerChannel)
|| !TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, compression)
|| !TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, colorspace)
|| !TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, channels)
|| !TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)
|| !TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, rowsPerStrip)
|| !TIFFSetField(pTiffHandle, TIFFTAG_PREDICTOR, predictor)
)
{
TIFFClose(pTiffHandle);
return false;
}
and change it to
if ( !TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width)
|| !TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height)
|| !TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, bitsPerChannel)
|| !TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, compression)
|| !TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, colorspace)
|| !TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, channels)
|| !TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)
|| !TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, rowsPerStrip)
)
{
TIFFClose(pTiffHandle);
return false;
}
if (compression != COMPRESSION_NONE
&& !TIFFSetField(pTiffHandle, TIFFTAG_PREDICTOR, predictor)
)
{
TIFFClose(pTiffHandle);
return false;
}
after this OpenCV can save compressed and uncompressed TIFFs (depends on parameters to imwrite
).
The other way is direct using libtiff in your application for saving TIFFs. Of course you need implement writing function in such case. For windows you should compile libtiff, but it is rather simple task (libtiff contains makefiles for many compilers and perfectly compiles in MinGW and MSVC, 32 and 64 bit).
At least from 2.1 (haven't used older versions) cvSaveImage saves a single channel 16b depth image without problems. I usualy use .png for this.
This would get you a 16b image with "somedata":
IplImage* image = cvCreateImage(cvSize(100,100),16,1);
memset(image->imageData,someData,image->width*image->height*2);
cvSaveImage("image.png",image);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With