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