void rasterize(std::ostream &output, const OsmAnd::EyePiece::Configuration& cfg) #endif { // Obtain and configure rasterization style context OsmAnd::MapStyles stylesCollection; for(auto itStyleFile = cfg.styleFiles.begin(); itStyleFile != cfg.styleFiles.end(); ++itStyleFile) { const auto& styleFile = *itStyleFile; if(!stylesCollection.registerStyle(styleFile.absoluteFilePath())) output << xT("Failed to parse metadata of '") << QStringToStlString(styleFile.fileName()) << xT("' or duplicate style") << std::endl; } std::shared_ptr<const OsmAnd::MapStyle> style; if(!stylesCollection.obtainStyle(cfg.styleName, style)) { output << xT("Failed to resolve style '") << QStringToStlString(cfg.styleName) << xT("'") << std::endl; return; } if(cfg.dumpRules) style->dump(); OsmAnd::ObfsCollection obfsCollection; obfsCollection.watchDirectory(cfg.obfsDir); // Collect all map objects (this should be replaced by something like RasterizerViewport/RasterizerContext) QList< std::shared_ptr<const OsmAnd::Model::MapObject> > mapObjects; OsmAnd::AreaI bbox31( OsmAnd::Utilities::get31TileNumberY(cfg.bbox.top), OsmAnd::Utilities::get31TileNumberX(cfg.bbox.left), OsmAnd::Utilities::get31TileNumberY(cfg.bbox.bottom), OsmAnd::Utilities::get31TileNumberX(cfg.bbox.right) ); const auto& obfDI = obfsCollection.obtainDataInterface(); OsmAnd::MapFoundationType mapFoundation; obfDI->obtainMapObjects(&mapObjects, &mapFoundation, bbox31, cfg.zoom, nullptr); bool basemapAvailable; obfDI->obtainBasemapPresenceFlag(basemapAvailable); // Calculate output size in pixels const auto tileWidth = OsmAnd::Utilities::getTileNumberX(cfg.zoom, cfg.bbox.right) - OsmAnd::Utilities::getTileNumberX(cfg.zoom, cfg.bbox.left); const auto tileHeight = OsmAnd::Utilities::getTileNumberY(cfg.zoom, cfg.bbox.bottom) - OsmAnd::Utilities::getTileNumberY(cfg.zoom, cfg.bbox.top); const auto pixelWidth = qCeil(tileWidth * cfg.tileSide); const auto pixelHeight = qCeil(tileHeight * cfg.tileSide); output << xT("Will rasterize ") << mapObjects.count() << xT(" objects onto ") << pixelWidth << xT("x") << pixelHeight << xT(" bitmap") << std::endl; // Allocate render target SkBitmap renderSurface; renderSurface.setConfig(cfg.is32bit ? SkBitmap::kARGB_8888_Config : SkBitmap::kRGB_565_Config, pixelWidth, pixelHeight); if(!renderSurface.allocPixels()) { output << xT("Failed to allocated render target ") << pixelWidth << xT("x") << pixelHeight; return; } SkDevice renderTarget(renderSurface); // Create render canvas SkCanvas canvas(&renderTarget); // Perform actual rendering OsmAnd::RasterizerEnvironment rasterizerEnv(style, basemapAvailable); OsmAnd::RasterizerContext rasterizerContext; OsmAnd::Rasterizer::prepareContext(rasterizerEnv, rasterizerContext, bbox31, cfg.zoom, cfg.tileSide, cfg.densityFactor, mapFoundation, mapObjects, OsmAnd::PointF(), nullptr); if(cfg.drawMap) OsmAnd::Rasterizer::rasterizeMap(rasterizerEnv, rasterizerContext, true, canvas, nullptr); /*if(cfg.drawText) OsmAnd::Rasterizer::rasterizeText(rasterizerContext, !cfg.drawMap, canvas, nullptr);*/ // Save rendered area if(!cfg.output.isEmpty()) { std::unique_ptr<SkImageEncoder> encoder(CreatePNGImageEncoder()); std::unique_ptr<SkImageEncoder> outputStream(CreatePNGImageEncoder()); encoder->encodeFile(cfg.output.toLocal8Bit(), renderSurface, 100); } return; }
bool OsmAnd::OfflineMapRasterTileProvider_GPU_P::obtainTile(const TileId& tileId, const ZoomLevel& zoom, std::shared_ptr<MapTile>& outTile) { // Get bounding box that covers this tile const auto tileBBox31 = Utilities::tileBoundingBox31(tileId, zoom); // Obtain OBF data interface const auto& dataInterface = owner->dataProvider->obfsCollection->obtainDataInterface(); // Get map objects from data proxy QList< std::shared_ptr<const Model::MapObject> > mapObjects; #if defined(_DEBUG) || defined(DEBUG) const auto dataRead_Begin = std::chrono::high_resolution_clock::now(); #endif bool basemapAvailable; MapFoundationType tileFoundation; dataInterface->obtainBasemapPresenceFlag(basemapAvailable, nullptr); dataInterface->obtainMapObjects(&mapObjects, &tileFoundation, tileBBox31, zoom, nullptr); #if defined(_DEBUG) || defined(DEBUG) const auto dataRead_End = std::chrono::high_resolution_clock::now(); const std::chrono::duration<float> dataRead_Elapsed = dataRead_End - dataRead_Begin; #endif #if defined(_DEBUG) || defined(DEBUG) const auto dataRasterization_Begin = std::chrono::high_resolution_clock::now(); #endif //TODO: SkGpuDevice // Allocate rasterization target auto rasterizationSurface = new SkBitmap(); rasterizationSurface->setConfig(SkBitmap::kARGB_8888_Config, outputTileSize, outputTileSize); if(!rasterizationSurface->allocPixels()) { delete rasterizationSurface; LogPrintf(LogSeverityLevel::Error, "Failed to allocate buffer for ARGB8888 rasterization surface %dx%d", outputTileSize, outputTileSize); return false; } SkBitmapDevice rasterizationTarget(*rasterizationSurface); // Create rasterization canvas SkCanvas canvas(&rasterizationTarget); // Perform actual rendering bool nothingToRasterize = false; RasterizerEnvironment rasterizerEnv(owner->dataProvider->mapStyle, basemapAvailable, density); RasterizerContext rasterizerContext; Rasterizer::prepareContext(rasterizerEnv, rasterizerContext, tileBBox31, zoom, outputTileSize, tileFoundation, mapObjects, OsmAnd::PointF(), ¬hingToRasterize, nullptr); if(!nothingToRasterize) Rasterizer::rasterizeMap(rasterizerEnv, rasterizerContext, true, canvas, nullptr); #if defined(_DEBUG) || defined(DEBUG) const auto dataRasterization_End = std::chrono::high_resolution_clock::now(); const std::chrono::duration<float> dataRasterization_Elapsed = dataRasterization_End - dataRasterization_Begin; if(!nothingToRasterize) { LogPrintf(LogSeverityLevel::Info, "%d map objects from %dx%d@%d: reading %fs, rasterization %fs", mapObjects.count(), tileId.x, tileId.y, zoom, dataRead_Elapsed.count(), dataRasterization_Elapsed.count()); } else { LogPrintf(LogSeverityLevel::Info, "%d map objects from %dx%d@%d: reading %fs, nothing to rasterize (%fs)", mapObjects.count(), tileId.x, tileId.y, zoom, dataRead_Elapsed.count(), dataRasterization_Elapsed.count()); } #endif // If there is no data to rasterize, tell that this tile is not available if(nothingToRasterize) { delete rasterizationSurface; outTile.reset(); return true; } // Or supply newly rasterized tile auto tile = new MapBitmapTile(rasterizationSurface, MapBitmapTile::AlphaChannelData::NotPresent); outTile.reset(tile); return true; }