Sunday, September 20, 2015

How to write a multipage TIFF file

Today, I just realized that it is a pain to write multipage TIFF images with OpenCV. I assume that it is not officially supported?

I wrote this simple sample code for all medical students with almost no programming experience! This code will allow you to dump your image sequence into a multipage tiff (or tiff stack?) that is readable by any machine or tools such as Matlab.

Here is a link to the code:
https://gist.github.com/anonymous/e827730f06aa7066afe8

And you can preview it here. But I don't recommend copying directly here just in case the symbols or spacing got messed up.

#include "tiffio.h"
#include "stdio.h"
#include "stdlib.h"
#include <string.h> /* memset */
#include <unistd.h> /* close */

int main(int argc, char* argv[])
{
    TIFF *out = TIFFOpen("new.tiff","w") ;
   
    if (out)
    {
        const int NPAGES = 10;
        int page;
        for (page = 0; page < NPAGES; page++){
            uint32 imagelength = 100;
            uint32 imagewidth=200;
            uint8 * buf;
            uint32 row, col, n;
            uint16 config, nsamples = 3;
            config = PLANARCONFIG_CONTIG ;

            TIFFSetField(out, TIFFTAG_IMAGELENGTH, imagelength);
            TIFFSetField(out, TIFFTAG_IMAGEWIDTH, imagewidth);
            TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
            TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, nsamples);
            TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_LZW) ;
            TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8) ;
            TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, imagewidth*nsamples));

            /* We are writing single page of the multipage file */
            TIFFSetField(out, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
            TIFFSetField(out, TIFFTAG_PAGENUMBER, page, NPAGES);
          
            printf("writing %d x %d, nsamples %d", imagewidth, imagelength, nsamples);

            buf = new uint8 [imagewidth*nsamples] ;

            for (row = 0; row < imagelength; row++){

                for(col=0; col < imagewidth; col++){
                    for(n = 0 ; n < nsamples ; ++n)
                    {  
                        //writing data -- replace with your own data
                        buf[col*nsamples+n] = page*row % 255 ;
                    }
                }
                if (TIFFWriteScanline(out, buf, row) != 1 )
                {
                    printf("Unable to write a row\n") ;
                    break ;
                }
            }
            TIFFWriteDirectory(out);
            _TIFFfree(buf);
        }
        TIFFClose(out);
    }
    return 0;
}

To compile it in Mac (assuming you have Macport), just run this in command line...

g++ main.cpp -I /opt/local/include -L/opt/local/lib -ltiff

... Enjoy!