This project has moved and is read-only. For the latest updates, please go here.

Speed up by create Tile from bytes

Apr 18, 2016 at 4:18 AM
The current BruTileHelper.DrawRasterNew method or tile cache mode use the world file to define the tile geolocation and this mode will
store huge small files on local disk is diffcult to copy or delete.
So if we cache the tiles in mbtile or even sqlite db we can easy to manage the tile caches
the fallow shows a way to reproject the tile on fly and show tile bytes from database in ArcGIS
may give some hints for someone interested.
//envelopeTo:the tile's geo envelope which belongs td
private bool DrawRaster(byte[] td, IEnvelope envelopeTo, ITileSchema schema, ITrackCancel trackCancel)
{
IWorkspaceFactory workspaceFactory = new RasterWorkspaceFactoryClass();
//DefaultCacheDir a directory on the local disk , but will not store data in it
IRasterWorkspace3 rasterWorkspace = (IRasterWorkspace3)workspaceFactory.OpenFromFile(DefaultCacheDir, 0);
if(rasterWorkspace == null)return false;
        // Create RasterDataset from Bytes
        IRasterDataset rasterDataset = rasterWorkspace.OpenRasterDatasetFromBytes(ref td, true);
        //get the default raster we define the srs according envelopeTo(the td bytes holded tile Envelope)
        //and the dataspatialreference 
        IRaster raster = rasterDataset.CreateDefaultRaster();
        IRasterProps rasterProps = raster as IRasterProps;
        IEnvelope extent = rasterProps.Extent;
        double x = rasterProps.MeanCellSize().X;
        double y = rasterProps.MeanCellSize().Y;
        // Define missing variable
        object missing = Missing.Value;
        IGeoDataset geoDatasetFrom = (IGeoDataset)rasterDataset;
        IEnvelope envelopeFrom = geoDatasetFrom.Extent;
        IPointCollection pointCollectionFrom = new MultipointClass();
        pointCollectionFrom.AddPoint(envelopeFrom.LowerLeft, ref missing, ref missing);
        pointCollectionFrom.AddPoint(envelopeFrom.UpperLeft, ref missing, ref missing);
        pointCollectionFrom.AddPoint(envelopeFrom.UpperRight, ref missing, ref missing);
        pointCollectionFrom.AddPoint(envelopeFrom.LowerRight, ref missing, ref missing);

        // Create To PointCollection
        IPointCollection pointCollectionTo = new MultipointClass();
        pointCollectionTo.AddPoint(envelopeTo.LowerLeft, ref missing, ref missing);
        pointCollectionTo.AddPoint(envelopeTo.UpperLeft, ref missing, ref missing);
        pointCollectionTo.AddPoint(envelopeTo.UpperRight, ref missing, ref missing);
        pointCollectionTo.AddPoint(envelopeTo.LowerRight, ref missing, ref missing);

        // Create Polynomical Adjustment
        IPolynomialXform polynomial = new PolynomialXformClass();
        polynomial.DefineFromControlPoints(pointCollectionFrom, pointCollectionTo, 1);
        polynomial.SpatialReference = dataSpatialReference;

        // Set the XForm
        IRaster2 raster2 = (IRaster2)raster;
        raster2.GeodataXform = polynomial;

        // Transform the Cell Size
        polynomial.TransformCellsize(esriTransformDirection.esriTransformForward, ref x, ref y, extent);
        polynomial.TransformExtent(esriTransformDirection.esriTransformForward, extent);

        // Set the transformed extent and cell size to the raster
        rasterProps.Extent = extent;
        rasterProps.Width = Convert.ToInt32(Convert.ToDouble(extent.Width) / x);
        rasterProps.Height = Convert.ToInt32(Convert.ToDouble(extent.Height) / y);
        //rasterProps.SpatialReference = dataSpatialReference;//the spatial reference created according to tile schema
        IRasterLayer layer = new RasterLayerClass();
        layer.CreateFromRaster(raster);

        //if we need reproject we use the fast mode to reproject
        if (this._needReproject)
        {
            IRasterGeometryProc proc = new RasterGeometryProcClass();
            //object missing = System.Type.Missing;
            proc.ProjectFast(layerSpatialReference, rstResamplingTypes.RSP_NearestNeighbor, ref missing, layer.Raster);
        }
        //IRasterProps props2 = (IRasterProps)layer.Raster;
        layer.Renderer.ResamplingType = rstResamplingTypes.RSP_BilinearInterpolation;
        IRasterRenderer renderer = layer.Renderer;
        IRasterStretch stretch = renderer as IRasterStretch;
        stretch.StretchType = esriRasterStretchTypesEnum.esriRasterStretch_NONE;
        IRasterStretch3 stretch2 = renderer as IRasterStretch3;
        stretch2.UseGamma = false;
        renderer.Update();
        layer.Renderer = renderer;
        layer.SpatialReference = layerSpatialReference;//the spatialreference of map or mxd
        layer.Draw(esriDrawPhase.esriDPGeography, this.display, null);
        return true;
}
Apr 18, 2016 at 7:02 AM
Hi thanks for this code, I will try it out. I'm glad there seems to be a way to avoid creating those small world files.
Also good suggestion to use MBTiles or SQLite.