1

I am trying to return a binary array of floating points. I get a Float32Array from a geotiff library, however the http can only return a string or buffer so I have to 'convert' it to a buffer.

const tiff  = await geotiff.fromUrl(ahnUrl);
const image = await tiff.getImage();
const data  = await image.readRasters(); <-- Is Float32Array
res.writeHead(200, {'Content-Type': 'application/octet-stream'});
var buf = Buffer.allocUnsafe( data.width * data.height );
for ( var y = 0; y < data.height; y++ )
{
  for ( var x = 0; x < data.width; x++ )
  {
    buf.writeFloatLE(data[y*data.width+x]);
  }
}
// buf = Buffer.from(data); <-- does not work
// buf = Buffer.from(data.buffer); neither
res.end(buf);

The problem is the double for loop, I do not want this. Ideally, there is no additional data copy and definitely not this very slow double for loop. Speed is pretty critical.

I am new to javascript/nodejs, but it appears that the Float32Array is multidimensional as its length returns 1, but its width and height are 1024x1024 (as expected).

The result of 'const buf = Buffer.from(data)' is a buffer with a single byte length.

2 Answers 2

1

A thanks, this does help. However, doing Buffer.from( Float32Array ) results in a 1byte per float buffer plus it copies the data. To get it working you also have to use this package:

let toBuffer = require("typedarray-to-buffer")
function()
{
  const data  = await image.readRasters({interleave:true});
  const buf   = toBuffer(data); <-- Now if contains 1 float, this is 4 bytes long.
}
Sign up to request clarification or add additional context in comments.

1 Comment

If my answer helped, please consider up-voting or marking it as correct. Anyway, look at the code for "typedarray-to-buffer". For TypedArrays like Float32Array, all it does is call Buffer.from(arr.buffer); As such I still stand by my answer: it answers the question succinctly without a third-party library. In other words, providing interleave: true and then using Buffer.from works correctly. github.com/feross/typedarray-to-buffer/blob/master/index.js#L16
0

I think you've misunderstood the return type of readRasters. As far as I can tell from the docs, it's not by default a Float32Array, but an array of arrays (one for each channel, e.g. R, G, and B).

By default, the raster is split to a separate array for each component. For an RGB image for example, we'd get three arrays, one for red, green and blue.

Try passing {interleave: true} to readRasters.

If we want instead all the bands interleaved in one big array, we have to pass the interleave: true option:

After that Buffer.from aught to do the trick.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.