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:
Robert Osfield 2009-04-09 14:00:16 +00:00
parent 53a19190ce
commit 38b02a26a9
6 changed files with 213 additions and 7 deletions

View File

@ -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 );

View File

@ -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
View 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
};

View File

@ -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() {}

View File

@ -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)) :

View File

@ -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();