osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthDrivers/mbtiles/ReaderWriterMBTiles.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003 * Copyright 2008-2010 Pelican Mapping
00004 * http://osgearth.org
00005 *
00006 * osgEarth is free software; you can redistribute it and/or modify
00007 * it under the terms of the GNU Lesser General Public License as published by
00008 * the Free Software Foundation; either version 2 of the License, or
00009 * (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU Lesser General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU Lesser General Public License
00017 * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018 */
00019 
00020 #include "MBTilesOptions"
00021 
00022 #include <osgEarth/TileSource>
00023 #include <osgEarth/Registry>
00024 #include <osgEarth/FileUtils>
00025 #include <osgEarth/ImageUtils>
00026 #include <osg/Notify>
00027 #include <osgDB/FileNameUtils>
00028 #include <osgDB/FileUtils>
00029 #include <osgDB/Registry>
00030 #include <osgDB/ReadFile>
00031 #include <osgDB/WriteFile>
00032 
00033 #include <sstream>
00034 #include <iomanip>
00035 #include <algorithm>
00036 
00037 using namespace osgEarth;
00038 using namespace osgEarth::Drivers;
00039 
00040 #include <sqlite3.h>
00041 
00042 
00043 #define LC "[MBTilesSource] "
00044 
00045 class MBTilesSource : public TileSource
00046 {
00047 public:
00048     MBTilesSource( const TileSourceOptions& options ) :
00049       TileSource( options ),
00050       _options( options ),      
00051       _database( NULL ),
00052       _minLevel( 0 ),
00053       _maxLevel( 20 )
00054     {
00055     }
00056 
00057     // override
00058     void initialize( const std::string& referenceURI, const Profile* overrideProfile)
00059     {
00060         //Set the profile
00061         setProfile( osgEarth::Registry::instance()->getGlobalMercatorProfile() );
00062 
00063         //Open the database
00064         std::string filename = _options.filename().value();
00065 
00066         //Get the absolute filename
00067         if (!osgDB::containsServerAddress(filename))
00068         {
00069             filename = osgEarth::getFullPath(referenceURI, filename);
00070         }
00071 
00072         int flags = SQLITE_OPEN_READONLY;
00073         int rc = sqlite3_open_v2( filename.c_str(), &_database, flags, 0L );
00074         if ( rc != 0 )
00075         {
00076             OE_WARN << LC << "Failed to open database \"" << filename << "\": " << sqlite3_errmsg(_database) << std::endl;
00077             return;
00078         }
00079 
00080         //Print out some metadata
00081         std::string name, type, version, description, format;
00082         getMetaData( "name", name );
00083         getMetaData( "type", type);
00084         getMetaData( "version", version );
00085         getMetaData( "description", description );
00086         getMetaData( "format", format );
00087         OE_NOTICE << "name=" << name << std::endl
00088                   << "type=" << type << std::endl
00089                   << "version=" << version << std::endl
00090                   << "description=" << description << std::endl
00091                   << "format=" << format << std::endl;
00092 
00093         //Determine the tile format and get a reader writer for it.        
00094         if (_options.format().isSet())
00095         {
00096             //Get an explicitly defined format
00097             _tileFormat = _options.format().value();
00098         }
00099         else if (!format.empty())
00100         {
00101             //Try to get it from the database metadata
00102             _tileFormat = format;
00103         }
00104         else
00105         {
00106             //Assume it's PNG
00107             _tileFormat = "png";
00108         }
00109 
00110         OE_DEBUG << LC <<  "_tileFormat = " << _tileFormat << std::endl;
00111 
00112         //Get the ReaderWriter
00113         _rw = osgDB::Registry::instance()->getReaderWriterForExtension( _tileFormat );
00114 
00115         computeLevels();
00116     }    
00117 
00118     // override
00119     osg::Image* createImage( const TileKey& key,
00120                              ProgressCallback* progress)
00121     {             
00122         int z = key.getLevelOfDetail();
00123         int x = key.getTileX();
00124         int y = key.getTileY();
00125 
00126         if (z < _minLevel)
00127         {
00128             //Return an empty image to make it continue subdividing
00129             return ImageUtils::createEmptyImage();
00130         }
00131 
00132         if (z > _maxLevel)
00133         {
00134             //If we're at the max level, just return NULL
00135             return NULL;
00136         }
00137 
00138         unsigned int numRows, numCols;
00139         key.getProfile()->getNumTiles(key.getLevelOfDetail(), numCols, numRows);
00140         y  = numRows - y - 1;
00141 
00142         //Get the image
00143         sqlite3_stmt* select = NULL;
00144         std::string query = "SELECT tile_data from tiles where zoom_level = ? AND tile_column = ? AND tile_row = ?";
00145         int rc = sqlite3_prepare_v2( _database, query.c_str(), -1, &select, 0L );
00146         if ( rc != SQLITE_OK )
00147         {
00148             OE_WARN << LC << "Failed to prepare SQL: " << query << "; " << sqlite3_errmsg(_database) << std::endl;
00149             return false;
00150         }
00151 
00152         bool valid = true;        
00153         sqlite3_bind_int( select, 1, z );
00154         sqlite3_bind_int( select, 2, x );
00155         sqlite3_bind_int( select, 3, y );
00156 
00157 
00158         osg::Image* result = NULL;
00159         rc = sqlite3_step( select );
00160         if ( rc == SQLITE_ROW)
00161         {                     
00162             // the pointer returned from _blob gets freed internally by sqlite, supposedly
00163             const char* data = (const char*)sqlite3_column_blob( select, 0 );
00164             int imageBufLen = sqlite3_column_bytes( select, 0 );
00165 
00166             // deserialize the image from the buffer:
00167             std::string imageString( data, imageBufLen );
00168             std::stringstream imageBufStream( imageString );
00169             osgDB::ReaderWriter::ReadResult rr = _rw->readImage( imageBufStream );
00170             if (rr.validImage())
00171             {
00172                 result = rr.takeImage();            
00173             }
00174         }
00175         else
00176         {
00177             OE_DEBUG << LC << "SQL QUERY failed for " << query << ": " << std::endl;
00178             valid = false;
00179         }
00180 
00181         sqlite3_finalize( select );
00182         return result;
00183 
00184     }
00185 
00186     bool getMetaData( const std::string& key, std::string& value )
00187     {
00188         //get the metadata
00189         sqlite3_stmt* select = NULL;
00190         std::string query = "SELECT value from metadata where name = ?";
00191         int rc = sqlite3_prepare_v2( _database, query.c_str(), -1, &select, 0L );
00192         if ( rc != SQLITE_OK )
00193         {
00194             OE_WARN << LC << "Failed to prepare SQL: " << query << "; " << sqlite3_errmsg(_database) << std::endl;
00195             return false;
00196         }
00197 
00198 
00199         bool valid = true;
00200         std::string keyStr = std::string( key );
00201         rc = sqlite3_bind_text( select, 1, keyStr.c_str(), keyStr.length(), SQLITE_STATIC );
00202         if (rc != SQLITE_OK )
00203         {
00204             OE_WARN << LC << "Failed to bind text: " << query << "; " << sqlite3_errmsg(_database) << std::endl;
00205             return false;
00206         }
00207 
00208         rc = sqlite3_step( select );
00209         if ( rc == SQLITE_ROW)
00210         {                     
00211             value = (char*)sqlite3_column_text( select, 0 );
00212         }
00213         else
00214         {
00215             OE_DEBUG << LC << "SQL QUERY failed for " << query << ": " << std::endl;
00216             valid = false;
00217         }
00218 
00219         sqlite3_finalize( select );
00220         return valid;
00221     }
00222 
00223     void computeLevels()
00224     {        
00225         sqlite3_stmt* select = NULL;
00226         std::string query = "SELECT min(zoom_level), max(zoom_level) from tiles";
00227         int rc = sqlite3_prepare_v2( _database, query.c_str(), -1, &select, 0L );
00228         if ( rc != SQLITE_OK )
00229         {
00230             OE_WARN << LC << "Failed to prepare SQL: " << query << "; " << sqlite3_errmsg(_database) << std::endl;
00231         }
00232 
00233         rc = sqlite3_step( select );
00234         if ( rc == SQLITE_ROW)
00235         {                     
00236             _minLevel = sqlite3_column_int( select, 0 );
00237             _maxLevel = sqlite3_column_int( select, 1 );
00238             //OE_NOTICE << "Min=" << _minLevel << " Max=" << _maxLevel << std::endl;
00239         }
00240         else
00241         {
00242             OE_DEBUG << LC << "SQL QUERY failed for " << query << ": " << std::endl;
00243         }
00244 
00245         sqlite3_finalize( select );        
00246     }
00247 
00248     // override
00249     virtual std::string getExtension() const 
00250     {
00251         return _tileFormat;
00252     }
00253 
00254 private:
00255     const MBTilesOptions _options;    
00256     sqlite3* _database;
00257     unsigned int _minLevel;
00258     unsigned int _maxLevel;
00259 
00260     osg::ref_ptr<osgDB::ReaderWriter> _rw;
00261     std::string _tileFormat;
00262 
00263 };
00264 
00265 
00266 class MBTilesTileSourceFactory : public TileSourceDriver
00267 {
00268 public:
00269     MBTilesTileSourceFactory()
00270     {
00271         supportsExtension( "osgearth_mbtiles", "MBTiles Driver" );
00272     }
00273 
00274     virtual const char* className()
00275     {
00276         return "MBTiles ReaderWriter";
00277     }
00278 
00279     virtual ReadResult readObject(const std::string& file_name, const Options* options) const
00280     {
00281         if ( !acceptsExtension(osgDB::getLowerCaseFileExtension( file_name )))
00282             return ReadResult::FILE_NOT_HANDLED;
00283 
00284         return new MBTilesSource( getTileSourceOptions(options) );
00285     }
00286 };
00287 
00288 REGISTER_OSGPLUGIN(osgearth_mbtiles, MBTilesTileSourceFactory)
00289 
00290 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines