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:
@@ -8,6 +8,8 @@
|
|||||||
#include <osgDB/FileUtils>
|
#include <osgDB/FileUtils>
|
||||||
#include <osgDB/FileNameUtils>
|
#include <osgDB/FileNameUtils>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace osg;
|
using namespace osg;
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
@@ -54,7 +56,7 @@ class ReaderWriterPNG : public osgDB::ReaderWriter
|
|||||||
virtual const char* className() const { return "PNG Image Reader/Writer"; }
|
virtual const char* className() const { return "PNG Image Reader/Writer"; }
|
||||||
virtual bool acceptsExtension(const std::string& extension) const { return osgDB::equalCaseInsensitive(extension,"png"); }
|
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_structp png = NULL;
|
||||||
png_infop info = NULL;
|
png_infop info = NULL;
|
||||||
@@ -72,6 +74,9 @@ class ReaderWriterPNG : public osgDB::ReaderWriter
|
|||||||
//Set custom write function so it will write to ostream
|
//Set custom write function so it will write to ostream
|
||||||
png_set_write_fn(png,&fout,png_write_ostream,png_flush_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()) {
|
switch(img.getPixelFormat()) {
|
||||||
case(GL_LUMINANCE): color = PNG_COLOR_TYPE_GRAY; break;
|
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
|
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;
|
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
|
virtual ReadResult readImage(std::istream& fin,const Options* =NULL) const
|
||||||
{
|
{
|
||||||
return readPNGStream(fin);
|
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
|
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;
|
return ws;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@
|
|||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <assert.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;
|
static int tifferror = ERR_NO_ERROR;
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -586,6 +654,75 @@ class ReaderWriterTIFF : public osgDB::ReaderWriter
|
|||||||
return pOsgImage;
|
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
|
virtual ReadResult readImage(std::istream& fin,const osgDB::ReaderWriter::Options* =NULL) const
|
||||||
{
|
{
|
||||||
return readTIFStream(fin);
|
return readTIFStream(fin);
|
||||||
@@ -605,6 +742,23 @@ class ReaderWriterTIFF : public osgDB::ReaderWriter
|
|||||||
if(rr.validImage()) rr.getImage()->setFileName(file);
|
if(rr.validImage()) rr.getImage()->setFileName(file);
|
||||||
return rr;
|
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
|
// now register with Registry to instantiate the above
|
||||||
|
|||||||
Reference in New Issue
Block a user