Skip to content

Sidecar georeferencing extraction ignores sidecar's own geokeys #2315

@brendancol

Description

@brendancol

Description

When a .tif.ovr sidecar is loaded, local eager reads correctly swap the pixel buffer and TIFF header over to the sidecar (xrspatial/geotiff/_reader.py ~line 223). The georef extraction call right below it still passes the base file's data and header.byte_order (line 234). _read_geo_info in xrspatial/geotiff/__init__.py (~line 291) has the same bug.

This is harmless under the usual GDAL convention, where the sidecar has no geokeys and georef lives on the base file. It is not safe in general: if the sidecar IFD does carry its own GeoKeyDirectory or model tags, those tags get parsed against the wrong byte buffer and the returned geo_info is silently wrong.

Expected behavior

If the selected IFD lives in the sidecar and that IFD declares its own georef payload, parse the georef against the sidecar's bytes and byte order. If the sidecar IFD has no georef payload, fall back to the existing behavior and inherit from the base file's level-0 IFD.

Actual behavior

Georef tags on a sidecar IFD are parsed as if they lived in the base file. ModelPixelScale, ModelTiepoint, and ModelTransformation values come out of the wrong offsets, and GeoKeyDirectory entries that point into GeoDoubleParamsTag or GeoAsciiParamsTag dereference into the base file instead of the sidecar.

Fix shape

  • Detect whether a sidecar IFD carries its own georef payload (any of tags 33550, 33922, 34264, 34735).
  • When it does, run extract_geo_info_with_overview_inheritance against the sidecar's data and header.byte_order for that IFD.
  • When it does not, keep today's behavior.
  • Apply the same rule at both call sites so the two paths agree.
  • Add a regression test using a synthetic base + sidecar pair where the sidecar declares its own ModelPixelScale, ModelTiepoint, and GeoKeyDirectory differing from the base.

Files

  • xrspatial/geotiff/_reader.py:234 (eager read path)
  • xrspatial/geotiff/__init__.py:291 (metadata-only path used by the dask backend)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginput-validationInput validation and error messages

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions