libtiff RGB image to greyscale + loading and saving
This example shows you how to load a RGB tiff image, convert it to greyscale and save it as 32 and 8bit greyscale images. It will also write the same RGB image to another file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | #include "tiffio.h" #include <iostream> #include <math.h> #include <vector> using namespace std; class Image { public : Image() { } void load_tiff(string input_filename) { m_image_data.clear(); TIFF* tif = TIFFOpen(input_filename.c_str(), "r" ); if (tif) { uint32 w, h; size_t npixels; uint32* raster; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); npixels = w * h; m_width = w; m_height = h; raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32)); if (raster != NULL) { if (TIFFReadRGBAImageOriented(tif, w, h, raster,ORIENTATION_TOPLEFT, 0)) { for ( size_t n=0;n<npixels;n++) m_image_data.push_back(raster[n]); } _TIFFfree(raster); } TIFFClose(tif); } } void save_tiff_rgb(string output_filename) { TIFF *output_image; // Open the TIFF file if ((output_image = TIFFOpen(output_filename.c_str(), "w" )) == NULL){ cerr << "Unable to write tif file: " << output_filename << endl; } // We need to set some values for basic tags before we can add any data TIFFSetField(output_image, TIFFTAG_IMAGEWIDTH, m_width); TIFFSetField(output_image, TIFFTAG_IMAGELENGTH, m_height); TIFFSetField(output_image, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(output_image, TIFFTAG_SAMPLESPERPIXEL, 4); TIFFSetField(output_image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(output_image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); TIFFSetField(output_image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); // Write the information to the file TIFFWriteEncodedStrip(output_image, 0, &m_image_data[0], m_width*m_height * 4); // Close the file TIFFClose(output_image); } void save_tiff_grey_32bit(string output_filename) { TIFF *output_image; // Open the TIFF file if ((output_image = TIFFOpen(output_filename.c_str(), "w" )) == NULL){ cerr << "Unable to write tif file: " << output_filename << endl; } // We need to set some values for basic tags before we can add any data TIFFSetField(output_image, TIFFTAG_IMAGEWIDTH, m_width); TIFFSetField(output_image, TIFFTAG_IMAGELENGTH, m_height); TIFFSetField(output_image, TIFFTAG_BITSPERSAMPLE, 32); TIFFSetField(output_image, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(output_image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(output_image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); TIFFSetField(output_image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); // Write the information to the file TIFFWriteEncodedStrip(output_image, 0, &m_image_data[0], m_width*m_height * 4); // Close the file TIFFClose(output_image); } void save_tiff_grey_8bit(string output_filename) { TIFF *output_image; // Open the TIFF file if ((output_image = TIFFOpen(output_filename.c_str(), "w" )) == NULL){ cerr << "Unable to write tif file: " << output_filename << endl; } // We need to set some values for basic tags before we can add any data TIFFSetField(output_image, TIFFTAG_IMAGEWIDTH, m_width); TIFFSetField(output_image, TIFFTAG_IMAGELENGTH, m_height); TIFFSetField(output_image, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(output_image, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(output_image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(output_image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); TIFFSetField(output_image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); // convert data to 8bit vector< uint8_t > data; for ( size_t n=0;n<m_image_data.size();n++) { data.push_back(255-(m_image_data[n]/(256*256*256))); } // Write the information to the file TIFFWriteEncodedStrip(output_image, 0, &data[0], m_width*m_height); // Close the file TIFFClose(output_image); } void make_greyscale() { for ( size_t n=0;n<m_image_data.size();n++) { double r = TIFFGetR(m_image_data[n]); double g = TIFFGetG(m_image_data[n]); double b = TIFFGetB(m_image_data[n]); m_image_data[n] = grey * 256 * 256 * 256; } } vector< uint32_t > m_image_data; size_t m_width; size_t m_height; }; int main( int argc, char * argv[]) { Image input; input.load_tiff(string(argv[1])); input.save_tiff_rgb(string(argv[2])); input.make_greyscale(); input.save_tiff_grey_32bit(string(argv[3])); input.save_tiff_grey_8bit(string(argv[4])); } |
Compile as:
1 | g++ makegrey.cpp -ltiff |
And run as:
1 | . /a .out inputfilename.tif rgb.tif 8bitgrey.tif 32bitgrey.tif |
Note: The 8bit version is slightly different than the 32bit version. It converts the data such that 0 represents white. This is because Preview.app, at least in MacOS X Lion, does not seem to be able to cope with 0 being black.
This has not been applied to the 32bit output, so this will display incorrectly in Preview. However it will display correctly in Imagemagick.