"""

This module implements the F3 steganography algorithm invented by Andreas Westfeld.

It embeds a secret message in JPEG DCT coefficients. It differs from simpler algorithms such as JSteg by subtracting the absolute DCT value if the currently embedded bit and the LSB of the DCT value are not equal. DCT coefficients with value 0 are ignored.
If a DCT coefficient is equal to 1 or -1 the current bit is embedded repeatedly in order to make non-ambiguous extraction possible. """ import time import math import numpy as np from msteg.StegBase import StegBase from common import * class F3(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 & 1 != m: x[...] -= math.copysign(1, x) 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. """ 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 hid_data[j] = x & 1 j = j + 1 return hid_data,j def __str__(self): return 'F3'