|
import cv2 |
|
import numpy as np |
|
from PIL import Image, PngImagePlugin |
|
import os |
|
import uuid |
|
|
|
def to_bin(data): |
|
if isinstance(data, str): |
|
return ''.join([format(ord(i), "08b") for i in data]) |
|
elif isinstance(data, bytes): |
|
return ''.join([format(i, "08b") for i in data]) |
|
elif isinstance(data, np.ndarray): |
|
return [format(i, "08b") for i in data] |
|
elif isinstance(data, int) or isinstance(data, np.uint8): |
|
return format(data, "08b") |
|
else: |
|
raise TypeError("Type not supported.") |
|
|
|
def encode(image_path, secret_data): |
|
try: |
|
|
|
image = cv2.imread(image_path) |
|
if image is None: |
|
return None, "Failed to read image" |
|
|
|
|
|
n_bytes = (image.shape[0] * image.shape[1] * 3) // 8 |
|
|
|
|
|
secret_data_with_delimiter = f'{secret_data}#####' |
|
if len(secret_data_with_delimiter) + 5 >= n_bytes: |
|
return None, "Watermark is too large for Image Size" |
|
|
|
secret_data_with_delimiter += "=====" |
|
binary_secret_data = to_bin(secret_data_with_delimiter) |
|
data_len = len(binary_secret_data) |
|
|
|
|
|
watermarked_image = image.copy() |
|
data_index = 0 |
|
|
|
|
|
for i in range(watermarked_image.shape[0]): |
|
for j in range(watermarked_image.shape[1]): |
|
for k in range(3): |
|
if data_index < data_len: |
|
|
|
pixel = watermarked_image[i, j, k] |
|
|
|
binary_pixel = format(pixel, '08b') |
|
new_pixel = binary_pixel[:-1] + binary_secret_data[data_index] |
|
|
|
watermarked_image[i, j, k] = int(new_pixel, 2) |
|
data_index += 1 |
|
else: |
|
break |
|
if data_index >= data_len: |
|
break |
|
if data_index >= data_len: |
|
break |
|
|
|
return watermarked_image, None |
|
except Exception as e: |
|
return None, f"Error during encoding: {str(e)}" |
|
|
|
def decode(image_path): |
|
try: |
|
|
|
image = cv2.imread(image_path) |
|
if image is None: |
|
return "Failed to read image" |
|
|
|
binary_data = "" |
|
|
|
for i in range(image.shape[0]): |
|
for j in range(image.shape[1]): |
|
for k in range(3): |
|
pixel = format(image[i, j, k], '08b') |
|
binary_data += pixel[-1] |
|
|
|
|
|
decoded_data = "" |
|
for i in range(0, len(binary_data), 8): |
|
byte = binary_data[i:i+8] |
|
if len(byte) == 8: |
|
decoded_data += chr(int(byte, 2)) |
|
|
|
if decoded_data[-5:] == "=====": |
|
break |
|
|
|
|
|
if "#####" in decoded_data: |
|
return decoded_data.split("#####")[0] |
|
return "No watermark found" |
|
|
|
except Exception as e: |
|
return f"Error during decoding: {str(e)}" |
|
|
|
def png_encode(im_name, extra): |
|
try: |
|
im = Image.open(im_name) |
|
info = PngImagePlugin.PngInfo() |
|
info.add_text("TXT", extra) |
|
|
|
unique_id = str(uuid.uuid4())[:8] |
|
filename, ext = os.path.splitext(im_name) |
|
new_filename = f"{filename}_{unique_id}{ext}" |
|
im.save(new_filename, "PNG", pnginfo=info) |
|
|
|
width, height = im.size |
|
rect_width, rect_height = 200, 50 |
|
x = width - rect_width - 10 |
|
y = height - rect_height - 10 |
|
global png_encode_coords |
|
png_encode_coords = (x, y, rect_width, rect_height) |
|
|
|
return new_filename, None |
|
|
|
except Exception as e: |
|
return None, str(e) |
|
|