fix: resample key images with a real filter instead of nearest-neighbour - #62
Open
constrictor wants to merge 2 commits into
Open
fix: resample key images with a real filter instead of nearest-neighbour#62constrictor wants to merge 2 commits into
constrictor wants to merge 2 commits into
Conversation
convert_image_with_format scaled every key image to the device's key size with FilterType::Nearest, which discards the antialiasing of whatever the caller drew. On a Stream Deck + the ratio is 144 -> 120, so it dropped every sixth row and column and point-sampled soft edges rather than averaging them: stair-stepped diagonals, strokes whose width alternates along their length, and unreadable small text. Use Lanczos3, and skip the resample altogether when the image already matches the key size. Key images are at most 200x200, so the filter costs microseconds; the common case of a correctly-sized image now costs nothing at all, where before it paid for a full resample.
Member
|
I've commented on the issue. In the future, please only open a PR and not an issue, since the discussion can be tracked in a single place without increasing maintenance overhead. |
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.
Fixes #61.
convert_image_with_formatresampled every key image withFilterType::Nearest, which discards the antialiasing of whatever the caller drew. On a Stream Deck + that is 144 → 120, a 6:5 ratio, so it dropped every sixth row and column and point-sampled soft edges instead of averaging them — stair-stepped diagonals, strokes whose width visibly alternates along their length, and small text reduced to mush.This switches to
Lanczos3and adds an early-out when the image already matches the key size.The early-out is worth having on its own:
resize_exactruns the sampler unconditionally, so a caller that already hands over a correctly-sized image was paying for a full resample to get its own pixels back. That case is now free, which also gives callers a way to opt out of the filter entirely by pre-scaling.Trianglewould also be a large improvement ifLanczos3seems too heavy — happy to switch.Correction to an earlier version of this description, prompted by @Terrorwolf01 in #61: I originally justified the filter choice with "key images are at most 200×200". That number was not derived from anything. The real ceiling in
Kind::key_image_format()is 120×120, and it is the wrong bound regardless — this function is public and also takeslcd_image_format(), which reaches 800×100 and 100×1200. Cost is really driven by the source size, which is unbounded through the public API. Measured onimage0.25.10, release build:For a host rendering at roughly key size, Lanczos3 costs ~190 µs more per update than Nearest. The outlier is a large source image: 1024×1024 → 120×120 is 24× Nearest. On that evidence
Triangleis arguably the better default — ~3.3× cheaper there, and visually near-identical to Lanczos3 at the ratios that motivated this. Say the word and I'll switch it.Testing
I found this writing an OpenDeck plugin that draws its key faces as SVG, against a Stream Deck +. Rendering the same source through the full pipeline twice — including both JPEG passes, changing only the filter — the
Nearestoutput matches what the panel shows and theLanczos3output is clean, with no change to the artwork.I could not run
cargo checkon the crate itself here:hidapineedslibudevheaders that aren't installed on this machine. I type-checked the changed expression againstimage0.25.10 with the same importsimages.rshas, andrustfmt --checkonsrc/images.rsis clean. Worth a second pair of eyes on the build.