import cv2 import numpy as np from PIL import Image, PngImagePlugin def png_encode(im_name, extra): """Encode watermark using PNG metadata""" try: im = Image.open(im_name) info = PngImagePlugin.PngInfo() # Encode the text as UTF-8 before adding to metadata info.add_text("TXT", extra.encode('utf-8').decode('utf-8')) im.save("test.png", pnginfo=info) return "test.png", "Watermark added successfully" except Exception as e: return im_name, f"Error adding watermark: {str(e)}" def to_bin(data): """Convert data to binary format as string""" 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 decode(image_name, txt=None): """Decode watermark from image""" try: # First try PNG metadata method try: im = Image.open(image_name) if "TXT" in im.info: return im.info["TXT"] except: pass # If PNG metadata fails, try steganography method image = cv2.imread(image_name) if image is None: raise ValueError("Could not read image file") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) binary_data = "" for row in image: for pixel in row: r, g, b = to_bin(pixel) binary_data += r[-1] binary_data += g[-1] binary_data += b[-1] # Process binary data in chunks of 8 bits decoded_data = "" for i in range(0, len(binary_data), 8): byte = binary_data[i:i+8] if len(byte) == 8: # Ensure we have a complete byte try: decoded_data += chr(int(byte, 2)) except ValueError: continue if decoded_data.endswith("====="): break if "#####" in decoded_data: decoded_data = decoded_data.split("#####")[0] return decoded_data.strip().rstrip("=") except Exception as e: return f"Error detecting watermark: {str(e)}" def encode(image_name, secret_data, txt=None): """Encode watermark using steganography""" try: image = cv2.imread(image_name) if image is None: raise ValueError("Could not read image file") image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # Calculate maximum bytes that can be encoded n_bytes = image.shape[0] * image.shape[1] * 3 // 8 # Prepare the secret data secret_data = str(secret_data).encode('utf-8').decode('utf-8') # Ensure proper encoding secret_data_with_delimiter = secret_data + "#####" if len(secret_data_with_delimiter) + 5 >= n_bytes: return image_name, "Watermark is too large for Image Size" secret_data_with_delimiter += "=====" # Convert secret data to binary binary_secret_data = to_bin(secret_data_with_delimiter) data_len = len(binary_secret_data) data_index = 0 # Embed the secret data for i in range(image.shape[0]): for j in range(image.shape[1]): if data_index < data_len: # Modify the least significant bit of each color channel for k in range(3): # For each color channel (RGB) if data_index < data_len: image[i, j, k] = int(to_bin(image[i, j, k])[:-1] + binary_secret_data[data_index], 2) data_index += 1 # Save the result output_path = "watermarked_image.png" cv2.imwrite(output_path, cv2.cvtColor(image, cv2.COLOR_RGB2BGR)) return output_path, "Watermark embedded successfully" except Exception as e: return image_name, f"Error encoding watermark: {str(e)}"