diff --git a/vtm-android/src/org/oscim/android/tiling/source/mbtiles/MBTileDataSource.java b/vtm-android/src/org/oscim/android/tiling/source/mbtiles/MBTileDataSource.java new file mode 100644 index 000000000..183c11505 --- /dev/null +++ b/vtm-android/src/org/oscim/android/tiling/source/mbtiles/MBTileDataSource.java @@ -0,0 +1,74 @@ +package org.oscim.android.tiling.source.mbtiles; + +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; + +import org.oscim.layers.tile.MapTile; +import org.oscim.tiling.ITileDataSink; +import org.oscim.tiling.ITileDataSource; +import org.oscim.tiling.source.ITileDecoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +/** + * Created by chaohan on 14-4-3. + */ +public class MBTileDataSource implements ITileDataSource { + + static final Logger log = LoggerFactory.getLogger(MBTileDataSource.class); + + MBTileSource mMBTileSource; + ITileDecoder mTileDecoder; + + public final static String TABLE_TILES = "tiles"; + public final static String COL_TILES_ZOOM_LEVEL = "zoom_level"; + public final static String COL_TILES_TILE_COLUMN = "tile_column"; + public final static String COL_TILES_TILE_ROW = "tile_row"; + public final static String COL_TILES_TILE_DATA = "tile_data"; + + public MBTileDataSource(MBTileSource tileSource, ITileDecoder tileDecoder){ + mMBTileSource = tileSource; + mTileDecoder = tileDecoder; + } + + public void query(MapTile tile, ITileDataSink sink){ + + + try { + InputStream ret = null; + final String[] tiledata = { COL_TILES_TILE_DATA }; + final String[] xyz = { + Integer.toString(tile.tileX) + , Double.toString(Math.pow(2, tile.zoomLevel) - tile.tileY - 1) // Use Google Tiling Spec + , Integer.toString(tile.zoomLevel) + }; + + final Cursor cur = mMBTileSource.db.query(TABLE_TILES, tiledata, "tile_column=? and tile_row=? and zoom_level=?", xyz, null, null, null); + + if(cur.getCount() != 0) { + cur.moveToFirst(); + ret = new ByteArrayInputStream(cur.getBlob(0)); + } + cur.close(); + if(ret != null) { + if (mTileDecoder.decode(tile, sink, ret)) { + sink.completed(ITileDataSink.QueryResult.SUCCESS); + return; + } + } + } catch(final Throwable e) { + log.warn("Error getting db stream: " + tile, e); + sink.completed(ITileDataSink.QueryResult.FAILED); + } + sink.completed(ITileDataSink.QueryResult.FAILED); + + } + + public void destroy(){ + + } +} diff --git a/vtm-android/src/org/oscim/android/tiling/source/mbtiles/MBTileSource.java b/vtm-android/src/org/oscim/android/tiling/source/mbtiles/MBTileSource.java new file mode 100644 index 000000000..8a445468c --- /dev/null +++ b/vtm-android/src/org/oscim/android/tiling/source/mbtiles/MBTileSource.java @@ -0,0 +1,102 @@ +package org.oscim.android.tiling.source.mbtiles; + +import android.database.sqlite.SQLiteDatabase; + +import org.oscim.backend.CanvasAdapter; +import org.oscim.backend.canvas.Bitmap; +import org.oscim.core.Tile; +import org.oscim.tiling.ITileDataSink; +import org.oscim.tiling.ITileDataSource; +import org.oscim.tiling.TileSource; +import org.oscim.tiling.source.ITileDecoder; +import org.oscim.tiling.source.bitmap.BitmapTileSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by chaohan on 14-4-3. + */ +public class MBTileSource extends TileSource { + static final Logger log = LoggerFactory.getLogger(MBTileSource.class); + + SQLiteDatabase db; + + + public ITileDataSource getDataSource(){ + return new MBTileDataSource(this, new BitmapTileDecoder()); + } + + public boolean setFile(String filename) { + setOption("file", filename); + + File file = new File(filename); + + if (!file.exists()) { + return false; + } else if (!file.isFile()) { + return false; + } else if (!file.canRead()) { + return false; + } + + return true; + } + + public OpenResult open(){ + if (!options.containsKey("file")) + return new OpenResult("no mb file set"); + + try { + // make sure to close any previously opened file first + //close(); + + File file = new File(options.get("file")); + + // check if the file exists and is readable + if (!file.exists()) { + return new OpenResult("file does not exist: " + file); + } else if (!file.isFile()) { + return new OpenResult("not a file: " + file); + } else if (!file.canRead()) { + return new OpenResult("cannot read file: " + file); + } + + // open the file in read only mode + db = SQLiteDatabase.openDatabase(file.getAbsolutePath(),null, + SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READONLY); + + return OpenResult.SUCCESS; + } catch (Exception e) { + log.error(e.getMessage()); + // make sure that the file is closed + close(); + return new OpenResult(e.getMessage()); + } + } + + public void close(){ + if (db != null) + db.close(); + } + + public class BitmapTileDecoder implements ITileDecoder { + + @Override + public boolean decode(Tile tile, ITileDataSink sink, InputStream is) + throws IOException { + + Bitmap bitmap = CanvasAdapter.g.decodeBitmap(is); + if (!bitmap.isValid()) { + log.debug("{} invalid bitmap", tile); + return false; + } + sink.setTileImage(bitmap); + + return true; + } + } +}