__author__ = 'chunk'
import numpy as np
import numpy.random as rnd
from .. import *
from ...common import *
from ...mjpeg import Jpeg
class F4(StegBase):
""" This module has two methods: embed_raw_data to embed data
with the F3 algorithm and extract_raw_data to extract data
which was embedded previously. """
def __init__(self, key=sample_key):
"""
Constructor of the F3 class.
"""
StegBase.__init__(self, key)
def _get_cov_data(self, img_path):
"""
Returns DCT coefficients of the cover image.
"""
self.cov_jpeg = Jpeg(img_path, key=self.key)
cov_data = self.cov_jpeg.getsignal(channel='Y')
self.cov_data = np.array(cov_data, dtype=np.int16)
return self.cov_data
def embed_raw_data(self, src_cover, src_hidden, tgt_stego):
self.t0 = time.time()
try:
cov_data = self._get_cov_data(src_cover)
hid_data = self._get_hid_data(src_hidden)
# print hid_data.dtype,type(hid_data),hid_data.tolist()
cov_data, bits_cnt = self._raw_embed(cov_data, hid_data)
if bits_cnt != np.size(hid_data) * 8:
raise Exception("Expected embedded size is %db but actually %db." % (
np.size(hid_data) * 8, bits_cnt))
self.cov_jpeg.setsignal(cov_data, channel='Y')
self.cov_jpeg.Jwrite(tgt_stego)
cov_bits = np.sum(cov_data != 0) - cov_data.size / 64
self._display_rate(cov_bits, bits_cnt)
# # size_cov = os.path.getsize(tgt_stego)
# size_cov = np.size(cov_data) / 8
# size_embedded = np.size(hid_data)
#
# self._display_stats("embedded", size_cov, size_embedded,
# time.time() - self.t0)
except TypeError as e:
raise e
except Exception as expt:
print "Exception when embedding!"
raise
def extract_raw_data(self, src_steg, tgt_hidden):
self.t0 = time.time()
try:
steg_data = self._get_cov_data(src_steg)
# emb_size = os.path.getsize(src_steg)
emb_size = np.size(steg_data) / 8
# recovering file size
header_size = 4 * 8
size_data, bits_cnt = self._raw_extract(steg_data, header_size)
if bits_cnt < header_size:
raise Exception("Expected embedded size is %db but actually %db." % (
header_size, bits_cnt))
size_data = bits2bytes(size_data)
size_hd = 0
for i in xrange(4):
size_hd += size_data[i] * 256 ** i
raw_size = size_hd * 8
if raw_size > np.size(steg_data):
raise Exception("Supposed secret data too large for stego image.")
hid_data, bits_cnt = self._raw_extract(steg_data, raw_size)
if bits_cnt != raw_size:
raise Exception("Expected embedded size is %db but actually %db." % (
raw_size, bits_cnt))
hid_data = bits2bytes(hid_data)
# print hid_data.dtype,type(hid_data),hid_data.tolist()
hid_data[4:].tofile(tgt_hidden)
self._display_stats("extracted", emb_size,
np.size(hid_data),
time.time() - self.t0)
except Exception as expt:
print "Exception when extracting!"
raise
def _raw_embed(self, cov_data, hid_data):
"""
cov_data - 1-D numpy.int16 array (permunated)
hid_data - 1-D numpy.uint8 array
"""
hid_data = bytes2bits(hid_data)
i = 0
for x in np.nditer(cov_data, op_flags=['readwrite']):
if x == 0: continue
m = (hid_data[i] & 1)
if x > 0 and x & 1 != m:
x[...] -= 1
elif x < 0 and x & 1 == m:
x[...] += 1
if x == 0: continue
i += 1
if i == hid_data.size: break
return cov_data, i
def _raw_extract(self, steg_data, num_bits):
"""
Just a small helper function to extract hidden data.
steg_data - 1-D numpy.int16 array (permunated)
"""
hid_data = np.zeros(num_bits, np.uint8)
j = 0
for x in steg_data:
if x == 0: continue
if j >= num_bits: break
if x > 0:
hid_data[j] = x & 1
else:
hid_data[j] = (x & 1) ^ 1
j = j + 1
return hid_data, j
def __str__(self):
return "F4"