"""

This module implements a slight variant of the F4 steganography algorithm invented by Andreas Westfeld. It embeds a secret message in JPEG DCT coefficients.

It differs from F3 in that even negative and odd positive DCT coefficients represent a 1 and odd negative and even positive DCT coefficients represent a 0. It also supports permutative strattling which is not included in the original description of F4. """ import time import numpy as np from msteg.StegBase import StegBase from common import * 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): """ Constructor of the F3 class. """ StegBase.__init__(self) def embed_raw_data(self, src_cover, src_hidden, tgt_stego): """ This method embeds arbitrary data into a cover image. The cover image must be a JPEG. src_cover - A valid pathname to an image file which serves as cover image (the image which the secret image is embedded into). src_hidden - A valid pathname to an arbitrary file that is supposed to be embedded into the cover image. tgt_stego - Target pathname of the resulting stego image. You should save to a PNG or another lossless format, because many LSBs don't survive lossy compression. """ self.t0 = time.time() StegBase._post_embed_actions(self, src_cover, src_hidden, tgt_stego) def extract_raw_data(self, src_steg, tgt_hidden): """ This method extracts secret data from a stego image. It is (obviously) the inverse operation of embed_raw_data. src_stego - A valid pathname to an image file which serves as stego image. tgt_hidden - A pathname denoting where the extracted data should be saved to. """ self.t0 = time.time() StegBase._post_extract_actions(self, src_steg, tgt_hidden) def _raw_embed(self, cov_data, hid_data, status_begin=0): """ cov_data - 4-D numpy.int32 array hid_data - 1-D numpy.uint8 array """ hid_data = bytes2bits(hid_data) i = 0 cnt = -1 for x in np.nditer(cov_data, op_flags=['readwrite']): cnt = cnt + 1 if x == 0 or cnt % 64 == 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 def _raw_extract(self, steg_data, num_bits): """ Just a small helper function to extract hidden data. """ hid_data = np.zeros(num_bits, np.uint8) j = 0 cnt = -1 for x in np.nditer(steg_data): cnt = cnt + 1 if x == 0 or cnt % 64 == 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 def __str__(self): return "F4'"