Altimeter Cloud tree canopy reader and LZMA decoder
====================================================

Packed 26/09/2026.

These were current when this zip was made. Years on there may well be newer
versions: check https://www.7-zip.org/sdk.html for the LZMA SDK, and
https://www.altimetercloud.com/api/docs/trees/ for the tree file format and
this reader.

What is in here
---------------

tree_reader.h and tree_reader.c
    Read a tree canopy file from the Altimeter Cloud Tree Canopy API
    (format=bin) on a microcontroller or anywhere else with a C or C++
    compiler. Include tree_reader.h and call:

      treeHeader()      checks the file and gives its header
      treeAt()          what's below me: the cell a position is in
      bandMetres()      a band's height range in metres
      treesWithin()     trees within a radius: how many, the nearest, the tallest
      treeUnpackLzma()  unpacks a compress=lzma download with LzmaDecode()

    Free to use, change and share, in any project.

LzmaDec.c, LzmaDec.h, 7zTypes.h, Precomp.h, Compiler.h
    The LZMA decoder from the LZMA SDK by Igor Pavlov, exactly as built into
    the Altimeter Cloud Jupiter flight computer: the 2018 release (LzmaDec.c
    2018-02-28, LzmaDec.h 2018-04-21; each file's first line gives its date).
    Precomp.h carries one added line, #define _7ZIP_ST, for a single-threaded
    build. The LZMA SDK is in the public domain: anyone may copy, modify,
    publish, use, compile, sell or distribute it, for any purpose.
    https://www.7-zip.org/sdk.html

Using it
--------

Arduino: copy tree_reader.h and tree_reader.c into the sketch folder, and for
.lzma files LzmaDec.c, LzmaDec.h, 7zTypes.h, Precomp.h and Compiler.h too. Then in
the sketch:

    #include "tree_reader.h"

    const TreeHeader *h = treeHeader(file, file_len);
    if (h) {
      const uint8_t *cells = treeCells(file);
      int below = treeAt(h, cells, lat, lon);            // what's below me
      TreeNear t = treesWithin(h, cells, lat, lon, 50);  // trees within 50 m
    }

tree_reader.h has the details of each function. treeUnpackLzma() is only
built when LzmaDec.h is beside tree_reader.c, so leave the SDK files out if
your files are stored unpacked (compress=none) and it drops out by itself.

Other builds: add tree_reader.c (and LzmaDec.c for .lzma files) to the build
and include tree_reader.h.

treeUnpackLzma() needs the unpacked file's size in memory (it is the size
given in bytes 5 to 12 of the .lzma file) plus about 16 KB while it works.
The Jupiter's own files use the same settings: lc=3 lp=0 pb=2 and a 64 KB
dictionary.

zlib: an ESP32 already has a zlib decoder (miniz's tinfl) in its ROM, so
compress=zlib files need nothing extra there.
