Add invoke-readwatermark CLI command to decode invisible watermarks#73
Add invoke-readwatermark CLI command to decode invisible watermarks#73
invoke-readwatermark CLI command to decode invisible watermarks#73Conversation
* Initial plan * Fix canvas text tool breaking hotkeys when canvas manager is null Co-authored-by: lstein <111189+lstein@users.noreply.github.com> * chore(frontend): fix eslint issue --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: lstein <111189+lstein@users.noreply.github.com> Co-authored-by: Lincoln Stein <lincoln.stein@gmail.com>
Remove 5th parameter for function that expects 4 parameters Co-authored-by: Lincoln Stein <lincoln.stein@gmail.com>
…ke-ai#8889) Co-authored-by: Lincoln Stein <lincoln.stein@gmail.com>
Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
invoke-readwatermark CLI command to decode invisible watermarks
|
@copilot The watermarks installed by
|
…keAI watermark text Co-authored-by: lstein <111189+lstein@users.noreply.github.com>
The garbled output was caused by a wrong default The fact that Fixed in commit |
|
@copilot Can you confirm that the watermark encoding is working properly? The watermark encodes and decodes properly on some images, but not others, and it seems to depend on which model and VAE is selected. |
The encoding code is correct. Testing confirms The model/VAE sensitivity you're seeing is a property of the DWT-DCT algorithm itself, not a code defect:
In short: some model+VAE combinations produce images where the existing frequency content happens to interfere with the watermark signal. This is a known limitation of the algorithm, not a bug in our implementation. If reliable watermark recovery is required regardless of content, the |
Summary
Adds a
invoke-readwatermarkCLI command that reads invisible watermarks from Invoke-generated images and prints them to stdout.Changes:
InvisibleWatermark.decode_watermark()— new classmethod on the existing watermark wrapper; usesWatermarkDecoder(already vendored, previously unused) to extract embedded watermark bytes, strips null padding, and returns a UTF-8 string. CatchesRuntimeError/ValueError/NameErrorfrom the vendor lib and logs failures at DEBUG level. Defaultwatermark_lengthis8bytes, matching the 8-character default"InvokeAI"watermark text.invokeai/app/util/read_watermark.py— new CLI entrypoint module; iterates provided image paths, decodes each watermark, and printsfilename: watermark_text. File-open errors go to stderr; processing continues on failure.pyproject.toml— registersinvoke-readwatermark = "invokeai.app.util.read_watermark:read_watermark"under[project.scripts].Usage:
Note on
--length: The--lengthvalue must match the byte length of the watermark text used when the image was generated. The default of8matches InvokeAI's default watermark text"InvokeAI". If a custom watermark text was used, pass its byte length via--length.Note on reliability: The DWT-DCT watermarking algorithm encodes bits into frequency-domain coefficients of the image. Decoding reliability depends on the image's frequency content — images whose native frequency structure coincidentally falls near the algorithm's decision boundary may produce incorrect bits for those positions. This is an inherent property of the algorithm and is not a code defect. The watermark is always applied to the final output image after VAE decoding, so model and VAE selection do not influence the watermarking step itself.
Related Issues / Discussions
QA Instructions
"InvokeAI").invoke-readwatermark <path/to/image.png>(no flags needed for the default watermark).<path>: InvokeAI."hello", 5 bytes), confirminvoke-readwatermark --length 5 image.pngdecodes correctly.Merge Plan
Checklist
What's Newcopy (if doing a release after this PR)Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.