Skip to content

Georef output contract: alpha band for grayscale, srcnodata as mask fallback (#56) - #79

Merged
NewGraphEnvironment merged 5 commits into
mainfrom
56-georef-output-contract-a-real-alpha-band
Sep 29, 2026
Merged

NewGraphEnvironment merged 5 commits into
mainfrom
56-georef-output-contract-a-real-alpha-band

Conversation

@NewGraphEnvironment

Copy link
Copy Markdown
Owner

Summary

  • Breaking: every fly_georef() output now gets -dstalpha. Grayscale goes from 1 band with NoData = 0 to 2 bands, Gray + Alpha, no NoData. RGB stays 4.
  • mask = "border" together with srcnodata is now accepted. srcnodata becomes the fallback for frames whose mask declined. fly_georef_warp_opts() was always an else if, so the old refusal guarded a pair GDAL never received.
  • georef_one() now warns when a mask declines and no fallback was given, because that frame's collar reaches the output as image data.

Related Issues

What was measured

Measured on the 182 grayscale calibration thumbnails, on sf's GDAL 3.8.5. Producer: data-raw/mask_measure-interior_zeros.R.

old -dstnodata 0 path frames where true black was rewritten as 1 max share of a frame
axis-aligned warp 161 of 182 3.6%
30° warp 41 of 182 0.26%

Test plan

  • devtools::test(): 2585 pass, 0 fail, 0 warn (macOS)
  • Mutation checks. Dropping -srcnodata turns the fallback test red. Restoring -dstnodata 0 next to the alpha band turns the collision test red on its values, not just on band count.
  • pkgdown::check_pkgdown() clean
  • Three-platform CI. The Windows pin in test-fly_georef_mask.R is removed, and the test now asserts 2 grayscale bands on every runner. Windows is the real test of Masking adds a band on Windows for grayscale, so "output band counts do not change" is platform-conditional #68.
  • Downstream COG round trip run against this branch. It failed as the table above describes, and that is filed as stac_airphoto_bc#36.

Notes

  • Review: /code-check ran 3 rounds on the code commit and 3 on the docs and measurement commit. Every finding in both loops was prose or measurement scope, and all were fixed. The docs loop ended by enumerating 30 claims. Review under-counted twice: first the source-side count, then a single bearing. The archive README keeps both wrong turns.
  • An issue was also filed in a private sibling that pins these warp options.
  • Version bump left for /gh-pr-merge. The change is breaking and pre-1.0, so it should be a minor bump.

🤖 Generated with Claude Code

https://claude.ai/code/session_0115csb82i78r86GWFzwPzis

NewGraphEnvironment and others added 5 commits September 28, 2026 21:39
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0115csb82i78r86GWFzwPzis
161 of 182 calibration grayscale frames hold true black the old -dstnodata 0
output deleted (median 47 px, max 3.5% on roll bcb94081). The mask declined on
0 of 264 and 0 of 10,105 thumbnails, so the srcnodata fallback only reaches
paths thumbnails cannot exercise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0115csb82i78r86GWFzwPzis
…ined mask (#56)

Grayscale now warps with -dstalpha like RGB: 2 bands, Gray + Alpha, no
NoData, replacing 1 band with -dstnodata 0, which wrote genuine black inside
the frame as nodata (161 of 182 calibration grayscale frames) and let the
band count differ by platform (fly#68).

fly_georef() no longer refuses mask = "border" with srcnodata. The warp
options were always either/or, so srcnodata is now the documented fallback
for frames whose mask declined (fly#69). georef_one() warns when a mask
declines with no fallback, since that collar reaches the output as data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0115csb82i78r86GWFzwPzis
… the source (#56)

The old grayscale -dstnodata 0 path rewrote true black as 1 rather than
deleting it: on the 182 calibration grayscale frames, 161 warped
axis-aligned (up to 3.6%) and 41 at a 30-degree bearing (up to 0.26%),
none deleted. The 0->1 shift #68 saw on Windows happens silently on sf's
GDAL 3.8.5 too. The measurement script gains that output-side pass at both
bearings; border-masking.md, CLAUDE.md and NEWS state the new contract
(2 bands gray, 4 RGB, alpha only) and srcnodata as a fallback for a
declined mask, each scoped to what was measured. The threshold calibration
script now calls fly_georef_warp_opts() rather than copying the old vector.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0115csb82i78r86GWFzwPzis
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0115csb82i78r86GWFzwPzis
@NewGraphEnvironment
NewGraphEnvironment merged commit 7047b63 into main Sep 29, 2026
4 checks passed
@NewGraphEnvironment
NewGraphEnvironment deleted the 56-georef-output-contract-a-real-alpha-band branch September 29, 2026 05:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Georef output contract: a real alpha band for grayscale, and a supported mask-or-nodata fallback

1 participant