Open In App

Image based Steganography using Python

Last Updated : 04 Apr, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Steganography (Hiding Data Inside Images) is the technique of concealing secret information within an image, audio, or video file. The goal is to embed data in such a way that it remains undetectable to the naked eye.

The idea behind image-based Steganography is very simple. Images are made up of pixels, and each pixel consists of three color values: Red, Green, and Blue (RGB). We can modify these values slightly to encode hidden data without significantly altering the image’s appearance.

Encode Data into an Image:

1. Convert Data to Binary: Each character in the secret message is converted to its 8-bit binary representation using ASCII values.

2. Modify Pixel Values:

  • Pixels are processed three at a time (9 RGB values in total).
  • The first 8 values store binary data:
  • If the binary bit is 1: make the value odd.
  • If the binary bit is 0: make the value even.
  • The 9th value ensures the message continues—it’s even if there’s more data to encode.

For example : 
Message to hide: “Hii” (3 bytes – needs 9 pixel values).

  • H – ASCII 72 = Binary 01001000
  • i – ASCII 105 = Binary 01101001
  • i – ASCII 105 = Binary 01101001
  • Total binary data = 24 bits
  • Modify pixel values accordingly:

Original Pixels:

[(27, 64, 164), (248, 244, 194), (174, 246, 250),
(149, 95, 232), (188, 156, 169), (71, 167, 127),
(132, 173, 97), (113, 69, 206), (255, 29, 213),
(53, 153, 220), (246, 225, 229), (142, 82, 175)]

Take the first 3 pixels:

(27, 64, 164), (248, 244, 194), (174, 246, 250)

Convert ‘H’ (ASCII 72) to binary: 01001000

Modify pixel values:

0: Keep Even, 1: Make Odd

Original ValueBinary BitModified Value
27 (Odd)0 → Make Even26
64 (Even)1 → Make Odd63
164 (Even)0 → Keep Even164
248 (Even)0 → Keep Even248
244 (Even)1 → Make Odd243
194 (Even)0 → Keep Even194
174 (Even)0 → Keep Even174
246 (Even)0 → Keep Even246

Final Modified Image (After Encoding “Hii”):

[(26, 63, 164), (248, 243, 194), (174, 246, 250), (148, 95, 231),
(188, 155, 168), (70, 167, 126), (132, 173, 97), (112, 69, 206),
(254, 29, 213), (53, 153, 220), (246, 225, 229), (142, 82, 175)]

Decode the data:

To extract the hidden message:

1. Read the image three pixels at a time.

2. Extract the binary values using the same encoding rule:

  • Odd value – 1
  • Even value – 0

3. Stop when the last value is odd, indicating the message has ended.

4. Convert the extracted binary sequence back to text.
 


Below is the Implementation of the above idea: 

Python
from PIL import Image

def genData(data):
    """Converts input text into a list of 8-bit binary strings."""
    return [format(ord(i), '08b') for i in data]

def modPix(pix, data):
    """Modifies pixel values to encode the binary data."""
    datalist = genData(data)
    lendata = len(datalist)
    imdata = iter(pix)
    
    for i in range(lendata):
        pixels = [value for value in next(imdata)[:3] + next(imdata)[:3] + next(imdata)[:3]]
        
        # Modify pixel values based on binary data
        for j in range(8):
            if datalist[i][j] == '0' and pixels[j] % 2 != 0:
                pixels[j] -= 1
            elif datalist[i][j] == '1' and pixels[j] % 2 == 0:
                pixels[j] = pixels[j] - 1 if pixels[j] != 0 else pixels[j] + 1
        
        # Set termination flag (last pixel even means continue, odd means stop)
        if i == lendata - 1:
            pixels[-1] |= 1  # Make odd (stop flag)
        else:
            pixels[-1] &= ~1  # Make even (continue flag)
        
        yield tuple(pixels[:3])
        yield tuple(pixels[3:6])
        yield tuple(pixels[6:9])

def encode_enc(newimg, data):
    """Encodes the modified pixel data into the new image."""
    w = newimg.size[0]
    (x, y) = (0, 0)
    
    for pixel in modPix(newimg.getdata(), data):
        newimg.putpixel((x, y), pixel)
        x = 0 if x == w - 1 else x + 1
        y += 1 if x == 0 else 0

def encode():
    """Handles user input and calls encoding functions."""
    img = input("Enter image name (with extension): ")
    image = Image.open(img, 'r')
    data = input("Enter data to be encoded: ")
    
    if not data:
        raise ValueError("Data is empty")
    
    newimg = image.copy()
    encode_enc(newimg, data)
    new_img_name = input("Enter the name of new image (with extension): ")
    newimg.save(new_img_name, new_img_name.split(".")[-1].upper())

def decode():
    """Decodes hidden text from an image."""
    img = input("Enter image name (with extension): ")
    image = Image.open(img, 'r')
    imgdata = iter(image.getdata())
    data = ""
    
    while True:
        pixels = [value for value in next(imgdata)[:3] + next(imgdata)[:3] + next(imgdata)[:3]]
        binstr = ''.join(['1' if i % 2 else '0' for i in pixels[:8]])
        data += chr(int(binstr, 2))
        
        if pixels[-1] % 2 != 0:
            break
    
    return data

def main():
    """Main function for user interaction."""
    choice = input(":: Welcome to Steganography ::\n1. Encode\n2. Decode\n")
    if choice == '1':
        encode()
    elif choice == '2':
        print("Decoded Word: " + decode())
    else:
        print("Invalid choice, exiting.")

if __name__ == "__main__":
    main()

Output : 

Steganography

Terminal Snapshot

Steps to Encode and Decode a Message

Encoding Steps (Hiding the Message)

  1. Run the script.
  2. Select 1 (Encode) when prompted.
  3. Enter the image filename (e.g., steganography-input.png).
  4. Enter the message, for example: This is a secret message from GFG
  5. Provide the output image name (e.g., encoded_image.png).
  6. The modified image is saved with hidden text.

Decoding Steps (Retrieving the Message)

  1. Run the script.
  2. Select 2 (Decode) when prompted.
  3. Enter the encoded image filename (e.g., encoded_image.png).
  4. The hidden message is displayed: This is a secret message from GFG
  5. That’s it! Let me know if you need further clarification.


Next Article

Similar Reads