From b3abc0842fb1803f7d6f439f0eec34e0e01482ff Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 23 Nov 2009 11:00:07 +0000 Subject: [PATCH] From Chris Hanson, " Add support for "OutputTextureFiles" option to IVE plugin to permit creation of external .dds texture files from internally-embedded textures during IVE writes." From Robert Osfield, fixed a bug in the above submission, and changed the way that the filename of the file is passed into DataOutputStream to avoid issues with the .ive's plugins ability to read from istreams. --- src/osgPlugins/ive/DataOutputStream.cpp | 68 ++++++++++++++++++++---- src/osgPlugins/ive/DataOutputStream.h | 15 +++++- src/osgPlugins/ive/ReaderWriterIVE.cpp | 8 ++- src/osgPlugins/osgTerrain/ImageLayer.cpp | 15 +++++- 4 files changed, 93 insertions(+), 13 deletions(-) diff --git a/src/osgPlugins/ive/DataOutputStream.cpp b/src/osgPlugins/ive/DataOutputStream.cpp index 1324e3d91..cb7379f0d 100644 --- a/src/osgPlugins/ive/DataOutputStream.cpp +++ b/src/osgPlugins/ive/DataOutputStream.cpp @@ -123,7 +123,9 @@ #include #include #include +#include #include +#include #include #include @@ -142,10 +144,23 @@ DataOutputStream::DataOutputStream(std::ostream * ostream, const osgDB::ReaderWr _useOriginalExternalReferences = true; _maximumErrorToSizeRatio = 0.001; + _outputTextureFiles = false; + _textureFileNameNumber = 0; + _options = options; _compressionLevel = 0; + if (options) _filename = options->getPluginStringData("filename"); + + if (_filename.empty()) + { + // initialize _filename to a unique identifier in case a real filename is not supplied + std::ostringstream filenameBuilder; + filenameBuilder << "file" << ostream; // use address of ostream to formulate unique filename + _filename = filenameBuilder.str(); + } + if (_options.get()) { std::string optionsString = _options->getOptionString(); @@ -157,19 +172,22 @@ DataOutputStream::DataOutputStream(std::ostream * ostream, const osgDB::ReaderWr } else if(optionsString.find("compressImageData")!=std::string::npos) { setIncludeImageMode(IMAGE_COMPRESS_DATA); } - osg::notify(osg::DEBUG_INFO) << "ive::DataOutpouStream.setIncludeImageMode()=" << getIncludeImageMode() << std::endl; + osg::notify(osg::DEBUG_INFO) << "ive::DataOutputStream.setIncludeImageMode()=" << getIncludeImageMode() << std::endl; setIncludeExternalReferences(optionsString.find("inlineExternalReferencesInIVEFile")!=std::string::npos); - osg::notify(osg::DEBUG_INFO) << "ive::DataOutpouStream.setIncludeExternalReferences()=" << getIncludeExternalReferences() << std::endl; + osg::notify(osg::DEBUG_INFO) << "ive::DataOutputStream.setIncludeExternalReferences()=" << getIncludeExternalReferences() << std::endl; setWriteExternalReferenceFiles(optionsString.find("noWriteExternalReferenceFiles")==std::string::npos); - osg::notify(osg::DEBUG_INFO) << "ive::DataOutpouStream.setWriteExternalReferenceFiles()=" << getWriteExternalReferenceFiles() << std::endl; + osg::notify(osg::DEBUG_INFO) << "ive::DataOutputStream.setWriteExternalReferenceFiles()=" << getWriteExternalReferenceFiles() << std::endl; setUseOriginalExternalReferences(optionsString.find("useOriginalExternalReferences")!=std::string::npos); - osg::notify(osg::DEBUG_INFO) << "ive::DataOutpouStream.setUseOriginalExternalReferences()=" << getUseOriginalExternalReferences() << std::endl; + osg::notify(osg::DEBUG_INFO) << "ive::DataOutputStream.setUseOriginalExternalReferences()=" << getUseOriginalExternalReferences() << std::endl; + + setOutputTextureFiles(optionsString.find("OutputTextureFiles")!=std::string::npos); + osg::notify(osg::DEBUG_INFO) << "ive::DataOutputStream.setOutputTextureFiles()=" << getOutputTextureFiles() << std::endl; _compressionLevel = (optionsString.find("compressed")!=std::string::npos) ? 1 : 0; - osg::notify(osg::DEBUG_INFO) << "ive::DataOutpouStream._compressionLevel=" << _compressionLevel << std::endl; + osg::notify(osg::DEBUG_INFO) << "ive::DataOutputStream._compressionLevel=" << _compressionLevel << std::endl; std::string::size_type terrainErrorPos = optionsString.find("TerrainMaximumErrorToSizeRatio="); if (terrainErrorPos!=std::string::npos) @@ -1439,14 +1457,28 @@ void DataOutputStream::writeImage(IncludeImageMode mode, osg::Image *image) ((ive::Image*)image)->write(this); break; case IMAGE_REFERENCE_FILE: - // Only include image name in stream - if (image && !(image->getFileName().empty())){ - writeString(image->getFileName()); + { + if (image) + { + // Only include image name in stream + std::string fileName = image->getFileName(); + // Export an image, if requested + if (getOutputTextureFiles()) + { + if (fileName.empty()) + { // synthesize a new faux filename + fileName = getTextureFileNameForOutput(); + } + osgDB::writeImageFile(*image, fileName); + } + writeString(fileName); } - else{ + else + { writeString(""); } break; + } case IMAGE_INCLUDE_FILE: // Include image file in stream if(image && !(image->getFileName().empty())) { @@ -1839,6 +1871,24 @@ void DataOutputStream::writeObject(const osg::Object* object) writeInt(-1); } +std::string DataOutputStream::getTextureFileNameForOutput() +{ + std::string fileName = osgDB::getNameLessExtension(_filename); + if (_textureFileNameNumber>0) + { + std::ostringstream o; + o << '_' << _textureFileNameNumber; + fileName += o.str(); + } + + fileName += ".dds"; + ++_textureFileNameNumber; + + return fileName; +} + + + void DataOutputStream::setExternalFileWritten(const std::string& filename, bool hasBeenWritten) { _externalFileWritten[filename] = hasBeenWritten; diff --git a/src/osgPlugins/ive/DataOutputStream.h b/src/osgPlugins/ive/DataOutputStream.h index 01ee43a5c..fe03dd9fa 100644 --- a/src/osgPlugins/ive/DataOutputStream.h +++ b/src/osgPlugins/ive/DataOutputStream.h @@ -130,6 +130,15 @@ public: void setUseOriginalExternalReferences(bool b) {_useOriginalExternalReferences=b;}; bool getUseOriginalExternalReferences() const {return _useOriginalExternalReferences;}; + // Set and get if export texture files during write + void setOutputTextureFiles(bool flag) { _outputTextureFiles = flag; } + bool getOutputTextureFiles() const { return _outputTextureFiles; } + + // support code for OutputTextureFiles + virtual std::string getTextureFileNameForOutput(); + void setFileName(std::string newFileName) {_filename = newFileName;} + std::string getFileName(void) const {return(_filename);} + void setTerrainMaximumErrorToSizeRatio(double ratio) { _maximumErrorToSizeRatio = ratio; } double getTerrainMaximumErrorToSizeRatio() const { return _maximumErrorToSizeRatio; } @@ -150,6 +159,7 @@ public: std::ostream* _ostream; std::ostream* _output_ostream; + std::string _filename; // not necessary, but optional for use in texture export std::stringstream _compressionStream; int _compressionLevel; @@ -188,7 +198,10 @@ public: double _maximumErrorToSizeRatio; IncludeImageMode _includeImageMode; - + + bool _outputTextureFiles; + unsigned int _textureFileNameNumber; + osg::ref_ptr _options; typedef std::map ExternalFileWrittenMap; diff --git a/src/osgPlugins/ive/ReaderWriterIVE.cpp b/src/osgPlugins/ive/ReaderWriterIVE.cpp index 3d534aa90..389dc6766 100644 --- a/src/osgPlugins/ive/ReaderWriterIVE.cpp +++ b/src/osgPlugins/ive/ReaderWriterIVE.cpp @@ -28,6 +28,7 @@ class ReaderWriterIVE : public ReaderWriter supportsOption("useOriginalExternalReferences","Export option"); supportsOption("TerrainMaximumErrorToSizeRatio=value","Export option that controls error matric used to determine terrain HieghtField storage precision."); supportsOption("noLoadExternalReferenceFiles","Import option"); + supportsOption("OutputTextureFiles","Write out the texture images to file"); } virtual const char* className() const { return "IVE Reader/Writer"; } @@ -68,7 +69,7 @@ class ReaderWriterIVE : public ReaderWriter // code for setting up the database path so that internally referenced file are searched for on relative paths. osg::ref_ptr local_opt = options ? static_cast(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; local_opt->getDatabasePathList().push_front(osgDB::getFilePath(fileName)); - + osgDB::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary); return readNode(istream,local_opt.get()); } @@ -118,6 +119,9 @@ class ReaderWriterIVE : public ReaderWriter osg::ref_ptr local_opt = options ? static_cast(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; if(local_opt->getDatabasePathList().empty()) local_opt->setDatabasePath(osgDB::getFilePath(fileName)); + + local_opt->setPluginStringData("filename",fileName); + osgDB::ofstream fout(fileName.c_str(), std::ios::out | std::ios::binary); if (!fout) return WriteResult::ERROR_IN_WRITING_FILE; WriteResult result = writeImage(image, fout, local_opt.get()); @@ -135,6 +139,8 @@ class ReaderWriterIVE : public ReaderWriter if(local_opt->getDatabasePathList().empty()) local_opt->setDatabasePath(osgDB::getFilePath(fileName)); + local_opt->setPluginStringData("filename",fileName); + osgDB::ofstream fout(fileName.c_str(), std::ios::out | std::ios::binary); if (!fout) return WriteResult::ERROR_IN_WRITING_FILE; diff --git a/src/osgPlugins/osgTerrain/ImageLayer.cpp b/src/osgPlugins/osgTerrain/ImageLayer.cpp index 07b481e4c..40d60212f 100644 --- a/src/osgPlugins/osgTerrain/ImageLayer.cpp +++ b/src/osgPlugins/osgTerrain/ImageLayer.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -64,10 +65,20 @@ bool ImageLayer_readLocalData(osg::Object& obj, osgDB::Input &fr) bool ImageLayer_writeLocalData(const osg::Object& obj, osgDB::Output& fw) { const osgTerrain::ImageLayer& layer = static_cast(obj); + + std::string fileName = layer.getFileName(); - if (!layer.getFileName().empty()) + if (fw.getOutputTextureFiles()) { - fw.indent()<<"file "<< layer.getFileName() << std::endl; + if (fileName.empty()) + { + fileName = fw.getTextureFileNameForOutput(); + } + osgDB::writeImageFile(*layer.getImage(), fileName); + } + if (!fileName.empty()) + { + fw.indent()<<"file "<< fw.wrapString(fileName) << std::endl; } return true;