Skip to content

Key images are resampled with FilterType::Nearest, discarding their antialiasing #61

Description

@constrictor

convert_image_with_format resamples every key image to the device's key size with nearest-neighbour:

https://github.com/OpenActionAPI/rust-elgato-streamdeck/blob/main/src/images.rs#L29

let image = image.resize_exact(ws as u32, hs as u32, FilterType::Nearest);

This discards the antialiasing of whatever the caller drew. On a Stream Deck + the ratio is 144 → 120, i.e. 6:5, so it drops every sixth row and column and point-samples soft edges rather than averaging them. The result on the panel is stair-stepped diagonals, strokes whose width visibly alternates along their length, and small text that turns to mush.

I ran into this writing an OpenDeck plugin that draws its key faces as SVG. Rendering the same source image through the pipeline twice — once with Nearest and once with Lanczos3, everything else identical, including both JPEG passes — the Nearest output matches what my hardware shows, and the Lanczos3 output is clean. Nothing about the artwork changed between the two.

Key images are at most 200×200, so a proper filter is not worth optimising away here:

-    let image = image.resize_exact(ws as u32, hs as u32, FilterType::Nearest);
+    // Nearest-neighbour discards the antialiasing on every key image. At the
+    // Stream Deck +'s 6:5 ratio (144 -> 120) it drops every sixth row and column
+    // and point-samples soft edges into stair-steps.
+    let image = if image.width() == ws as u32 && image.height() == hs as u32 {
+        image
+    } else {
+        image.resize_exact(ws as u32, hs as u32, FilterType::Lanczos3)
+    };

FilterType::Triangle would also be a large improvement if Lanczos3 is considered too heavy. The equality guard keeps the call free for callers that already hand over a correctly-sized image, which is the case worth optimising for.

Happy to open a PR if you'd like it in that shape.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions