adobe / adobe/trustmark

Rust decoder loses watermarks: decode-path resize uses non-antialiased ResizeAlg::Interpolation

Open
#37 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
141
Forks
34
PR merge metrics
No merged PRs in 30d

Description

Hi, I found that the TrustMark Python library was detecting watermarks that the Rust library was not, so I dug a bit deeper. My fix on my end is pinning the Rust library back to an earlier commit.

Worth noting the failure is silent: ECC returns 61 bits but flags them not-detected, so the CLI prints Corrupt or missing watermark and exits 0 — indistinguishable from an unwatermarked image.

**Root cause:** rust/src/image_processing.rs:69-73. fast_image_resize distinguishes ResizeAlg::Convolution (scaled support, antialiased) from ResizeAlg::Interpolation (documented as "like Convolution but with fixed kernel size" / "similar to OpenCV except INTER_AREA") a fixed 2x2 kernel means no antialiasing however large the ratio. The decoder uses the latter; PIL's Image.BILINEAR on the Python side is antialiased. Decoding a multi-megapixel image at 256x256 is a 4-7x downscale, so this drops most of the pixels. The same TryFrom conversion is used by encode (lib.rs:130, :141), so the residual is computed from an aliased downscale too, decode is where I looked.

**Regression:** 3b3aabe ("perf: switch from image-rs to fast_image_resize…") replaced .resize_exact(size, size, FilterType::Triangle), which is antialiased in image, so the change reads as unintended — a like-for-like swap of "bilinear" for "bilinear". Parent bff6dcdd (2025-04-15) uses the antialiased path. Only five commits have ever touched the file; 9234078 ("fix: integer truncation bug") is in remove_boundary_artifact, off the decode path.

Repro, without patching anything: take an image the binary reports as undetected and hand it the same content pre-resized to exactly 256x256 with an antialiased filter, so the internal resize becomes an identity op. The unmodified binary then detects it, while the full-size original still doesn't — same binary, same models, same pixels, only the resize does or doesn't do work. I couldn't build a patched CLI in my environment to confirm the fix directly.

Suggested fix: ResizeAlg::Convolution(FilterType::Bilinear) still SIMD-accelerated, so most of 3b3aabe's win is retained.

Contributor guide

Open the contributing guide

Research direction

Start with rust/src/image_processing.rs:69-73 and inspect the TryFrom conversion referenced in lib.rs:130 and :141. Reproduce the issue by comparing a full-size image with the same content pre-resized to 256x256 using an antialiased filter, then verify that the decoder detects the watermark after the resize path is corrected and add a regression check if the project’s existing test structure supports it.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
computer-vision
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
75/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.