From Glenn Waldron, "Here is a first cut at the mime-type support we discussed a little while ago
(http://www.mail-archive.com/osg-users@lists.openscenegraph.org/msg23098.html) Background: when you access a file over HTTP, you cannot rely on a file extension being present; instead the file's mime-type is conveyed in the HTTP Content-Type response header. This facility adds a mime-type-to-extension map to the registry to handle this. There are two new osgDB::Registry functions which are pretty self-explanatory: void addMimeTypeExtensionMapping( mime-type, extension ) ReaderWriter* getReaderWriterForMimeType( mime-type ) I also added the file osgDB/MimeTypes.cpp which houses a hard-coded list of built-in types. I took the list from here (http://www.webmaster-toolkit.com/mime-types.shtml) and then pared it down to include mostly image and video types, editing them to map to existing plugins where possible. In addition, I updated the CURL plugin to a) install a set of built-in mime-type mappings, and b) use them to look up an extension in the event that the target filename does not have an extension. Here is a test case. This URL pulls down a JPEG (without a file extension): osgviewer --image "http://us.maps3.yimg.com/aerial.maps.yimg.com/ximg?v=1.8&s=256&t=a&r=1&x=0&y=0&z=2" "
This commit is contained in:
parent
53a19190ce
commit
38b02a26a9
@ -94,6 +94,12 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
* method. Lines can be commented out with an initial '#' character.*/
|
||||
bool readPluginAliasConfigurationFile( const std::string& file );
|
||||
|
||||
/** Registers a mapping of a mime-type to an extension. A process fetching data
|
||||
* over HTTP can use this facility to determine the proper ReaderWriter to use
|
||||
* when there is no filename extension to rely upon.
|
||||
*/
|
||||
void addMimeTypeExtensionMapping(const std::string fromMimeType, const std::string toExt);
|
||||
|
||||
void addDotOsgWrapper(DotOsgWrapper* wrapper);
|
||||
void removeDotOsgWrapper(DotOsgWrapper* wrapper);
|
||||
|
||||
@ -129,6 +135,10 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
|
||||
/** get a reader writer which handles specified extension.*/
|
||||
ReaderWriter* getReaderWriterForExtension(const std::string& ext);
|
||||
|
||||
/** gets a reader/writer that handles the extension mapped to by one of
|
||||
* the registered mime-types. */
|
||||
ReaderWriter* getReaderWriterForMimeType(const std::string& mimeType);
|
||||
|
||||
/** get list of all registered ReaderWriters.*/
|
||||
ReaderWriterList& getReaderWriterList() { return _rwList; }
|
||||
@ -492,6 +502,7 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
typedef std::map< std::string, osg::ref_ptr<DotOsgWrapper> > DotOsgWrapperMap;
|
||||
typedef std::vector< osg::ref_ptr<DynamicLibrary> > DynamicLibraryList;
|
||||
typedef std::map< std::string, std::string> ExtensionAliasMap;
|
||||
typedef std::map< std::string, std::string> MimeTypeExtensionMap;
|
||||
typedef std::vector< std::string> ArchiveExtensionList;
|
||||
|
||||
typedef std::pair<osg::ref_ptr<osg::Object>, double > ObjectTimeStampPair;
|
||||
@ -592,6 +603,9 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
// map to alias to extensions to plugins.
|
||||
ExtensionAliasMap _extAliasMap;
|
||||
|
||||
// maps mime-types to extensions.
|
||||
MimeTypeExtensionMap _mimeTypeExtMap;
|
||||
|
||||
// Utility: Removes whitespace from both ends of a string.
|
||||
static std::string trim( const std::string& str );
|
||||
|
||||
|
@ -68,6 +68,7 @@ ADD_LIBRARY(${LIB_NAME}
|
||||
ImageOptions.cpp
|
||||
ImagePager.cpp
|
||||
Input.cpp
|
||||
MimeTypes.cpp
|
||||
Output.cpp
|
||||
PluginQuery.cpp
|
||||
ReaderWriter.cpp
|
||||
|
127
src/osgDB/MimeTypes.cpp
Normal file
127
src/osgDB/MimeTypes.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
const char* builtinMimeTypeExtMappings[] =
|
||||
{
|
||||
"application/dxf","dxf",
|
||||
"application/gnutar","tgz",
|
||||
"application/pdf","pdf",
|
||||
"application/plain","text",
|
||||
"application/postscript","ps",
|
||||
"application/x-bzip","bz",
|
||||
"application/x-bzip2","bz2",
|
||||
"application/x-compressed","zip",
|
||||
"application/x-gzip","gz",
|
||||
"application/x-inventor","iv",
|
||||
"application/x-javascript","js",
|
||||
"application/xml","xml",
|
||||
"application/x-tar","tar",
|
||||
"application/x-vrml","wrl",
|
||||
"application/x-world","wrl",
|
||||
"application/x-zip-compressed","zip",
|
||||
"application/zip","zip",
|
||||
"drawing/x-dwf(old)","dwf",
|
||||
"image/bmp","bmp",
|
||||
"image/cmu-raster","ras",
|
||||
"image/fif","fif",
|
||||
"image/florian","flo",
|
||||
"image/g3fax","g3",
|
||||
"image/gif","gif",
|
||||
"image/ief","ief",
|
||||
"image/jpeg","jpg",
|
||||
"image/jutvision","jut",
|
||||
"image/naplps","nap",
|
||||
"image/naplps","naplps",
|
||||
"image/pict","pic",
|
||||
"image/pjpeg","jpg",
|
||||
"image/png","png",
|
||||
"image/tiff","tif",
|
||||
"image/vasa","mcf",
|
||||
"image/vnd.dwg","dxf",
|
||||
"image/vnd.fpx","fpx",
|
||||
"image/vnd.net-fpx","fpx",
|
||||
"image/vnd.rn-realflash","rf",
|
||||
"image/vnd.rn-realpix","rp",
|
||||
"image/vnd.wap.wbmp","wbmp",
|
||||
"image/vnd.xiff","xif",
|
||||
"image/xbm","xbm",
|
||||
"image/x-cmu-raster","ras",
|
||||
"image/x-dwg","dxf",
|
||||
"image/x-icon","ico",
|
||||
"image/x-jg","art",
|
||||
"image/x-jps","jps",
|
||||
"image/x-niff","nif",
|
||||
"image/x-pcx","pcx",
|
||||
"image/x-pict","pct",
|
||||
"image/xpm","xpm",
|
||||
"image/x-portable-anymap","pnm",
|
||||
"image/x-portable-bitmap","pbm",
|
||||
"image/x-portable-graymap","pgm",
|
||||
"image/x-portable-greymap","pgm",
|
||||
"image/x-portable-pixmap","ppm",
|
||||
"image/x-quicktime","qif",
|
||||
"image/x-rgb","rgb",
|
||||
"image/x-tiff","tif",
|
||||
"image/x-windows-bmp","bmp",
|
||||
"image/x-xbitmap","xbm",
|
||||
"image/x-xbm","xbm",
|
||||
"image/x-xpixmap","xpm",
|
||||
"image/x-xwd","xwd",
|
||||
"image/x-xwindowdump","xwd",
|
||||
"i-world/i-vrml","ivr",
|
||||
"model/iges","igs",
|
||||
"model/vnd.dwf","dwf",
|
||||
"model/vrml","wrl",
|
||||
"model/x-pov","pov",
|
||||
"multipart/x-gzip","gzip",
|
||||
"multipart/x-ustar","ustar",
|
||||
"multipart/x-zip","zip",
|
||||
"video/animaflex","afl",
|
||||
"video/avi","avi",
|
||||
"video/avs-video","avs",
|
||||
"video/dl","dl",
|
||||
"video/fli","fli",
|
||||
"video/gl","gl",
|
||||
"video/mpeg","mpg",
|
||||
"video/msvideo","avi",
|
||||
"video/quicktime","qt",
|
||||
"video/vdo","vdo",
|
||||
"video/vivo","viv",
|
||||
"video/vnd.rn-realvideo","rv",
|
||||
"video/vnd.vivo","viv",
|
||||
"video/vosaic","vos",
|
||||
"video/x-amt-demorun","xdr",
|
||||
"video/x-amt-showrun","xsr",
|
||||
"video/x-atomic3d-feature","fmf",
|
||||
"video/x-dl","dl",
|
||||
"video/x-dv","dv",
|
||||
"video/x-fli","fli",
|
||||
"video/x-gl","gl",
|
||||
"video/x-isvideo","isu",
|
||||
"video/x-motion-jpeg","mjpg",
|
||||
"video/x-mpeg","mp3",
|
||||
"video/x-mpeq2a","mp2",
|
||||
"video/x-ms-asf","asf",
|
||||
"video/x-ms-asf-plugin","asx",
|
||||
"video/x-msvideo","avi",
|
||||
"video/x-qtc","qtc",
|
||||
"video/x-scm","scm",
|
||||
"video/x-sgi-movie","movie",
|
||||
"windows/metafile","wmf",
|
||||
"xgl/drawing","xgz",
|
||||
"xgl/movie","xmz",
|
||||
"x-world/x-3dmf","3dm",
|
||||
"x-world/x-svr","svr",
|
||||
"x-world/x-vrml","wrl",
|
||||
"x-world/x-vrt","vrt",
|
||||
"" // end of list
|
||||
};
|
@ -63,6 +63,10 @@ static osg::ApplicationUsageProxy Registry_e1(osg::ApplicationUsage::ENVIRONMENT
|
||||
static osg::ApplicationUsageProxy Registry_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_BUILD_KDTREES on/off","Enable/disable the automatic building of KdTrees for each loaded Geometry.");
|
||||
|
||||
|
||||
// from MimeTypes.cpp
|
||||
extern const char* builtinMimeTypeExtMappings[];
|
||||
|
||||
|
||||
class Registry::AvailableReaderWriterIterator
|
||||
{
|
||||
public:
|
||||
@ -331,9 +335,17 @@ Registry::Registry()
|
||||
addFileExtensionAlias("pgm", "pnm");
|
||||
addFileExtensionAlias("ppm", "pnm");
|
||||
|
||||
// add built-in mime-type extension mappings
|
||||
for( int i=0; ; i+=2 )
|
||||
{
|
||||
std::string mimeType = builtinMimeTypeExtMappings[i];
|
||||
if ( mimeType.length() == 0 )
|
||||
break;
|
||||
addMimeTypeExtensionMapping( mimeType, builtinMimeTypeExtMappings[i+1] );
|
||||
}
|
||||
|
||||
// register http-protocol, so the curl can handle it, if necessary
|
||||
registerProtocol("http");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -587,6 +599,11 @@ void Registry::addFileExtensionAlias(const std::string mapExt, const std::string
|
||||
_extAliasMap[mapExt] = toExt;
|
||||
}
|
||||
|
||||
void Registry::addMimeTypeExtensionMapping(const std::string fromMimeType, const std::string toExt)
|
||||
{
|
||||
_mimeTypeExtMap[fromMimeType] = toExt;
|
||||
}
|
||||
|
||||
bool Registry::readPluginAliasConfigurationFile( const std::string& file )
|
||||
{
|
||||
std::string fileName = osgDB::findDataFile( file );
|
||||
@ -825,6 +842,14 @@ ReaderWriter* Registry::getReaderWriterForExtension(const std::string& ext)
|
||||
|
||||
}
|
||||
|
||||
ReaderWriter* Registry::getReaderWriterForMimeType(const std::string& mimeType)
|
||||
{
|
||||
MimeTypeExtensionMap::const_iterator i = _mimeTypeExtMap.find( mimeType );
|
||||
return i != _mimeTypeExtMap.end()?
|
||||
getReaderWriterForExtension( i->second ) :
|
||||
NULL;
|
||||
}
|
||||
|
||||
struct concrete_wrapper: basic_type_wrapper
|
||||
{
|
||||
virtual ~concrete_wrapper() {}
|
||||
|
@ -57,6 +57,11 @@ void EasyCurl::StreamObject::write(const char* ptr, size_t realsize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string EasyCurl::getResultMimeType(const StreamObject& sp) const
|
||||
{
|
||||
return sp._resultMimeType;
|
||||
}
|
||||
|
||||
size_t EasyCurl::StreamMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
|
||||
{
|
||||
@ -192,6 +197,15 @@ osgDB::ReaderWriter::ReadResult EasyCurl::read(const std::string& proxyAddress,
|
||||
return rr;
|
||||
}
|
||||
|
||||
// Store the mime-type, if any. (Note: CURL manages the buffer returned by
|
||||
// this call.)
|
||||
char* ctbuf = NULL;
|
||||
if ( curl_easy_getinfo(_curl, CURLINFO_CONTENT_TYPE, &ctbuf) == 0 && ctbuf )
|
||||
{
|
||||
sp._resultMimeType = ctbuf;
|
||||
}
|
||||
|
||||
|
||||
return osgDB::ReaderWriter::ReadResult::FILE_LOADED;
|
||||
|
||||
}
|
||||
@ -213,7 +227,7 @@ ReaderWriterCURL::ReaderWriterCURL()
|
||||
supportsExtension("curl","Psuedo file extension, used to select curl plugin.");
|
||||
supportsExtension("*","Passes all read files to other plugins to handle actual model loading.");
|
||||
supportsOption("OSG_CURL_PROXY","Specify the http proxy.");
|
||||
supportsOption("OSG_CURL_PROXYPORT","Specify the http proxy oirt.");
|
||||
supportsOption("OSG_CURL_PROXYPORT","Specify the http proxy port.");
|
||||
}
|
||||
|
||||
ReaderWriterCURL::~ReaderWriterCURL()
|
||||
@ -324,14 +338,16 @@ osgDB::ReaderWriter::ReadResult ReaderWriterCURL::readFile(ObjectType objectType
|
||||
}
|
||||
|
||||
|
||||
// Try to find a reader by file extension. If this fails, we will fetch the file
|
||||
// anyway and try to get a reader via mime-type.
|
||||
osgDB::ReaderWriter *reader =
|
||||
osgDB::Registry::instance()->getReaderWriterForExtension( ext );
|
||||
|
||||
if (!reader)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Error: No ReaderWriter for file "<<fileName<<std::endl;
|
||||
return ReadResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
//if (!reader)
|
||||
//{
|
||||
// osg::notify(osg::NOTICE)<<"Error: No ReaderWriter for file "<<fileName<<std::endl;
|
||||
// return ReadResult::FILE_NOT_HANDLED;
|
||||
//}
|
||||
|
||||
const char* proxyEnvAddress = getenv("OSG_CURL_PROXY");
|
||||
if (proxyEnvAddress) //Env Proxy Settings
|
||||
@ -352,6 +368,24 @@ osgDB::ReaderWriter::ReadResult ReaderWriterCURL::readFile(ObjectType objectType
|
||||
|
||||
if (curlResult.status()==ReadResult::FILE_LOADED)
|
||||
{
|
||||
// If we do not already have a ReaderWriter, try to find one based on the
|
||||
// mime-type:
|
||||
if ( !reader )
|
||||
{
|
||||
std::string mimeType = getEasyCurl().getResultMimeType(sp);
|
||||
osg::notify(osg::INFO) << "CURL: Looking up extension for mime-type " << mimeType << std::endl;
|
||||
if ( mimeType.length() > 0 )
|
||||
{
|
||||
reader = osgDB::Registry::instance()->getReaderWriterForMimeType(mimeType);
|
||||
}
|
||||
}
|
||||
|
||||
// If there is still no reader, fail.
|
||||
if ( !reader )
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Error: No ReaderWriter for file "<<fileName<<std::endl;
|
||||
return ReadResult::FILE_NOT_HANDLED;
|
||||
}
|
||||
|
||||
osg::ref_ptr<Options> local_opt = options ?
|
||||
static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) :
|
||||
|
@ -44,6 +44,7 @@ class EasyCurl : public osg::Referenced
|
||||
bool _foutOpened;
|
||||
std::string _cacheFileName;
|
||||
std::ofstream _fout;
|
||||
std::string _resultMimeType;
|
||||
};
|
||||
|
||||
static size_t StreamMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data);
|
||||
@ -52,6 +53,10 @@ class EasyCurl : public osg::Referenced
|
||||
|
||||
osgDB::ReaderWriter::ReadResult read(const std::string& proxyAddress, const std::string& fileName, StreamObject& sp, const osgDB::ReaderWriter::Options *options);
|
||||
|
||||
/** Returns the mime type of the data retrieved with the provided stream object on a
|
||||
* previous call to EasyCurl::read(). */
|
||||
std::string getResultMimeType(const StreamObject& sp) const;
|
||||
|
||||
protected:
|
||||
|
||||
virtual ~EasyCurl();
|
||||
|
Loading…
Reference in New Issue
Block a user