From Farshid Lashkari, support for writing to istream for the the TIFF plugin and support for

controlling PNG compression level via the the ReaderWriter::Option string "PNG_COMPRESSION <level>"
This commit is contained in:
Robert Osfield
2006-03-02 20:39:20 +00:00
parent 8796f37acb
commit cdc8b13f14
2 changed files with 179 additions and 3 deletions

View File

@@ -8,6 +8,8 @@
#include <osgDB/FileUtils>
#include <osgDB/FileNameUtils>
#include <sstream>
using namespace osg;
extern "C"
@@ -54,7 +56,7 @@ class ReaderWriterPNG : public osgDB::ReaderWriter
virtual const char* className() const { return "PNG Image Reader/Writer"; }
virtual bool acceptsExtension(const std::string& extension) const { return osgDB::equalCaseInsensitive(extension,"png"); }
WriteResult::WriteStatus writePngStream(std::ostream& fout, const osg::Image& img) const
WriteResult::WriteStatus writePngStream(std::ostream& fout, const osg::Image& img, int compression_level) const
{
png_structp png = NULL;
png_infop info = NULL;
@@ -72,6 +74,9 @@ class ReaderWriterPNG : public osgDB::ReaderWriter
//Set custom write function so it will write to ostream
png_set_write_fn(png,&fout,png_write_ostream,png_flush_ostream);
//Set compression level
png_set_compression_level(png, compression_level);
switch(img.getPixelFormat()) {
case(GL_LUMINANCE): color = PNG_COLOR_TYPE_GRAY; break;
case(GL_ALPHA): color = PNG_COLOR_TYPE_GRAY; break; //Couldn't find a color type for pure alpha, using gray instead
@@ -259,6 +264,23 @@ class ReaderWriterPNG : public osgDB::ReaderWriter
return pOsgImage;
}
int getCompressionLevel(const osgDB::ReaderWriter::Options *options) const
{
if(options) {
std::istringstream iss(options->getOptionString());
std::string opt;
while (iss >> opt) {
if(opt=="PNG_COMPRESSION") {
int level;
iss >> level;
return level;
}
}
}
return Z_DEFAULT_COMPRESSION;
}
virtual ReadResult readImage(std::istream& fin,const Options* =NULL) const
{
return readPNGStream(fin);
@@ -281,7 +303,7 @@ class ReaderWriterPNG : public osgDB::ReaderWriter
virtual WriteResult writeImage(const osg::Image& img,std::ostream& fout,const osgDB::ReaderWriter::Options *options) const
{
WriteResult::WriteStatus ws = writePngStream(fout,img);
WriteResult::WriteStatus ws = writePngStream(fout,img,getCompressionLevel(options));
return ws;
}

View File

@@ -40,7 +40,6 @@
*
**********************************************************************/
#include <string.h>
#include <stdarg.h>
#include <assert.h>
@@ -138,6 +137,75 @@ 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
@@ -586,6 +654,75 @@ class ReaderWriterTIFF : public osgDB::ReaderWriter
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;
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;
}
TIFFSetField(image, TIFFTAG_IMAGEWIDTH,img.s());
TIFFSetField(image, TIFFTAG_IMAGELENGTH,img.t());
TIFFSetField(image, TIFFTAG_BITSPERSAMPLE,8);
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 readImage(std::istream& fin,const osgDB::ReaderWriter::Options* =NULL) const
{
return readTIFStream(fin);
@@ -605,6 +742,23 @@ class ReaderWriterTIFF : public osgDB::ReaderWriter
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