diff --git a/luke_04/images/input-pokemon_jakt.png b/luke_04/images/input-pokemon_jakt.png new file mode 100644 index 0000000..d3490d4 Binary files /dev/null and b/luke_04/images/input-pokemon_jakt.png differ diff --git a/luke_04/images/output-pokemon_jakt.png b/luke_04/images/output-pokemon_jakt.png new file mode 100644 index 0000000..9304531 Binary files /dev/null and b/luke_04/images/output-pokemon_jakt.png differ diff --git a/luke_04/steganography.py b/luke_04/steganography.py new file mode 100644 index 0000000..0f2ffae --- /dev/null +++ b/luke_04/steganography.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +import os +from PIL import Image +import numpy as np +import itertools + +input_image = os.path.join(os.path.dirname(__file__), 'images/input-pokemon_jakt.png') +output_image = os.path.join(os.path.dirname(__file__), 'images/output-pokemon_jakt.png') + +def main(): + LSB = 4 + image = Image.open(input_image) + pixels = np.array(image) + width, height, channels = pixels.shape + + for i,j,k in [(i,j,k) for i in range(width) for j in range(height) for k in range(channels)]: + value = int(f'{pixels[i][j][k]:b}'[-LSB:], 2) + pixels[i,j,k] = (255 // 2**LSB) * value + + image = Image.fromarray(pixels) + image.save(output_image) + return output_image + +if __name__ == '__main__': + main() + + + +''' +_____ +tests + + * compare the hash values of images + * compare all bits in every channel + calls = [hashCompare] +''' + +''' +___ +previous attempts + +for i, j, in itertools.product(width, height, channels): + encoded_value = int(f'{pixels[i][j][k]:b}'[-LSB:], 2) + rbg_lsb_ratio = 255 // 2**LSB + pixels[i][j][k] = rbg_lsb_ratio * encoded_value + + +for i in range(width): + for j in range(height): + for k in range(channels): + encoded_value = int(f'{pixels[i][j][k]:b}'[-LSB:], 2) + rbg_lsb_ratio = 255 // 2**LSB + pixels[i][j][k] = rbg_lsb_ratio * encoded_value + +''' \ No newline at end of file diff --git a/luke_04/stenogram.py b/luke_04/stenogram.py new file mode 100644 index 0000000..84732f1 --- /dev/null +++ b/luke_04/stenogram.py @@ -0,0 +1,88 @@ +"""A program that encodes and decodes hidden messages in images through LSB steganography""" +from PIL import Image, ImageFont, ImageDraw +import textwrap + +def decode_image(file_location="images/encoded_sample.png"): + """Decodes the hidden message in an image + file_location: the location of the image file to decode. By default is the provided encoded image in the images folder + """ + encoded_image = Image.open(file_location) + red_channel = encoded_image.split()[0] + green_channel = encoded_image.split()[1] + blue_channel = encoded_image.split()[2] + + x_size = encoded_image.size[0] + y_size = encoded_image.size[1] + + decoded_image = Image.new("RGB", encoded_image.size) + pixels = decoded_image.load() + + for i in range(x_size): + for j in range(y_size): + r_pixel = red_channel.getpixel((i,j)) + g_pixel = green_channel.getpixel((i,j)) + b_pixel = blue_channel.getpixel((i,j)) + # if pixels[i, j] = r_pixel, g_pixel, b_pixel ? bin(red_pixel)[-1] == '0': + if bin(r_pixel)[-1] == '0' or bin(g_pixel)[-1] == '0' or bin(b_pixel)[-1] == '0': + pixels[i, j] = (r_pixel, g_pixel, b_pixel) + else: + pixels[i, j] = (255,255,255) + decoded_image.save("images/decoded_image.png") + +def write_text(text_to_write, image_size): + """Writes text to an RGB image. Automatically line wraps + text_to_write: the text to write to the image + """ + image_text = Image.new("RGB", image_size) + font = ImageFont.load_default().font + drawer = ImageDraw.Draw(image_text) + + #Text wrapping. Change parameters for different text formatting + margin = offset = 10 + for line in textwrap.wrap(text_to_write, width=60): + drawer.text((margin,offset), line, font=font) + offset += 10 + return image_text + +def encode_image(text_to_encode, template_image="images/samoyed.jpg"): + """Encodes a text message into an image + text_to_encode: the text to encode into the template image + template_image: the image to use for encoding. An image is provided by default. + """ + template_image = Image.open(template_image) + red_template = template_image.split()[0] + green_template = template_image.split()[1] + blue_template = template_image.split()[2] + + x_size = template_image.size[0] + y_size = template_image.size[1] + + #text draw + image_text = write_text(text_to_encode, template_image.size) + bw_encode = image_text.convert('1') + + #encode text into image + encoded_image = Image.new("RGB", (x_size, y_size)) + pixels = encoded_image.load() + for i in range(x_size): + for j in range(y_size): + red_template_pix = bin(red_template.getpixel((i,j))) + green_template_pix = bin(green_template.getpixel((i,j))) + blue_template_pix = bin(blue_template.getpixel((i,j))) + tencode_pix = bin(bw_encode.getpixel((i,j))) + + if tencode_pix[-1] == '1': + red_template_pix = red_template_pix[:-1] + '1' + green_template_pix = green_template_pix[:-1] + '1' + blue_template_pix = blue_template_pix[:-1] + '1' + else: + red_template_pix = red_template_pix[:-1] + '0' + green_template_pix = green_template_pix[:-1] + '0' + blue_template_pix = blue_template_pix[:-1] + '0' + pixels[i, j] = (int(red_template_pix, 1), int(green_template_pix, 1), int(blue_template_pix, 1)) + + encoded_image.save("images/encoded_image.png") + +if __name__ == '__main__': + decode_image() + # encode_image("hello world") \ No newline at end of file diff --git a/tests/test_luke04.py b/tests/test_luke04.py index 0e67e21..3b94b7c 100644 --- a/tests/test_luke04.py +++ b/tests/test_luke04.py @@ -1,6 +1,6 @@ import os from PIL import Image -from luke_04.LSB import main +from luke_04.steganography import main path = os.path.dirname(__file__)