Leica CityMapper
Aerial deliveries flown with a Leica CityMapper-2, in the Dutch Beeldmateriaal folder structure: distortion-free TIFF frames from the nadir and four oblique heads, the block adjustment's orientation file and a footprint shapefile, and optionally a true-ortho mosaic and LAZ tiles of the same flight.
This page is the delivery standard. Everything it lists is checked when the delivery is handed over, and a delivery that does not match is sent back with the reason. There are no parameters to set: a delivery that follows the standard needs none.
Photos are indexed per head, as five sets: Nadir,
Forward, Backward, Left and Right.
Folder layout#
<dataset bucket>/
├── 05_Luchtfotografie/
│ ├── 03_Footprints/
│ │ └── <name>.shp .shx .dbf .prj exactly one shapefile
│ ├── 06_Verticale_Luchtfotografie/
│ │ └── <head>_<line>_00<HHMMSS>.tif nadir frames
│ └── 07_Oblieke_Luchtfotografie/
│ └── <head>_<line>_00<HHMMSS>.tif oblique frames, all four heads
├── 06_Aansluitingsvereffening/
│ └── 01_BM5_Bestanden/
│ └── <name>_uitwendig_geleverde_beelden.txt exactly one: the orientations
├── 07_Trueorthofotomozaiek/ optional: .ecw / .tif
└── 08_Laserdata/
└── 05_LAZ_Tiles/ optional: .laz, directly inside
The ortho folder is looked for under these names, in this order — the first containing at least one matching file wins:
07_Trueorthofotomozaiek/
The pointcloud folder is looked for under these names, in this order — the first containing at least one matching file wins:
08_Laserdata/05_LAZ_Tiles/
Everything else in the bucket is welcome and not read: project area and
flight plan, ground control, flight report, the GNSS/IMU orientations in
08_Direct_Referencing_Orientaties, the other block-adjustment files
(including …_uitwendig_xas_in_vliegrichting.txt), calibration reports and
quality reports. Subfolders of the photo, ortho and LAZ folders are not read
either.
Photos#
-
Names are
<head>_<line>_00<HHMMSS>.tif, e.g.401_0001_00092720.tif: three digits for the camera head, four for the flight line, and the exposure time as00HHMMSSin UTC. Names are unique within a delivery, and the extension is a lower-case.tif. -
Head numbers are yours to choose (
401–405,501–505, …) as long as they stay the same throughout the delivery. You do not say which head is which: that is read from the orientations (see Orientations). The nadir head's frames go in06_Verticale_Luchtfotografie/, the four oblique heads' in07_Oblieke_Luchtfotografie/. -
The frames are the distortion-free output at the nominal focal length (71 mm nadir, 112 mm oblique) with no principal-point offset: 8-bit RGB TIFF, 14192 × 10640 pixels of 3.76 µm, tiled or striped. Uncompressed is accepted; LZW, Deflate, JPEG, PackBits, Zstandard and WebP compression are too, and preferred — an uncompressed frame is 462 MB.
-
Every frame is named
<head>_<line>_00<HHMMSS>.tif: three digits for the camera head, four for the flight line, and the exposure time in UTC (e.g.401_0001_00092720.tif). Head numbers are free to choose but stay the same within a delivery, and one head's frames all go in one folder. -
Every frame has a row in the orientation file under its file name.
-
Every frame's TIFF header must parse (it is read from the start of the file; the pixels are not downloaded) and describe a CityMapper-2 frame: 14192 × 10640 pixels, three 8-bit samples (RGB), uncompressed or compressed with LZW, Deflate, JPEG, PackBits, Zstandard or WebP.
-
The pixel data each frame's header points at must all be in the file. This catches a partial upload, which a header check alone cannot see when the header sits at the start of the file.
Orientations#
One file in 06_Aansluitingsvereffening/01_BM5_Bestanden/ whose name ends in
_uitwendig_geleverde_beelden.txt: the adjusted exterior orientation
straight from the block adjustment, for the photos as delivered.
- One row per delivered photo — nadir and oblique — and no other rows.
- Whitespace-separated, no header:
<photo>.tif E N H omega phi kappa. E,N,Hin the dataset's coordinate reference system (for RD New + NAP: metres easting, northing and height); the angles in degrees.- The angles in the Beeldmateriaal convention:
X − X₀ = λ · R(ω) R(φ) R(κ) · (x, y, −c)with the standard right-handed rotation matrices, terrain x east, y north, z up; photo x along the image's short side, the camera looking along −z. - The angles describe the delivered pixels. With photo +x pointing toward the image's last pixel row, the delivered frames put it:
| Head | Photo +x points |
|---|---|
| Nadir | along the flight direction |
| Forward | toward the near edge of the footprint |
| Backward, Left, Right | toward the far edge of the footprint |
This is the convention of …_uitwendig_geleverde_beelden.txt in the 2025
and 2026 deliveries. Do not deliver the BINGO frame
(…_uitwendig_xas_in_vliegrichting.txt, x in the flight direction for every
head) or the GNSS/IMU orientations in its place: their kappa does not
describe the frames, and the delivery is sent back.
Which head is which follows from the angles: the head looking straight down is the nadir head, and the four oblique heads are told apart by their view direction against each flight line's heading.
Example#
401_0001_00092720.tif 187775.576 323670.916 1092.204 0.1780 -0.0928 180.0355
404_0001_00092720.tif 187775.867 323670.912 1092.061 -0.1690 45.0391 0.2398
- Exactly one
*_uitwendig_geleverde_beelden.txt, whose every row is<photo>.tif E N H omega phi kappa: the photo's file name, the projection centre and the three angles in degrees. One row per photo, no duplicates. - Every row in the orientation file has its frame. A row without a photo means the upload is incomplete.
- The heads must make up one CityMapper: one looking straight down and one each looking forward, backward, left and right, read from the orientations themselves (the view direction against each flight line's heading). At least 99% of a head's photos must agree on its direction, and each head's frames must be in its folder (nadir or oblique).
- The angles must describe the delivered pixels in the agreed convention: photo +x along the flight direction for the nadir head, toward the near edge of the footprint for the forward head and toward the far edge for the backward, left and right heads, within 30° on at least 95% of each head's photos. A kappa turned by 90° or 180° fails here.
- Photos whose own view direction is not their head's: up to 1% of a head's photos may disagree without failing the delivery, and those are listed here, since they are stored with their head's direction and lens. (a warning, not an error)
- Every projection centre must lie within 10 km of its own footprint (the same coordinate reference system) and between 100 and 5000 m height.
- Footprints computed from the orientation file and the camera are compared with the delivered footprint polygons. Widespread disagreement means the orientations may not describe the delivered photos — worth a look before accepting. (a warning, not an error)
Footprints#
One shapefile in 05_Luchtfotografie/03_Footprints/ — .shp, .shx, .dbf
and .prj under one name — with one polygon per photo in the dataset's
coordinate reference system. The table needs these columns; any others
(Richting, Lijn, SerieNr, Type, …) are welcome and not read:
| Column | Content |
|---|---|
Foto | the photo's file name without .tif |
Datum | the capture date, day first: D/M/YYYY (zero padding optional) |
Tijd | the capture time H:MM:SS in UTC — the same time as the photo name's HHMMSS |
- Exactly one shapefile (
.shp,.shx,.dbf,.prj, one name), whose table hasFoto,DatumandTijdcolumns, with one polygon row per frame (Foto= the file name without.tif). - The shapefile's
.prjmust be the dataset's coordinate reference system. Nothing is reprojected. Datumis the capture date day first (D/M/YYYY) andTijdthe capture time (H:MM:SS) in UTC, equal to the photo name'sHHMMSSto the second. A table in local time fails here.Datumshould be the same for every photo of one exposure and for every photo of a flight line (two consecutive days for a line flown across midnight), and not in the future. (a warning, not an error)
Timestamps#
Every capture time is UTC: the HHMMSS in the photo name and Tijd in the
footprint table, which must agree to the second. Do not deliver the table in
local time (10:09:43 for a photo named …_00090943): it is sent back.
Coordinate reference system#
Nothing is reprojected. Projection centres are in the dataset's 3D CRS, footprints, ortho and LAZ in its 2D CRS (for a Dutch dataset typically RD New
- NAP and RD New). The
footprint
.prjis compared with the dataset's CRS. See Coordinates.
True ortho#
Optional. ECW or GeoTIFF files directly inside 07_Trueorthofotomozaiek/,
indexed as Ortho (generic) indexes Ortho/. A delivery
without them is fine.
Georeferencing#
- Each GeoTIFF's TIFF header and first IFD must parse (only the header is read; the pixel data is not downloaded). A corrupt or truncated TIFF fails the run, naming the file. ECW files are checked separately.
- Each GeoTIFF's full-resolution strips or tiles must all end inside the file (their offsets and byte counts are read from the header; the pixels are not downloaded). This catches a partial upload whose header survived, as it does when the header sits at the start of the file (a Cloud Optimized GeoTIFF, for one). Tiles left out on purpose, as GDAL's sparse files do, are fine.
- Each GeoTIFF must carry a ModelPixelScale/Tiepoint (or ModelTransformation). A file with none is not indexed: a pixel-space rectangle stamped with the dataset CRS would place it at the CRS origin. World files (
.tfw) are not read. - Each ECW file's header must parse (magic, version, dimensions, georeference). A truncated or corrupt header fails the run, naming the file.
- Each raster's CRS (GeoTIFF GeoKeys, or the ECW header) must equal the dataset's 2D CRS. Nothing is reprojected. A mismatch, or a file with no recognised CRS, fails the run.
ECW#
ECW files are checked by their own header, and their coordinate reference system must be the dataset's.
Point cloud#
Optional. LAZ (or LAS) tiles directly inside 08_Laserdata/05_LAZ_Tiles/,
indexed and merged into one point cloud as for
Point cloud (generic); subfolders are not read. A
delivery without them is photos-only.
- The LAS public header of each point cloud file must parse (it is read from the first 64 KiB). A corrupt or truncated header fails the run, naming the file.
- Point-data record formats 0 and 2 carry no GPS time, so the merged point cloud gets no temporal index and cannot be filtered by capture time. (a warning, not an error)
- The point records must actually be there: a header can parse while the data behind it is truncated (a half-finished upload or copy). Checked for uncompressed LAS, where the declared point count and record length give an exact expected size; LAZ stores points in variable-size chunks, so the same arithmetic does not apply.
- Where a file describes extra per-point fields (the LAS 1.4 Extra Bytes record), every minimum and maximum a field descriptor flags as filled in must be a real statistic: a value the field's data type can hold, not NaN or infinity, and a minimum no larger than the maximum. Unset placeholders such as the largest 64-bit integer on a
u16field, or ±DBL_MAX on anf32, fail the delivery. Write the actual minimum and maximum, or clear the descriptor's min/max flags (options bits 1 and 2) when your software does not compute them. The record must also be a whole number of 192-byte descriptors.
What you get back#
- Indexed nadir and oblique photos per head, with their footprints, orientations, camera and capture times.
- A tilepack per photo, and a deep-zoom SZI per photo for tenants on Omnibase.
- Indexed true-ortho rasters, when delivered.
- Indexed LAZ tiles plus one merged COPC, when delivered.
Common failures#
| Symptom | Cause |
|---|---|
| The frame convention fails on every oblique head | The BINGO orientations (…_xas_in_vliegrichting.txt) were delivered instead of …_uitwendig_geleverde_beelden.txt |
| The frame convention fails on every head | The GNSS/IMU orientations were delivered instead of …_uitwendig_geleverde_beelden.txt |
Tijd does not match the photo names | The footprint table is in local time; deliver UTC |
The .prj is not the dataset's CRS | Footprints exported in lon/lat, or without a .prj |
| Orientation rows without a photo | An upload that stopped before all frames were in |
| A frame's pixel data runs past the end of the file | A partial upload of that frame; upload it again |
| A head is reported in the wrong folder | Nadir frames among the obliques, or the other way round |