File size: 4,159 Bytes
f6cb6df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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)