Skip to content

Fix crop=True dropping boundary pixels when all_touched=True (#1197)#1200

Merged
brendancol merged 3 commits into
masterfrom
issue-1197
Apr 14, 2026
Merged

Fix crop=True dropping boundary pixels when all_touched=True (#1197)#1200
brendancol merged 3 commits into
masterfrom
issue-1197

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

  • _crop_to_bbox was comparing pixel center coordinates against the geometry bounding box without accounting for pixel cell extent. When all_touched=True, pixels whose centers fell just outside the bbox were silently excluded even though their cells overlapped the polygon.
  • Now _crop_to_bbox receives the all_touched flag and pads the bbox comparison by half a pixel on each side when set, so rasterize sees every pixel whose cell intersects the geometry.
  • Also cleaned up dead ascending/descending branches that computed the same mask regardless of coordinate order.

Closes #1197

Test plan

  • New test_all_touched_crop_matches_nocrop in numpy backend confirms crop=True, all_touched=True produces identical pixel counts and values as crop=False, all_touched=True for a polygon whose edges land between pixel centers
  • Same test added for dask+numpy backend
  • All 22 tests pass (20 existing + 2 new), including CuPy and dask+CuPy backend parity tests

Two security fixes for the geotiff subpackage:

1. Add a configurable max_pixels guard to read_to_array() and all
   internal read functions (_read_strips, _read_tiles, _read_cog_http).
   A crafted TIFF with fabricated header dimensions could previously
   trigger multi-TB allocations. The default limit is 1 billion pixels
   (~4 GB for float32 single-band), overridable via max_pixels kwarg.
   Fixes #1184.

2. Canonicalize VRT source filenames with os.path.realpath() after
   resolving relative paths. Previously, a VRT file with "../" in
   SourceFilename could read arbitrary files outside the VRT directory.
   Fixes #1185.
os.path.realpath() converts Unix-style paths to Windows paths on
Windows (e.g. /data/tile.tif becomes D:\data\tile.tif). Use
os.path.realpath() in the assertion so it matches the production
code's canonicalization on all platforms.
_crop_to_bbox compared pixel center coordinates against the geometry
bounding box without accounting for pixel cell extent. When
all_touched=True, pixels whose centers fell just outside the bbox were
excluded even though their cells overlapped the polygon.

Now _crop_to_bbox receives the all_touched flag and expands the bbox
comparison by half a pixel on each side when set, so rasterize gets to
see every pixel whose cell intersects the geometry.

Also removed dead ascending/descending branches that computed the same
mask regardless of coordinate order.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label Apr 14, 2026
@brendancol brendancol merged commit 5ef4237 into master Apr 14, 2026
11 checks passed
@brendancol brendancol deleted the issue-1197 branch May 5, 2026 03:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

clip_polygon crop=True drops boundary pixels when all_touched=True

1 participant