1

I have downloaded some of the NASA SRTM elevation data, which comes in binary files. The format is described as follows:

The DEM is provided as 16-bit signed integer data in a simple binary raster. There are no header or trailer bytes embedded in the file. The data are stored in row major order (all the data for row 1, followed by all the data for row 2, etc.).

All elevations are in meters referenced to the WGS84/EGM96 geoid as documented at http:// www.NGA.mil/GandG/wgsegm/.

Byte order is Motorola ("big-endian") standard with the most significant byte first. Since they are signed integers elevations can range from -32767 to 32767 meters, encompassing the range of elevation to be found on the Earth.

These data also contain occassional voids from a number of causes such as shadowing, phase unwrapping anomalies, or other radar-specific causes. Voids are flagged with the value -32768.

I am trying to parse these values with clojure for further analysis and visualization. My current code looks like this:

;; Taken from http://stackoverflow.com/a/26372677/2345852
(defn slurp-bytes
  "Slurp the bytes from a slurpable thing"
  [x]
  (with-open [out (java.io.ByteArrayOutputStream.)]
    (clojure.java.io/copy (clojure.java.io/input-stream x) out)
    (.toByteArray out)))

(defn read-elevation
  "Reads elevation data stored in .hgt files as provided by the NASA
  SRTM datasets"
  [src]
  (->> (slurp-bytes src)
       (partition 2)
       (map #(reduce + %))))

(read-elevation ...)

This however seems to output wrong data: I am looking at the Himalayas and the array holds numbers from -126 to 150. I suggest is because of wrong byte order (executing (java.nio.ByteOrder/nativeOrder) returns LITTLE_ENDIAN). How do I reverse the byte-order so that it's platform independent?

heyarne
  • 1,127
  • 9
  • 33

1 Answers1

1

I dont know much about the elevation data supplied by nasa, but if you want to have a different byte order, simply read through ByteBuffer. If you have a byte array, it could be easily converted to a ByteBuffer by wrapping:

(def bb (ByteBuffer/wrap b-array))
(.order bb ByteOrder/BIG_ENDIAN)

and to access, you could use any of ByteBuffer getters (i.e. getLong, getDouble, etc).

You could also read the file directly into a ByteBuffer, take a look for example here.

Community
  • 1
  • 1
Shlomi
  • 4,708
  • 1
  • 23
  • 32