Skip to content

fix(geotiff): read projection origin from all equivalent GeoKeys - #671

Merged
kylebarron merged 1 commit into
mainfrom
kyle/fix-oblique-stereographic-crs
Sep 25, 2026
Merged

kylebarron merged 1 commit into
mainfrom
kyle/fix-oblique-stereographic-crs

Conversation

@kylebarron

@kylebarron kylebarron commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

the GeoKey parsing to PROJJSON is already vibe coded, so we continue to let claude vibe code it with more and more test files

This should hopefully fix source-cooperative/cog-viewer#40

Validated in the dev app that it's now rendering in the right place:

image image

Note

Written by Claude (Claude Code) on behalf of @kylebarron, not by @kylebarron.

Fixes source-cooperative/cog-viewer#40

Bug

O2308000_7586000_cog.tif uses New Brunswick Stereographic (equivalent to EPSG:2953), stored as a user-defined CRS with ProjCoordTransGeoKey = CT_ObliqueStereographic. GDAL wrote the origin into ProjNatOriginLatGeoKey / ProjNatOriginLongGeoKey / ProjScaleAtNatOriginGeoKey, but crsFromGeoKeys read ProjCenter* / ProjScaleAtCenter for this method. Those keys were missing, so the origin fell back to (0, 0) with scale 1, and the image rendered near Null Island.

Fix

Each projection method read its origin, scale factor and false easting/northing from a single hand-picked key. libgeotiff instead takes each one from the first of several equivalent keys that is present:

Parameter Keys, in order
Origin latitude ProjNatOriginLat → ProjFalseOriginLat → ProjCenterLat
Origin longitude ProjNatOriginLong → ProjFalseOriginLong → ProjCenterLong
Scale factor ProjScaleAtNatOrigin → ProjScaleAtCenter
False easting ProjFalseEasting → ProjCenterEasting → ProjFalseOriginEasting
False northing ProjFalseNorthing → ProjCenterNorthing → ProjFalseOriginNorthing

_buildConversion now does the same for every method. When the key a method used to read is present, it still gets the same value. Albers and LCC 2SP keep checking their false-origin keys first.

This also fixes Stereographic: GDAL writes its scale factor to ProjScaleAtNatOrigin, which we didn't read, so it was always 1.

Tests

Not fixed here

  • Hotine Oblique Mercator: GDAL treats CT_ObliqueMercator (3) as variant A, but we emit variant B. We also take the "Angle from Rectified to Skew Grid" from ProjAzimuthAngleGeoKey rather than ProjRectifiedGridAngleGeoKey.
  • When the datum is an EPSG code, we don't pass on the ellipsoid given in the file's GeoKeys, so proj4 uses WGS84's instead.

🤖 Written by Claude Code

Each projection method read its origin, scale factor and false
easting/northing from a single hand-picked GeoKey. Writers disagree on
which of the equivalent keys they use: GDAL writes ProjNatOrigin* for
Oblique Stereographic, but we read ProjCenter*, so a user-defined New
Brunswick Stereographic COG got an origin of (0, 0) and rendered near
Null Island (source-cooperative/cog-viewer#40).

Resolve each parameter the way libgeotiff's GTIFFetchProjParms does:
from the first of its equivalent keys that is present. This also fixes
the Stereographic scale factor, which GDAL writes to
ProjScaleAtNatOrigin. Albers and LCC 2SP keep checking their
false-origin keys first.

Bumps geotiff-test-data for the O2308000_7586000_cog.tif fixture.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the fix label Sep 25, 2026
@kylebarron
kylebarron merged commit 11da6e7 into main Sep 25, 2026
4 checks passed
@kylebarron
kylebarron deleted the kyle/fix-oblique-stereographic-crs branch September 25, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

COG Not Shown in Proper Location

1 participant