File size: 4,443 Bytes
1618e9b
b2358ad
aa56dd1
1618e9b
 
aa56dd1
059deb6
66655a5
059deb6
66655a5
059deb6
66655a5
059deb6
66655a5
059deb6
66655a5
059deb6
 
1618e9b
dbea623
66655a5
dbea623
 
 
 
 
66655a5
dbea623
66655a5
dbea623
66655a5
 
 
 
 
 
db1515c
 
66655a5
dbea623
66655a5
 
 
dbea623
 
66655a5
 
dbea623
 
66655a5
 
 
 
 
 
 
 
 
 
 
 
 
 
dbea623
 
1618e9b
dbea623
66655a5
f00a6e1
dbea623
66655a5
 
 
 
 
 
dbea623
 
66655a5
f00a6e1
66655a5
 
 
 
 
 
 
dbea623
 
66655a5
 
 
 
 
 
 
 
 
 
 
 
dbea623
66655a5
f00a6e1
dbea623
1618e9b
dbea623
66655a5
dbea623
 
 
 
059deb6
dbea623
 
66655a5
dbea623
 
 
 
 
 
 
 
 
 
 
66655a5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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)