diff --git a/include/osgDB/InputStream b/include/osgDB/InputStream index d17f3c7b3..d84d294db 100644 --- a/include/osgDB/InputStream +++ b/include/osgDB/InputStream @@ -161,6 +161,7 @@ protected: int _byteSwap; bool _useFloatMatrix; + bool _useSchemaData; bool _forceReadingImage; std::vector _fields; osg::ref_ptr _in; diff --git a/include/osgDB/OutputStream b/include/osgDB/OutputStream index 4519bb569..d18506c6c 100644 --- a/include/osgDB/OutputStream +++ b/include/osgDB/OutputStream @@ -168,6 +168,8 @@ protected: ObjectMap _objectMap; WriteImageHint _writeImageHint; + bool _useSchemaData; + std::map _inbuiltSchemaMap; std::vector _fields; std::string _schemaName; std::string _compressorName; diff --git a/src/osgDB/InputStream.cpp b/src/osgDB/InputStream.cpp index 1558243b3..6ab942727 100644 --- a/src/osgDB/InputStream.cpp +++ b/src/osgDB/InputStream.cpp @@ -24,7 +24,7 @@ using namespace osgDB; static std::string s_lastSchema; InputStream::InputStream( const osgDB::Options* options ) -: _byteSwap(0), _useFloatMatrix(false), _forceReadingImage(false) +: _byteSwap(0), _useFloatMatrix(true), _useSchemaData(false), _forceReadingImage(false) { if ( !options ) return; _options = options; @@ -624,9 +624,9 @@ InputStream::ReadType InputStream::start( InputIterator* inIterator ) *this >> typeValue >> version; type = static_cast(typeValue); - unsigned int matrixValueType; *this >> matrixValueType; - if ( matrixValueType==0 ) _useFloatMatrix = true; - else _useFloatMatrix = false; + unsigned int attributes; *this >> attributes; + if ( attributes&0x1 ) _useFloatMatrix = false; + if ( attributes&0x2 ) _useSchemaData = true; } if ( !isBinary() ) { @@ -655,29 +655,36 @@ void InputStream::decompress() { if ( !isBinary() ) return; _fields.clear(); - _fields.push_back( "Decompression" ); std::string compressorName; *this >> compressorName; - if ( compressorName=="0" ) + if ( compressorName!="0" ) { + std::string data; + _fields.push_back( "Decompression" ); + + BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(compressorName); + if ( !compressor ) + { + osg::notify(osg::WARN) << "InputStream::decompress(): No such compressor " + << compressorName << std::endl; + } + + if ( !compressor->decompress(*(_in->getStream()), data) ) + throwException( "InputStream: Failed to decompress stream." ); + if ( getException() ) return; + + _in->setStream( new std::stringstream(data) ); _fields.pop_back(); - return; } - BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(compressorName); - if ( !compressor ) + if ( _useSchemaData ) { - osg::notify(osg::WARN) << "InputStream::decompress(): No such compressor " - << compressorName << std::endl; + _fields.push_back( "SchemaData" ); + std::string schemaSource; *this >> schemaSource; + std::istringstream iss( schemaSource ); + readSchema( iss ); + _fields.pop_back(); } - - std::string data; - if ( !compressor->decompress(*(_in->getStream()), data) ) - throwException( "InputStream: Failed to decompress stream." ); - if ( getException() ) return; - - _in->setStream( new std::stringstream(data) ); - _fields.pop_back(); } // PROTECTED METHODS diff --git a/src/osgDB/OutputStream.cpp b/src/osgDB/OutputStream.cpp index 14d585de3..40ab99930 100644 --- a/src/osgDB/OutputStream.cpp +++ b/src/osgDB/OutputStream.cpp @@ -22,7 +22,7 @@ using namespace osgDB; OutputStream::OutputStream( const osgDB::Options* options ) -: _writeImageHint(WRITE_USE_IMAGE_HINT) +: _writeImageHint(WRITE_USE_IMAGE_HINT), _useSchemaData(false) { if ( !options ) return; _options = options; @@ -36,6 +36,10 @@ OutputStream::OutputStream( const osgDB::Options* options ) { // Omit this } + else if ( option=="SchemaData" ) + { + _useSchemaData = true; + } else { StringList keyAndValues; @@ -422,13 +426,32 @@ void OutputStream::writeObject( const osg::Object* obj ) const StringList& associates = wrapper->getAssociates(); for ( StringList::const_iterator itr=associates.begin(); itr!=associates.end(); ++itr ) { - ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(*itr); + const std::string& assocName = *itr; + ObjectWrapper* assocWrapper = Registry::instance()->getObjectWrapperManager()->findWrapper(assocName); if ( !assocWrapper ) { osg::notify(osg::WARN) << "OutputStream::writeObject(): Unsupported associated class " - << *itr << std::endl; + << assocName << std::endl; continue; } + else if ( _useSchemaData ) + { + if ( _inbuiltSchemaMap.find(assocName)==_inbuiltSchemaMap.end() ) + { + StringList properties; + assocWrapper->writeSchema( properties ); + if ( properties.size()>0 ) + { + std::string propertiesString; + for ( StringList::iterator sitr=properties.begin(); sitr!=properties.end(); ++sitr ) + { + propertiesString += *sitr; + propertiesString += ' '; + } + _inbuiltSchemaMap[assocName] = propertiesString; + } + } + } _fields.push_back( assocWrapper->getName() ); assocWrapper->write( *this, *obj ); @@ -455,8 +478,16 @@ void OutputStream::start( OutputIterator* outIterator, OutputStream::WriteType t { *this << (unsigned int)type << (unsigned int)PLUGIN_VERSION; - if ( sizeof(osg::Matrix::value_type)==FLOAT_SIZE ) *this << (unsigned int)0; - else *this << (unsigned int)1; // Record matrix value type of current built OSG + bool useCompressSource = false; + unsigned int attributes = 0; + if ( sizeof(osg::Matrix::value_type)!=FLOAT_SIZE ) + attributes |= 0x1; // Record matrix value type of current built OSG + if ( _useSchemaData ) + { + attributes |= 0x2; // Record if we use inbuilt schema data or not + useCompressSource = true; + } + *this << attributes; if ( !_compressorName.empty() ) { @@ -465,16 +496,22 @@ void OutputStream::start( OutputIterator* outIterator, OutputStream::WriteType t { osg::notify(osg::WARN) << "OutputStream::start(): No such compressor " << _compressorName << std::endl; + _compressorName.clear(); } else { - *this << _compressorName; - _out->flush(); - _out->setStream( &_compressSource ); - return; + useCompressSource = true; } } - *this << std::string("0"); + if ( !_compressorName.empty() ) *this << _compressorName; + else *this << std::string("0"); // No compressor + + // Compressors and inbuilt schema use a new stream, which will be merged with the original one at the end. + if ( useCompressSource ) + { + _out->flush(); + _out->setStream( &_compressSource ); + } } else { @@ -498,20 +535,51 @@ void OutputStream::start( OutputIterator* outIterator, OutputStream::WriteType t void OutputStream::compress( std::ostream* ostream ) { - if ( _compressorName.empty() || !isBinary() ) return; _fields.clear(); - _fields.push_back( "Compression" ); + if ( !isBinary() ) return; - BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(_compressorName); - if ( !compressor || !ostream ) + std::stringstream schemaSource; + if ( _useSchemaData ) { + _fields.push_back( "SchemaData" ); + + std::string schemaData; + for ( std::map::iterator itr=_inbuiltSchemaMap.begin(); + itr!=_inbuiltSchemaMap.end(); ++itr ) + { + schemaData += itr->first + '='; + schemaData += itr->second; + schemaData += '\n'; + } + + int size = schemaData.size(); + schemaSource.write( (char*)&size, INT_SIZE ); + schemaSource.write( schemaData.c_str(), size ); + + _inbuiltSchemaMap.clear(); _fields.pop_back(); - return; } - if ( !compressor->compress(*ostream, _compressSource.str()) ) - throwException( "OutputStream: Failed to compress stream." ); - _fields.pop_back(); + if ( !_compressorName.empty() ) + { + _fields.push_back( "Compression" ); + BaseCompressor* compressor = Registry::instance()->getObjectWrapperManager()->findCompressor(_compressorName); + if ( !compressor || !ostream ) + { + _fields.pop_back(); + return; + } + + if ( !compressor->compress(*ostream, schemaSource.str() + _compressSource.str()) ) + throwException( "OutputStream: Failed to compress stream." ); + if ( getException() ) return; + _fields.pop_back(); + } + else if ( _useSchemaData ) + { + std::string str = schemaSource.str() + _compressSource.str(); + ostream->write( str.c_str(), str.size() ); + } } void OutputStream::writeSchema( std::ostream& fout ) diff --git a/src/osgPlugins/osg/ReaderWriterOSG2.cpp b/src/osgPlugins/osg/ReaderWriterOSG2.cpp index 2544eeaef..e0c0a9aff 100644 --- a/src/osgPlugins/osg/ReaderWriterOSG2.cpp +++ b/src/osgPlugins/osg/ReaderWriterOSG2.cpp @@ -103,7 +103,8 @@ public: supportsOption( "Ascii", "Import/Export option: Force reading/writing ascii file" ); supportsOption( "XML", "Import/Export option: Force reading/writing XML file" ); supportsOption( "ForceReadingImage", "Import option: Load an empty image instead if required file missed" ); - supportsOption( "SchemaFile=", "Import/Export option: Use/Record a ascii schema file" ); + supportsOption( "SchemaData", "Export option: Record inbuilt schema data into a binary file" ); + supportsOption( "SchemaFile=", "Import/Export option: Use/Record an ascii schema file" ); supportsOption( "Compressor=", "Export option: Use an inbuilt or user-defined compressor" ); supportsOption( "WriteImageHint=", "Export option: Hint of writing image to stream: " " writes Image::data() directly; "