UNPKG

gis-tools-ts

Version:

A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.

120 lines 5.12 kB
import { JpxImage } from '../../../image/index.js'; import { complexUnpacking, spectralComplexUnpacking, spectralSimpleUnpacking } from './index.js'; // TODO: spectrals are not implemented correctly yet. // TODO: case 41: case 40010: PNG // TODO: case 42: AEC https://github.com/NOAA-EMC/NCEPLIBS-g2c/blob/develop/src/aecunpack.c /** * Converts data Buffer according to data representation section * @param reader - The raw data to convert * @param sections - The sections of the GRIB2 message that have been parsed so far * @returns Converted data */ export function getGrib2Template7(reader, sections) { const drs = sections.dataRepresentation; if (drs === undefined) throw new Error('Data Representation Section is not defined'); const { dataRepresentationTemplate } = drs; switch (dataRepresentationTemplate.code) { case 0: return simpleUnpacking(reader, drs); case 2: case 3: return complexUnpacking(reader, sections); case 40: case 40000: { const bms = sections.bitMap; if (bms === undefined) throw new Error('Bit Map Section is not defined'); return jpeg2000Unpacking(reader, drs, bms); } case 50: return spectralSimpleUnpacking(reader, drs); case 51: return spectralComplexUnpacking(reader, drs); default: throw new Error(`Template 7.${dataRepresentationTemplate} not defined`); } } /** * # Data Template 7.0 - Grid point data - simple packing * * [Read more...](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp7-0.shtml) * @param reader - The raw data to convert * @param drs - The data representation section * @returns - The converted data */ export function simpleUnpacking(reader, drs) { const { numberOfBits, decimalScaleFactor, referenceValue, binaryScaleFactor } = drs.dataRepresentation; const DD = Math.pow(10, decimalScaleFactor); const EE = Math.pow(2, binaryScaleFactor); const data = new Uint8Array(reader.slice().buffer); const totalBits = data.length * 8; const count = Math.floor(totalBits / numberOfBits); const values = []; let bitPos = 0; for (let i = 0; i < count; i++) { let acc = 0; for (let b = 0; b < numberOfBits; b++) { const byteIndex = Math.floor(bitPos / 8); const bitOffset = 7 - (bitPos % 8); const bit = (data[byteIndex] >> bitOffset) & 1; acc = (acc << 1) | bit; bitPos++; } values.push((referenceValue + acc * EE) / DD); } return values; } /** * # Data Template 7.40 - Grid point data - JPEG 2000 code stream format * * [Read more...](https://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_temp7-40.shtml) * @param reader - The raw data to convert * @param drs - The data representation section * @param bms - The bit map section * @returns - The converted data */ export function jpeg2000Unpacking(reader, drs, bms) { const jpx = new JpxImage(reader); if (jpx.componentsCount !== 1) throw new Error('JPEG Decoder: Only single component is supported'); if (jpx.tiles.length !== 1) throw new Error('JPEG Decoder: Only single tile is supported'); if (jpx.tiles[0].height !== 1) throw new Error('JPEG Decoder: Only single row (1xN) is supported'); const { bitMap: bitBuffer, bitMapIndicator } = bms; const { numberOfDataPoints, dataRepresentation } = drs; const { decimalScaleFactor, referenceValue, binaryScaleFactor, numberOfBits } = dataRepresentation; const DD = Math.pow(10, decimalScaleFactor); const EE = Math.pow(2, binaryScaleFactor); const result = []; if (numberOfBits === 0) { for (let i = 0; i < numberOfDataPoints; i++) result.push(referenceValue); return result; } // A bit map applies to this product if (bitMapIndicator.code === 0 && bitBuffer !== null) { const bitMapData = new Uint8Array(bitBuffer.buffer, bitBuffer.byteOffset, bitBuffer.byteLength); for (let i = 0; i < numberOfDataPoints; i++) { // Apply bit map to the data. // Length of data values is often smaller than the bit map itself. Bitmap is used to // indicate which data values are present, 1 bit meaning is present, 0 bit meaning is missing, -1 meaning undefined. // [Read more](https://confluence.ecmwf.int/display/UDOC/What+is+the+GRIB+bitmap+-+ecCodes+GRIB+FAQ) const byte = bitMapData[Math.floor(i / 8)]; if ((byte & (1 << (i % 8))) !== 0) { result.push((referenceValue + jpx.tiles[0].items[i] * EE) / DD); } else { result.push(Number.NEGATIVE_INFINITY); } } } else { // Do not use `.map` on Uint8Array, as it clamps the values to 0-255 for (const byte of jpx.tiles[0].items) result.push((referenceValue + byte * EE) / DD); } return result; } //# sourceMappingURL=templates.js.map