Repository navigation
feat(resample): resample_oriented, the upright result without the upright copy - #2
Merged
Merged
Conversation
…ight copy Adds Orientation (the eight EXIF transforms), orient (the per-pixel definition), and resample_oriented, which returns resample(&orient(..), ..) bit for bit without building the upright frame. Equality is by construction: every accumulator sums the same samples, with the same weights, taps ascending. Only the loops around the accumulators change. For the four axis-swapping orientations an upright row is a stored column, so every upright row accumulates at once and each tap streams one stored row. Measured on a 6240x4160 RGB frame, three box tiers, release, medians of 7: blocks of 64 upright rows took 174/240 ms at EXIF 6/8, improving with every doubling until one block spanned the frame at 46-62 ms. Resampling an already-upright frame takes 59 ms; a tiled copy then resample, 129/149 ms. Tests: resample_oriented against orient-then-resample, bitwise, over every orientation, all three filters, channel counts 1/3/4 and eight frame sizes down to 1x1. It fails on a wrong horizontal flag, a wrong vertical flag, and an unreversed mirrored walk. orient is pinned by hand on a 3x2 frame. fmt, clippy -D warnings (1.98), MSRV 1.75 check, conformance all pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A camera stores most portraits sideways, so a photo pipeline orients a full frame before every resample: a copy of the whole frame (311 MB of f32 for a 26 MP RGB photo), and for the four orientations that swap axes, a copy that reads its source down a column.
This adds:
Orientation: the eight EXIF transforms, withfrom_exif,swaps_axes,upright_sizeandsource_of.orient: the per-pixel permutation, public, and the definition the tests hold the fast path to.resample_oriented: returnsresample(&orient(..), ..)bit for bit without building the upright frame.Why it's exact
Every accumulator sums the same samples, with the same weights, taps ascending. Only the loops around the accumulators change. For the axis-swapping orientations an upright row is a stored column, so every upright row accumulates at once and each tap streams one whole stored row. The vertical pass is now one shared function, so
resampleandresample_orientedcan't drift.Measured
6240x4160 RGB, three box tiers (600/400/200 px short edge), release, medians of 7:
resample_orientedresampleIt started blocked: 64 upright rows at a time took 174/240 ms. Every doubling helped until one block spanned the frame, so the block was deleted. Streaming whole rows matches or beats resampling an already-upright frame.
Tests
resample_orientedagainst orient-then-resample,to_bits()equality, over all 8 orientations, all 3 filters, channel counts 1/3/4 (fixed and dynamic paths) and 8 frame sizes down to 1x1. Mutation controls: it fails on a wrong horizontal flag, a wrong vertical flag, and an unreversed mirrored walk.orientpinned by hand on a 3x2 frame.cargo fmt --check, clippy-D warningson the pinned 1.98, MSRV 1.75check, conformance: all pass.First consumer
aadhar.sh's zenc pins this branch commit (
871487e) in oddharsh/site#891. Please merge with a merge commit, not a squash, as #1 was, so that sha stays reachable frommain.The wasm/JS surface is unchanged;
resample_orientedisn't exported there yet.