Images images

Image steganography — hide and recover secret messages in the least-significant bits of image pixels
Pixelbadger Toolkit — pbtk images← all topics

Overview

The steganography command lets you hide a text message inside an image file and later recover it. The message is stored in the least-significant bits of the R, G, and B channels of each pixel in scan order, so the visual change to the image is imperceptible to the human eye.

Method
LSB Steganography

One bit stored per colour channel. Three bits per pixel.

Encoding
UTF-8

Message is converted to UTF-8 bytes before bit-packing.

Terminator
<<END>>

Appended to the message so decoding knows where to stop.

Library
ImageSharp

SixLabors.ImageSharp handles pixel-level access for all supported formats.

How It Works

Encoding

The message is appended with the sentinel string <<END>>, converted to UTF-8 bytes, then expanded to a bit array. The bits are written into the least-significant bit of each colour channel (R, G, B) in left-to-right, top-to-bottom pixel order.

pixel.R = (pixel.R & 0xFE) | messageBits[i] pixel.G = (pixel.G & 0xFE) | messageBits[i+1] pixel.B = (pixel.B & 0xFE) | messageBits[i+2]

Decoding

The LSBs of R, G, and B are read from each pixel in the same scan order, accumulated into bytes, and converted back to a UTF-8 string until the <<END>> sentinel is found. Everything before the sentinel is the recovered message.

flowchart TD MSG["Plaintext message"] --> UTF8["UTF-8 encode + append <<END>>"] UTF8 --> BITS["Expand to bit array\n8 bits per byte"] BITS --> PACK["Write one bit into LSB\nof each R, G, B channel\nper pixel (scan order)"] IMG["Input image"] --> PACK PACK --> OUT["Output image\n(visually identical)"]
The message capacity of an image is floor(width × height × 3 / 8) bytes (minus the 7-byte terminator). A 100 × 100 image holds roughly 3,750 bytes of message text.
Output format matters: save the encoded image as a lossless format (PNG, BMP). Saving as JPEG re-compresses the pixel data and will corrupt the hidden bits, making the message unrecoverable.

Encode

Hide a message inside an image. The output file is a new image with the message bits written into the least-significant channel bits.

$ pbtk images steganography --mode encode --image cover.png --message "Secret payload" --output stego.png
OptionRequiredDescription
--modeYesMust be encode
--imageYesPath to the input cover image
--messageYes (encode)The plaintext message to hide
--outputYes (encode)Path to write the output stego image

Decode

Recover a previously hidden message from a stego image. The image must have been produced by the encode mode of this same command.

$ pbtk images steganography --mode decode --image stego.png
OptionRequiredDescription
--modeYesMust be decode
--imageYesPath to the stego image containing a hidden message

Command Reference

Command Required options Optional options Output
images steganography --mode encode --image --message --output Stego image written to --output
images steganography --mode decode --image Recovered message printed to stdout

Constraints and Limits

ConstraintValueReason
Bits per pixel 3 (one per R/G/B channel) LSB of alpha channel is left untouched to avoid transparency artefacts
Message terminator <<END>> (7 bytes) Required for the decoder to know when the message ends
Output format Lossless (PNG, BMP recommended) Lossy compression (JPEG) destroys the hidden bits
Message encoding UTF-8 Full Unicode supported; multi-byte characters consume more capacity