Как читать бинарные файлы NASA.hgt

Я уверен, что это действительно просто, если вы знаете что-нибудь о бинарных файлах, но я новичок на этом счету.

Как извлечь данные из файлов NASA.hgt? Вот описание из www2.jpl.nasa.gov/srtm/faq.html:

Файлы данных SRTM имеют имена типа "N34W119.hgt". Что буквы и цифры, и что такое формат .hgt?

Каждый файл данных покрывает одну градус широты на одну градус долготы блок поверхности Земли. Первые семь символов указывают на юго-запад угол блока, причем N, S, E и W относятся к северу, югу, востоку, и на запад. Таким образом, файл N34W119.hgt охватывает широты от 34 до 35 северных и долготы 118-119 запад (этот файл включает в себя центр Лос-Анджелеса, Калифорния). Расширение имени файла .hgt просто означает слово "высота", означающая возвышение. Это НЕ формат. Эти файлы в "сыром" формате (без заголовков и не сжатых), 16-разрядных целых чисел, высота, измеренная в метрах над уровнем моря, в "географическом" (широта) и longitude array) с данными, пропущенными -32768. Международные 3-дуговые файлы имеют 1201 столбцов и 1201 строк данных, с общим размером файла 2 884 802 байта (= 1201 x 1201 x 2). объединенный Штатные 1-арк-второй файлы имеют 3601 столбцов и 3601 строку данных, с общий размер файла составляет 25 934 402 байта (= 3601 x 3601 x 2). Для большего информация читает текстовый файл "SRTM_Topo.txt" в http://edcftp.cr.usgs.gov/pub/data/srtm/Readme.html

Спасибо за любую помощь! Я буду использовать эти данные в python script, поэтому, если вы не можете использовать какие-либо специфические для языка трюки для любых других языков, это было бы потрясающе.

Ответ 1

Проверенный пример numpy:

import os
import math
import numpy

fn = 'DMV/N51E000.hgt'

siz = os.path.getsize(fn)
dim = int(math.sqrt(siz/2))

assert dim*dim*2 == siz, 'Invalid file size'

data = numpy.fromfile(fn, numpy.dtype('>i2'), dim*dim).reshape((dim, dim))

Ответ 2

Поскольку записи фиксированной длины (16-разрядные целые числа), и вы знаете размер сетки (1201 x 1201 или 3601x3601), Python struct идеально подходит (непроверенный код):

from struct import unpack,calcsize

# 'row_length' being 1201 or 3601 and 'row' being the raw data for one row
def read_row( row, row_length ):
    format = 'h'  # h stands for signed short

    for i in range(0, row_length):
        offset = i * calcsize(format)
        (height,) = unpack(format, row[offset : offset+calcsize(format))
        # do something with the height

Описывая его в более общих терминах, в основном вы хотите прочитать файл в 2 байта за раз, проанализируйте байты, считанные как 16-разрядное целое число со знаком, и обработайте его. Поскольку вы уже знаете размер сетки, вы можете читать ее в строке за строкой или любым другим способом, удобным для вашего приложения. Это также означает, что вы можете произвольно искать конкретные координаты внутри файла данных.

Ответ 3

Если вам требуется немного больше скорости, чем вы получаете от миллионов вызовов struct.unpack, посмотрите на array.array. Хотя реализация "struct-and-for-loop" занимает несколько секунд на моем, по общему признанию, медленном ноутбуке, следующее мгновенно:

from array import array

f = open(filename, 'rb')
format = 'h'
row_length = 1201
data = array(format)
data.fromfile(f, row_length*row_length)
data.byteswap()
f.close()

Ответ 4

Файлы данных NAST SRTM находятся в формате Big-Endian, поэтому в зависимости от того, на какой платформе вы читаете данные, вам может потребоваться преобразование из Big-Endian в Little-Endian.

Есть много источников о том, как это сделать, у меня нет опыта работы с Python, поэтому я не могу вам помочь.

Но если вы забудете об этом, ваши ценности будут испорчены.

Ответ 5

Если у вас есть фотошоп, вы можете поиграть с сырым импортом, чтобы заставить его прочитать эти файлы и спасти их до чего-то более полезного. У меня был определенный успех в прошлом.