module NSWTopo::Formats
def rasterise(png_path, background:, ppi: nil, resolution: nil)
def rasterise(png_path, background:, ppi: nil, resolution: nil) Dir.mktmppath do |temp_dir| svg_path = temp_dir / "map.svg" vrt_path = temp_dir / "map.vrt" render_svg svg_path, background: background case when ppi ppi_info = "%i ppi" % ppi mm_per_px = 25.4 / ppi when resolution ppi_info = "%.1f m/px" % resolution mm_per_px = to_mm(resolution) end viewport_size = [TILE * mm_per_px] * 2 raster_size = @dimensions.map { |dimension| (dimension / mm_per_px).ceil } megapixels = raster_size.inject(&:*) / 1024.0 / 1024.0 raster_info = "%i×%i (%.1fMpx) map raster at %s" % [*raster_size, megapixels, ppi_info] log_update "chrome: creating #{raster_info}" raster_size.map do |px| (0...px).step(TILE).map do |px| [px, px * mm_per_px] end end.inject(&:product).map(&:transpose).map do |raster_offset, viewport_offset| next raster_offset, viewport_offset, temp_dir.join("tile.%i.%i.png" % raster_offset) end.inject(ThreadPool.new(CHROME_INSTANCES), &:<<).in_groups do |*grid| NSWTopo::Chrome.with_browser "file://#{svg_path}", width: TILE, height: TILE, args: CHROME_ARGS do |browser| svg = browser.query_selector "svg" svg[:width], svg[:height] = nil, nil grid.each do |raster_offset, viewport_offset, tile_path| svg[:viewBox] = [*viewport_offset, *viewport_size].join(?\s) browser.screenshot tile_path end end end.map do |raster_offset, viewport_offset, tile_path| REXML::Document.new(OS.gdal_translate "-of", "VRT", tile_path, "/vsistdout/").tap do |vrt| vrt.elements.each("VRTDataset/VRTRasterBand/SimpleSource/DstRect") do |dst_rect| dst_rect.add_attributes "xOff" => raster_offset[0], "yOff" => raster_offset[1] end end end.inject do |vrt, tile_vrt| vrt.elements["VRTDataset/VRTRasterBand[@band='1']"].add_element tile_vrt.elements["VRTDataset/VRTRasterBand[@band='1']/SimpleSource"] vrt.elements["VRTDataset/VRTRasterBand[@band='2']"].add_element tile_vrt.elements["VRTDataset/VRTRasterBand[@band='2']/SimpleSource"] vrt.elements["VRTDataset/VRTRasterBand[@band='3']"].add_element tile_vrt.elements["VRTDataset/VRTRasterBand[@band='3']/SimpleSource"] vrt.elements["VRTDataset/VRTRasterBand[@band='4']"].add_element tile_vrt.elements["VRTDataset/VRTRasterBand[@band='4']/SimpleSource"] vrt end.tap do |vrt| vrt.elements.each("VRTDataset/VRTRasterBand/@blockYSize", &:remove) vrt.elements.each("VRTDataset/Metadata", &:remove) vrt.elements["VRTDataset"].add_attributes "rasterXSize" => raster_size[0], "rasterYSize" => raster_size[1] File.write vrt_path, vrt end log_update "nswtopo: finalising #{raster_info}" OS.gdal_translate vrt_path, png_path end end