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: # Read the image image = cv2.imread(image_path) if image is None: return None, "Failed to read image" # Calculate maximum bytes for encoding n_bytes = (image.shape[0] * image.shape[1] * 3) // 8 # Prepare secret data 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) # Create a copy of the image watermarked_image = image.copy() data_index = 0 # Encode the data for i in range(watermarked_image.shape[0]): for j in range(watermarked_image.shape[1]): for k in range(3): # RGB channels if data_index < data_len: # Get the current pixel value pixel = watermarked_image[i, j, k] # Convert to binary and modify the least significant bit binary_pixel = format(pixel, '08b') new_pixel = binary_pixel[:-1] + binary_secret_data[data_index] # Update the pixel value 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: # Read the image image = cv2.imread(image_path) if image is None: return "Failed to read image" binary_data = "" # Extract the least significant bits 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] # Convert binary to text 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)) # Check for ending delimiter if decoded_data[-5:] == "=====": break # Remove delimiters and return the message 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)