Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing 16 bit uncompressed image using OpenCV

Tags:

c++

image

opencv

How can I save a 16 bit image (PNG or TIFF) without any compression? What is the syntax?

like image 746
EyalG Avatar asked Aug 22 '12 12:08

EyalG


2 Answers

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:

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

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

like image 186
avtomaton Avatar answered Sep 22 '22 06:09

avtomaton


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);
like image 28
p.streef Avatar answered Sep 23 '22 06:09

p.streef