osgEarth 2.1.1
|
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