noumanjavaid's picture
Update utils.py
66655a5 verified
raw
history blame
4.44 kB
import cv2
import numpy as np
from PIL import Image, PngImagePlugin
import os
import uuid
def to_bin(data):
"""Convert data to binary format"""
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):
"""Encode watermark into image"""
try:
# Read the image
image = cv2.imread(image_path)
if image is None:
return None, "Failed to read image"
# Calculate maximum bytes for encoding
max_bytes = (image.shape[0] * image.shape[1] * 3) // 8
# Add delimiters to secret data
secret_data = f"START{secret_data}END"
# Check if the data can fit in the image
if len(secret_data) * 8 > max_bytes:
return None, "Watermark is too large for image size"
# Convert data to binary
binary_secret_data = to_bin(secret_data)
data_len = len(binary_secret_data)
# Create output image
watermarked_image = image.copy()
data_index = 0
# Embed the data
for i in range(watermarked_image.shape[0]):
if data_index >= data_len:
break
for j in range(watermarked_image.shape[1]):
if data_index >= data_len:
break
for k in range(3):
if data_index >= data_len:
break
# Get binary pixel value
binary_pixel = to_bin(watermarked_image[i, j, k])
# Replace least significant bit
new_binary = binary_pixel[:-1] + binary_secret_data[data_index]
watermarked_image[i, j, k] = int(new_binary, 2)
data_index += 1
return watermarked_image, None
except Exception as e:
return None, f"Error during encoding: {str(e)}"
def decode(image_path):
"""Decode watermark from image"""
try:
# Read the image
if isinstance(image_path, str):
image = cv2.imread(image_path)
else:
# Handle PIL Image input
image = cv2.cvtColor(np.array(Image.open(image_path)), cv2.COLOR_RGB2BGR)
if image is None:
return "Failed to read image"
binary_data = ""
# Extract LSB from each pixel
for i in range(image.shape[0]):
for j in range(image.shape[1]):
for k in range(3):
binary_pixel = to_bin(image[i, j, k])
binary_data += binary_pixel[-1]
# Convert binary to text
text_data = ""
for i in range(0, len(binary_data), 8):
byte = binary_data[i:i+8]
if len(byte) == 8:
text_data += chr(int(byte, 2))
# Check for end marker
if "END" in text_data:
# Extract the actual message between START and END
start_idx = text_data.find("START")
end_idx = text_data.find("END")
if start_idx != -1 and end_idx != -1:
return text_data[start_idx+5:end_idx]
return "No watermark found"
except Exception as e:
return f"Error during decoding: {str(e)}"
def png_encode(im_name, extra):
"""Encode watermark into PNG metadata"""
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}.png"
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)