LAZ is defined by the open-source LASzip library and its design notes, both on GitHub under LASzip. A LAZ file is a LAS file whose point records are compressed; everything else keeps the LAS layout. This page describes that container: what changes in the LAS structures, the LASzip record and the chunks. The arithmetic coding of each field is described only in outline, as the design notes do; the exact models are those in the LASzip source code.
File layout
| Part | Compressed? | Notes |
|---|---|---|
| Public header block | No | As in LAS, except that bit 7 of Point Data Record Format is set: formats 128 to 138 mean LAS formats 0 to 10, compressed |
| VLRs | No | As in LAS, plus the LASzip VLR |
| Chunk table offset | No | At Offset to Point Data: an int64 giving the position of the chunk table, for the chunked compressors |
| Chunks | Yes | The points, in independent chunks |
| Chunk table | Partly | Where each chunk starts and, for variable chunks, how many points it holds |
| EVLRs | No | As in LAS 1.4 |
When the chunk table offset is −1, the writer could not seek back to fill it in, and the real offset is in the last 8 bytes of the file. Point Data Record Length keeps the uncompressed size of a point.
LASzip VLR
A VLR with User ID laszip encoded and Record ID 22204. Its data is 34
bytes plus 6 for each item:
| Offset | Size | Type | Name | Meaning |
|---|---|---|---|---|
| 0 | 2 | uint16 | compressor | See below |
| 2 | 2 | uint16 | coder | 0, arithmetic coding (the only coder) |
| 4 | 1 | uint8 | version_major | LASzip version that wrote the file, such as 3 |
| 5 | 1 | uint8 | version_minor | |
| 6 | 2 | uint16 | version_revision | |
| 8 | 4 | uint32 | options | Bit 0: LAS 1.4 compatibility mode, in which formats 6 to 10 are stored as formats 1 to 5 plus extra bytes |
| 12 | 4 | uint32 | chunk_size | Points per chunk, 50,000 by default; 0xFFFFFFFF means chunks of varying size |
| 16 | 8 | int64 | number_of_special_evlrs | Reserved for special EVLRs; −1 when not used, as LASzip writes it |
| 24 | 8 | int64 | offset_to_special_evlrs | Reserved for special EVLRs; −1 when not used |
| 32 | 2 | uint16 | num_items | Items that make up one point |
| 34 | 6 × n | items | items | For each item: uint16 type, uint16 size, uint16 version |
Compressors
| Value | Name | Meaning |
|---|---|---|
| 0 | None | Not compressed |
| 1 | Pointwise | One compressed stream, no chunks |
| 2 | Pointwise chunked | Point formats 0 to 5: chunks, each point coded field by field |
| 3 | Layered chunked | Point formats 6 to 10: chunks whose fields are coded in separate layers |
Item types
A point is the items in order; their sizes add up to the point record length.
| Type | Name | Size | Holds |
|---|---|---|---|
| 0 | BYTE | Any | Extra bytes (formats 0 to 5) |
| 1 | SHORT | – | Defined but not used |
| 2 | INT | – | Defined but not used |
| 3 | LONG | – | Defined but not used |
| 4 | FLOAT | – | Defined but not used |
| 5 | DOUBLE | – | Defined but not used |
| 6 | POINT10 | 20 | The core of formats 0 to 5 |
| 7 | GPSTIME11 | 8 | GPS time (formats 1, 3, 4, 5) |
| 8 | RGB12 | 6 | Colour (formats 2, 3, 5) |
| 9 | WAVEPACKET13 | 29 | Wave packet fields (formats 4, 5) |
| 10 | POINT14 | 30 | The core of formats 6 to 10, GPS time included |
| 11 | RGB14 | 6 | Colour (format 7) |
| 12 | RGBNIR14 | 8 | Colour and near infrared (formats 8, 10) |
| 13 | WAVEPACKET14 | 29 | Wave packet fields (formats 9, 10) |
| 14 | BYTE14 | Any | Extra bytes (formats 6 to 10) |
The item version selects the coding: 1 or 2 for the older items, and 3 or 4 for the LAS 1.4 items (version 4 fixed an error in how contexts are switched between scanner channels).
Chunks
Each chunk can be decompressed on its own: the coders start afresh, and the first point of the chunk is stored uncompressed.
Formats 0 to 5
After the raw first point comes one arithmetic-coded stream in which each following point is coded item by item, each field predicted from the point before.
Formats 6 to 10
After the raw first point come a uint32 count of the remaining points in the chunk, then a uint32 byte size for each layer, then the layers themselves, so a reader can skip layers it does not need. The layers are, in order:
- Scanner channel, return counts, X and Y, and flags saying whether the point source ID, GPS time and scan angle changed (always present)
- Z
- Classification
- Flags
- Intensity
- Scan angle
- User data
- Point source ID
- GPS time
- RGB, if present
- NIR, if present
- Wave packet, if present
- One layer per extra byte, if any
Within a chunk, each point is predicted from the previous point of the same scanner channel.
Chunk table
| Size | Type | Meaning |
|---|---|---|
| 4 | uint32 | Version, 0 |
| 4 | uint32 | Number of chunks |
| varies | arithmetic coded | For each chunk: its point count (only when chunk_size is 0xFFFFFFFF), then its size in bytes, each coded as the difference from the previous chunk’s value |
The first chunk starts right after the 8-byte chunk table offset; adding the chunk sizes in turn gives the start of every other chunk.