#include #include #include #include #include #include #include #include #include /**************************************************************************** * * Follows is code extracted from the simage library. Original Authors: * * Systems in Motion, * * * Peder Blekken * Morten Eriksen * Marius Bugge Monsen * * The original COPYING notice * * All files in this library are public domain, except simage_rgb.cpp which is * Copyright (c) Mark J Kilgard . I will contact Mark * very soon to hear if this source also can become public domain. * * Please send patches for bugs and new features to: . * * Peder Blekken * * * Ported into the OSG as a plugin, Robert Osfield Decemeber 2000. * Note, reference above to license of simage_rgb is not relevent to the OSG * as the OSG does not use it. Also for patches, bugs and new features * please send them direct to the OSG dev team rather than address above. * **********************************************************************/ #include #include #include #include #define ERR_NO_ERROR 0 #define ERR_OPEN 1 #define ERR_READ 2 #define ERR_MEM 3 #define ERR_UNSUPPORTED 4 #define ERR_TIFFLIB 5 /* Functions to read TIFF image from memory * */ tsize_t libtiffStreamReadProc(thandle_t fd, tdata_t buf, tsize_t size) { std::istream *fin = (std::istream*)fd; fin->read((char*)buf,size); if(fin->bad()) return -1; if(fin->gcount() < size) return 0; return size; } tsize_t libtiffStreamWriteProc(thandle_t, tdata_t, tsize_t) { return 0; } toff_t libtiffStreamSeekProc(thandle_t fd, toff_t off, int i) { std::istream *fin = (std::istream*)fd; toff_t ret; switch(i) { case SEEK_SET: fin->seekg(off,std::ios::beg); ret = fin->tellg(); if(fin->bad()) ret = 0; break; case SEEK_CUR: fin->seekg(off,std::ios::cur); ret = fin->tellg(); if(fin->bad()) ret = 0; break; case SEEK_END: fin->seekg(off,std::ios::end); ret = fin->tellg(); if(fin->bad()) ret = 0; break; default: ret = 0; break; } return ret; } int libtiffStreamCloseProc(thandle_t) { return 0; } toff_t libtiffStreamSizeProc(thandle_t fd) { std::istream *fin = (std::istream*)fd; std::streampos curPos = fin->tellg(); fin->seekg(0, std::ios::end); toff_t size = fin->tellg(); fin->seekg(curPos, std::ios::beg); return size; } int libtiffStreamMapProc(thandle_t, tdata_t*, toff_t*) { return 0; } void libtiffStreamUnmapProc(thandle_t, tdata_t, toff_t) { } /* Functions to write TIFF image from memory * */ tsize_t libtiffOStreamReadProc(thandle_t, tdata_t, tsize_t) { return 0; } tsize_t libtiffOStreamWriteProc(thandle_t fd, tdata_t buf, tsize_t size) { std::ostream *fout = (std::ostream*)fd; fout->write((const char*)buf,size); if(fout->bad()) { return -1; } return size; } toff_t libtiffOStreamSizeProc(thandle_t fd) { std::ostream *fout = (std::ostream*)fd; std::streampos curPos = fout->tellp(); fout->seekp(0, std::ios::end); toff_t size = fout->tellp(); fout->seekp(curPos, std::ios::beg); return size; } toff_t libtiffOStreamSeekProc(thandle_t fd, toff_t off, int i) { std::ostream *fout = (std::ostream*)fd; toff_t ret; switch(i) { case SEEK_SET: fout->seekp(off,std::ios::beg); ret = fout->tellp(); if(fout->bad()) ret = 0; break; case SEEK_CUR: fout->seekp(off,std::ios::cur); ret = fout->tellp(); if(fout->bad()) ret = 0; break; case SEEK_END: fout->seekp(off,std::ios::end); ret = fout->tellp(); if(fout->bad()) ret = 0; break; default: ret = 0; break; } return ret; } static int tifferror = ERR_NO_ERROR; int simage_tiff_error(char * buffer, int buflen) { switch (tifferror) { case ERR_OPEN: strncpy(buffer, "TIFF loader: Error opening file", buflen); break; case ERR_MEM: strncpy(buffer, "TIFF loader: Out of memory error", buflen); break; case ERR_UNSUPPORTED: strncpy(buffer, "TIFF loader: Unsupported image type", buflen); break; case ERR_TIFFLIB: strncpy(buffer, "TIFF loader: Illegal tiff file", buflen); break; } return tifferror; } static void tiff_error(const char*, const char*, va_list) { // values are (const char* module, const char* fmt, va_list list) /* FIXME: store error message ? */ } static void tiff_warn(const char *, const char *, va_list) { // values are (const char* module, const char* fmt, va_list list) /* FIXME: notify? */ } static int checkcmap(int n, uint16* r, uint16* g, uint16* b) { while (n-- > 0) if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) return (16); /* Assuming 8-bit colormap */ return (8); } static void invert_row(unsigned char *ptr, unsigned char *data, int n, int invert, uint16 bitspersample) { // osg::notify(osg::NOTICE)<<"invert_row "<setImage(s,t,r, internalFormat, pixelFormat, dataType, imageData, osg::Image::USE_NEW_DELETE); return pOsgImage; } WriteResult::WriteStatus writeTIFStream(std::ostream& fout, const osg::Image& img) const { //Code is based from the following article on CodeProject.com //http://www.codeproject.com/bitmap/BitmapsToTiffs.asp TIFF *image; int samplesPerPixel; int bitsPerSample; uint16 photometric; image = TIFFClientOpen("outputstream", "w", (thandle_t)&fout, libtiffOStreamReadProc, //Custom read function libtiffOStreamWriteProc, //Custom write function libtiffOStreamSeekProc, //Custom seek function libtiffStreamCloseProc, //Custom close function libtiffOStreamSizeProc, //Custom size function libtiffStreamMapProc, //Custom map function libtiffStreamUnmapProc); //Custom unmap function if(image == NULL) { return WriteResult::ERROR_IN_WRITING_FILE; } switch(img.getPixelFormat()) { case GL_LUMINANCE: case GL_ALPHA: photometric = PHOTOMETRIC_MINISBLACK; samplesPerPixel = 1; break; case GL_LUMINANCE_ALPHA: photometric = PHOTOMETRIC_MINISBLACK; samplesPerPixel = 2; break; case GL_RGB: photometric = PHOTOMETRIC_RGB; samplesPerPixel = 3; break; case GL_RGBA: photometric = PHOTOMETRIC_RGB; samplesPerPixel = 4; break; default: return WriteResult::ERROR_IN_WRITING_FILE; break; } switch(img.getDataType()){ case GL_FLOAT: TIFFSetField(image, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, 1); bitsPerSample = 32; break; case GL_SHORT: TIFFSetField(image, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); bitsPerSample = 16; break; default: bitsPerSample = 8; break; } TIFFSetField(image, TIFFTAG_IMAGEWIDTH,img.s()); TIFFSetField(image, TIFFTAG_IMAGELENGTH,img.t()); TIFFSetField(image, TIFFTAG_BITSPERSAMPLE,bitsPerSample); TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL,samplesPerPixel); TIFFSetField(image, TIFFTAG_PHOTOMETRIC, photometric); TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS); TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); //uint32 rowsperstrip = TIFFDefaultStripSize(image, -1); //TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, rowsperstrip); // Write the information to the file for(int i = 0; i < img.t(); ++i) { TIFFWriteScanline(image,(tdata_t)img.data(0,img.t()-i-1),i,0); } // Close the file TIFFClose(image); return WriteResult::FILE_SAVED; } virtual ReadResult readObject(std::istream& fin,const osgDB::ReaderWriter::Options* options =NULL) const { return readImage(fin, options); } virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options =NULL) const { return readImage(file, options); } virtual ReadResult readImage(std::istream& fin,const osgDB::ReaderWriter::Options* =NULL) const { return readTIFStream(fin); } virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const { std::string ext = osgDB::getLowerCaseFileExtension(file); if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; std::string fileName = osgDB::findDataFile( file, options ); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; std::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary); if(!istream) return ReadResult::FILE_NOT_HANDLED; ReadResult rr = readTIFStream(istream); if(rr.validImage()) rr.getImage()->setFileName(file); return rr; } virtual WriteResult writeImage(const osg::Image& img,std::ostream& fout,const osgDB::ReaderWriter::Options* /*options*/) const { WriteResult::WriteStatus ws = writeTIFStream(fout,img); return ws; } virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options *options) const { std::string ext = osgDB::getFileExtension(fileName); if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; std::ofstream fout(fileName.c_str(), std::ios::out | std::ios::binary); if(!fout) return WriteResult::ERROR_IN_WRITING_FILE; return writeImage(img,fout,options); } }; // now register with Registry to instantiate the above // reader/writer. REGISTER_OSGPLUGIN(tiff, ReaderWriterTIFF)