__author__ = 'chunk' import time import numpy as np from .. import * from ...common import * class LSB(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): """ 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 x == 1 or cnt % 64 == 0: continue m = (hid_data[i] & 1) x[...] = (x & 0xfffffffe) | m # '0xfffe' is enough, for elements are expected to be short integers. 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 x == 1 or cnt % 64 == 0: continue if j >= num_bits: break hid_data[j] = x & 1 j = j + 1 return hid_data def __str__(self): return 'LSB' # this function might be a candidate for some kind of util module def _parse_boolean(b): """Turns a boolean value into a string if it is not already a boolean. @param b: A boolean or a string. @return: A boolean value representing b. Every value of b is interpreted to be true except the boolean False and any string that satisfies a case-insensitive comparison with 'false'. """ return b if isinstance(b, bool) else b.strip.lower() != 'false'