Skip to content

Commit de79bdf

Browse files
Fixed bug in random noise storing
1 parent 69d749d commit de79bdf

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

injection.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import numpy as np
2+
3+
from constants.constants import *
4+
from utils.bit_storing import store_bits, retrieve_bits
5+
from utils.conversor import conv
6+
from utils.ctxt import *
7+
from utils.progress_bar import progress_bar
8+
9+
def inject_file(img_arr:np.ndarray, file:str, filename:str, store_random:bool) -> np.ndarray:
10+
print(ctxt("\nPreparing...\n", Fore.MAGENTA))
11+
12+
img_arr_flat = img_arr.flatten()
13+
14+
#-------------------------------------------------------
15+
# Get the maximum size the file can have
16+
max_file_size = len(img_arr_flat) - MAX_FN_SIZE_BIN - 1
17+
# Get the length of the maximum size in binary
18+
max_file_size_len = len(conv(max_file_size, 2))
19+
# Get the available pixels for storing the file
20+
available_channels = max_file_size - max_file_size_len
21+
#-------------------------------------------------------
22+
# Get the base to use and the mask
23+
times = available_channels // len(file)
24+
if times < 1:
25+
needed_img_size = (len(file) + MAX_FN_SIZE_BIN + 1 + 50)/3 # 50 is a really big image size ((2^50)/3 pixels)
26+
raise Exception(f"Image is too small to store the file. Needed size: {ctxt(f'{round(needed_img_size/1000000,4)} MP', Fore.YELLOW)}")
27+
times = times if times <= 4 else 4
28+
base_exp = 5-times
29+
base = 2**base_exp
30+
mask = 256 - base
31+
#-------------------------------------------------------
32+
# Convert the filename to base 2 and fill it left with 0s
33+
filename_conv = conv(int(filename,16), 2).zfill(MAX_FN_SIZE_BIN)
34+
35+
# Convert the file to base {base}
36+
file_conv = conv(int(file,16), base)
37+
38+
# Get the file size and convert it to base 2
39+
file_size = len(file_conv)
40+
file_size_conv = conv(file_size, 2).zfill(max_file_size_len) # image resolution in pixels
41+
#-------------------------------------------------------
42+
print(f"Modified bits per channel: {ctxt(base_exp, Fore.YELLOW)}")
43+
print(f"Image modification: {ctxt(f'{round(base/256*100, 2)}%', Fore.YELLOW)}\n")
44+
#-------------------------------------------------------
45+
# (1) Store the (base exponent) in idx 0 (e.g. 3 = 2^3 = 8)
46+
img_arr_flat[0] = store_bits(img_arr_flat[0], base_exp, MAX_BASE_EXP_MASK)
47+
idx = 1
48+
# Store the file size in the next {max_file_size_len} pixels
49+
for i,h in enumerate(file_size_conv):
50+
img_arr_flat[idx+i] = store_bits(img_arr_flat[idx+i], int(h, 2), 256 - 2)
51+
idx += len(file_size_conv)
52+
#-------------------------------------------------------
53+
# Store the filename
54+
for i,h in enumerate(filename_conv):
55+
img_arr_flat[idx+i] = store_bits(img_arr_flat[idx+i], int(h, 2), 256 - 2)
56+
idx += len(filename_conv)
57+
58+
# Store the input file
59+
for i in range(len(file_conv)):
60+
if i % 10000 == 0 or i == len(file_conv)-1:
61+
progress_bar(i/(len(file_conv)-1), ctxt("Storing...", Fore.GREEN))
62+
img_arr_flat[idx+i] = store_bits(img_arr_flat[idx+i], int(file_conv[i], base), mask)
63+
idx += len(file_conv)
64+
#-------------------------------------------------------
65+
# Store random values on the rest of the pixels
66+
if store_random:
67+
print(ctxt("\nGenerating random values...", Fore.MAGENTA))
68+
rands = list(np.random.randint(low = 0, high=base, size=len(img_arr_flat[idx:])))
69+
print(ctxt("\nStoring random values...", Fore.MAGENTA))
70+
img_arr_flat[idx:] = np.array([store_bits(x, rands[i], mask) for i,x in enumerate(img_arr_flat[idx:].tolist())])
71+
#-------------------------------------------------------
72+
# Return flat_img to original shape
73+
print(ctxt("\nReshaping...", Fore.MAGENTA))
74+
img_arr = img_arr_flat.reshape(img_arr.shape)
75+
76+
return img_arr
77+
78+
79+
80+
def extract_file(mod_img_arr_flat:np.ndarray) -> str:
81+
print(ctxt("\nPreparing...", Fore.MAGENTA))
82+
83+
# Get the maximum size the file can have
84+
max_file_size = len(mod_img_arr_flat) - MAX_FN_SIZE_BIN - 1
85+
# Get the length of the maximum size in binary
86+
max_file_size_len = len(conv(max_file_size, 2))
87+
88+
# Get the base
89+
base_exp = retrieve_bits(mod_img_arr_flat[0], MAX_BASE_EXP_BASE)
90+
base = 2**base_exp
91+
idx = 1
92+
93+
# Get the file size
94+
file_size_str = "".join([f'{retrieve_bits(x, 2):b}' for x in mod_img_arr_flat[idx:idx+max_file_size_len]])
95+
file_size = int(file_size_str, 2)
96+
idx += max_file_size_len
97+
98+
# Get the filename
99+
print(ctxt("\nRetrieving filename...", Fore.MAGENTA))
100+
filename_str = "".join([f'{retrieve_bits(x, 2):b}' for x in mod_img_arr_flat[idx:idx+MAX_FN_SIZE_BIN]])
101+
filename_hex = f"{int(filename_str, 2):x}"
102+
idx += MAX_FN_SIZE_BIN
103+
104+
# Get the file
105+
print(ctxt("\nRetrieving input file...", Fore.MAGENTA))
106+
file_str = "".join([f'{retrieve_bits(x, base):x}' for x in mod_img_arr_flat[idx:idx+file_size]])
107+
file_hex = f"{int(file_str, base):x}"
108+
109+
# Return the filename and the input file
110+
return {
111+
"filename": bytes.fromhex(filename_hex),
112+
"file": bytes.fromhex(file_hex)
113+
}

0 commit comments

Comments
 (0)