georaster icon indicating copy to clipboard operation
georaster copied to clipboard

Save as PNG

Open DanielJDufour opened this issue 7 years ago • 2 comments

Is your feature request related to a problem? Please describe.

Sometimes users might want to save their GeoRaster as a PNG file. For example, this would be useful for displaying results in Observable or Jupyter Notebooks.

Describe the solution you'd like

We should create a new function called savePNG that returns an (array)buffer for a PNG.

Describe alternatives you've considered

I've thought about creating a save method where you pass in the filename and the function auto-detects the file type from the extension of the filename. I don't think this would be a good idea, because we can't easily save files in the browser and I think this would make this package much more complicated. Perhaps, we can explore this after creating the function that creates the arraybuffer because I think this is a pre-requisite to saving a file, anyway.

Additional context

Should users have to manually create a data URI like those found at https://en.wikipedia.org/wiki/Data_URI_scheme or should we have a separate method savePNGDataURI. It might be more maintainable to force the users to construct their own data URIs, but I'm not sure what % of users will know how to do this.

DanielJDufour avatar Jul 21 '18 17:07 DanielJDufour

This is something I implemented using pngjs, here is the snippet:

const parse_georaster = require('georaster')
const { PNG } = require('pngjs')
const hexRgb = require('hex-rgb')

const georaster = await parse_georaster(tiffBuffer)
const { width, height } = georaster
const png = new PNG({ width, height })
const band = georaster.values[0]
for(let x = 0; x < band.length; x++) {
  for(let y = 0; y < band[x].length; y++) {
    if(band[x] && band[x][y]) {
      // I need to "translate" values to colors myself, you might as well use the color if it's in the TIFF
      const color = pixelValueToColor(band[x][y])
      const rgba = color ? hexRgb(color, {format: 'array'}) : [ 0, 0, 0, 0 ]
      const idx = (width * x + y) << 2
      png.data[idx  ] = rgba[0]
      png.data[idx+1] = rgba[1]
      png.data[idx+2] = rgba[2]
      png.data[idx+3] = rgba[3] * 255
    }
  }
}
const pngBuffer = PNG.sync.write(png)

from there you can write the PNG to a file, produce a data URI, stream it or anything else you can do with a buffer.

GabiAxel avatar Mar 21 '19 13:03 GabiAxel

Awesome!

DanielJDufour avatar Mar 21 '19 22:03 DanielJDufour