Skip to content

Instantly share code, notes, and snippets.

@insaneyilin
Created June 16, 2025 18:33
Show Gist options
  • Save insaneyilin/90388c32c8e93f5b93bcef3d76e24291 to your computer and use it in GitHub Desktop.
Save insaneyilin/90388c32c8e93f5b93bcef3d76e24291 to your computer and use it in GitHub Desktop.
image steganography
import argparse
from PIL import Image
def embed_message(image_path, message, output_path):
org_img = Image.open(image_path)
org_pixelMap = org_img.load()
enc_img = Image.new(org_img.mode, org_img.size)
enc_pixelsMap = enc_img.load()
binary_msg = ''.join(format(ord(char), '08b') for char in message)
msg_len = len(binary_msg)
msg_index = 0
for row in range(org_img.size[0]):
for col in range(org_img.size[1]):
r, g, b = org_pixelMap[row, col]
if row == 0 and col == 0:
msg_len_bin = format(msg_len, '024b')
r = int(msg_len_bin[:8], 2)
g = int(msg_len_bin[8:16], 2)
b = int(msg_len_bin[16:], 2)
enc_pixelsMap[row, col] = (r, g, b)
elif msg_index < msg_len:
r_bin = format(r, '08b')
g_bin = format(g, '08b')
b_bin = format(b, '08b')
new_r_bin = r_bin[:-1] + binary_msg[msg_index]
new_r = int(new_r_bin, 2)
msg_index += 1
if msg_index < msg_len:
new_g_bin = g_bin[:-1] + binary_msg[msg_index]
new_g = int(new_g_bin, 2)
msg_index += 1
else:
new_g = g
if msg_index < msg_len:
new_b_bin = b_bin[:-1] + binary_msg[msg_index]
new_b = int(new_b_bin, 2)
msg_index += 1
else:
new_b = b
enc_pixelsMap[row, col] = (new_r, new_g, new_b)
else:
enc_pixelsMap[row, col] = (r, g, b)
org_img.close()
enc_img.save(output_path)
enc_img.close()
print(f"Message embedded successfully. Encrypted image saved as {output_path}")
def extract_message(image_path):
enc_img = Image.open(image_path)
enc_pixelMap = enc_img.load()
binary_msg = ""
msg_len = 0
for row in range(enc_img.size[0]):
for col in range(enc_img.size[1]):
r, g, b = enc_pixelMap[row, col]
if row == 0 and col == 0:
msg_len = (r << 16) | (g << 8) | b
elif msg_len > 0:
r_bin = format(r, '08b')
g_bin = format(g, '08b')
b_bin = format(b, '08b')
binary_msg += r_bin[-1]
msg_len -= 1
if msg_len > 0:
binary_msg += g_bin[-1]
msg_len -= 1
if msg_len > 0:
binary_msg += b_bin[-1]
msg_len -= 1
message = ''.join(chr(int(binary_msg[i:i+8], 2)) for i in range(0, len(binary_msg), 8))
enc_img.close()
return message
def main():
parser = argparse.ArgumentParser(description="Steganography tool to hide and extract messages in images.")
subparsers = parser.add_subparsers(dest="command", required=True, help="Sub-command to run.")
# Subparser for the "hide" command
hide_parser = subparsers.add_parser("hide", help="Hide a message in an image.")
hide_parser.add_argument("-p", "--image", required=True, help="Path to the image file.")
hide_parser.add_argument("-f", "--file", required=True, help="Path to the file containing the secret message.")
hide_parser.add_argument("-o", "--output", required=True, help="Path to the output image file.")
# Subparser for the "extract" command
extract_parser = subparsers.add_parser("extract", help="Extract a message from an image.")
extract_parser.add_argument("-u", "--image", required=True, help="Path to the image file containing the hidden message.")
extract_parser.add_argument("-o", "--output", required=True, help="Path to the output file for the extracted message.")
args = parser.parse_args()
if args.command == "hide":
with open(args.file, "r") as f:
message = f.read()
embed_message(args.image, message, args.output)
elif args.command == "extract":
hidden_message = extract_message(args.image)
with open(args.output, "w") as f:
f.write(hidden_message)
print(f"Message extracted successfully. Saved to {args.output}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment