-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimageStegHelper.py
More file actions
153 lines (131 loc) · 4.76 KB
/
imageStegHelper.py
File metadata and controls
153 lines (131 loc) · 4.76 KB
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
from PIL import Image
import numpy as np
import heapq
from collections import defaultdict
import os
class HuffmanNode:
def __init__(self, char, freq):
self.char = char
self.freq = freq
self.left = None
self.right = None
def __lt__(self, other):
return self.freq < other.freq
class ImageSteg:
def __init__(self):
pass
# Methods for Huffman Coding
def build_huffman_tree(self, text):
frequency = defaultdict(int)
for char in text:
frequency[char] += 1
priority_queue = [HuffmanNode(char, freq) for char, freq in frequency.items()]
heapq.heapify(priority_queue)
while len(priority_queue) > 1:
left = heapq.heappop(priority_queue)
right = heapq.heappop(priority_queue)
merged = HuffmanNode(None, left.freq + right.freq)
merged.left = left
merged.right = right
heapq.heappush(priority_queue, merged)
return priority_queue[0]
def build_huffman_codes(self, root, prefix="", codes=None):
if codes is None:
codes = {}
if root is not None:
if root.char is not None:
codes[root.char] = prefix
self.build_huffman_codes(root.left, prefix + "0", codes)
self.build_huffman_codes(root.right, prefix + "1", codes)
return codes
def huffman_compress(self, text):
root = self.build_huffman_tree(text)
codes = self.build_huffman_codes(root)
encoded_text = "".join(codes[char] for char in text)
return encoded_text, codes
def huffman_decompress(self, text, codes):
decoded_text = ""
current_code = ""
for bit in text:
current_code += bit
for char, code in codes.items():
if code == current_code:
decoded_text += char
current_code = ""
break
return decoded_text
# Method for Run-Length Encoding
def rle_compress(self, text):
encoded_text = ""
count = 1
for i in range(1, len(text)):
if text[i] == text[i - 1]:
count += 1
else:
encoded_text += str(count) + text[i - 1]
count = 1
encoded_text += str(count) + text[-1]
return encoded_text
def rle_decompress(self, text):
decoded_text = ""
i = 0
while i < len(text):
count = int(text[i])
char = text[i + 1]
decoded_text += char * count
i += 2
return decoded_text
def __fillMSB(self, inp):
'''
0b01100 -> [0,0,0,0,1,1,0,0]
'''
inp = inp.split("b")[-1]
inp = '0'*(7-len(inp))+inp
return [int(x) for x in inp]
def __decrypt_pixels(self, pixels):
'''
Given list of 7 pixel values -> Determine 0/1 -> Join 7 0/1s to form binary -> integer -> character
'''
pixels = [str(x%2) for x in pixels]
bin_repr = "".join(pixels)
return chr(int(bin_repr,2))
def encrypt_text_in_image(self, image_path, msg, target_path=""):
'''
Read image -> Flatten -> encrypt images using LSB -> reshape and repack -> return image
'''
img = np.array(Image.open(image_path))
imgArr = img.flatten()
msg += "<-END->"
msgArr = [self.__fillMSB(bin(ord(ch))) for ch in msg]
idx = 0
for char in msgArr:
for bit in char:
if bit==1:
if imgArr[idx]==0:
imgArr[idx] = 1
else:
imgArr[idx] = imgArr[idx] if imgArr[idx]%2==1 else imgArr[idx]-1
else:
if imgArr[idx]==255:
imgArr[idx] = 254
else:
imgArr[idx] = imgArr[idx] if imgArr[idx]%2==0 else imgArr[idx]+1
idx += 1
filename = os.path.basename(image_path)
savePath = os.path.join(target_path, filename.split(".")[0] + "_embedded.png")
resImg = Image.fromarray(np.reshape(imgArr, img.shape))
resImg.save(savePath)
return savePath
def decrypt_text_in_image(self, image_path):
'''
Read image -> Extract Text -> Return
'''
img = np.array(Image.open(image_path))
imgArr = np.array(img).flatten()
decrypted_message = ""
for i in range(7,len(imgArr),7):
decrypted_char = self.__decrypt_pixels(imgArr[i-7:i])
decrypted_message += decrypted_char
if len(decrypted_message)>10 and decrypted_message[-7:] == "<-END->":
break
return decrypted_message[:-7]