Commit 8cfc1a2373c0fb2aa9b6fcbd6a4e795f3ac76320

Authored by Chunk
1 parent 033d3b0d
Exists in master

F5 half-finished.

jpegObj/__init__.pyc
No preview for this file type
msteg/StegBase.py
... ... @@ -102,6 +102,10 @@ class StegBase(object):
102 102 # recovering file size
103 103 header_size = 4 * 8
104 104 size_data, bits_cnt = self._raw_extract(steg_data, header_size)
  105 + if bits_cnt < header_size:
  106 + raise Exception("Expected embedded size is %db but actually %db." % (
  107 + header_size, bits_cnt))
  108 +
105 109 size_data = bits2bytes(size_data)
106 110 size_hd = 0
107 111 for i in xrange(4):
... ...
msteg/StegBase.pyc
No preview for this file type
msteg/steganography/F3.pyc
No preview for this file type
msteg/steganography/F4-simple.py 0 → 100644
... ... @@ -0,0 +1,101 @@
  1 +__author__ = 'chunk'
  2 +
  3 +"""
  4 +<p>This module implements a slight variant of the F4 steganography algorithm
  5 +invented by Andreas Westfeld. It embeds a secret message in JPEG
  6 +DCT coefficients.</p>
  7 +It differs from F3 in that even negative and odd positive DCT
  8 +coefficients represent a 1 and odd negative and even positive
  9 +DCT coefficients represent a 0. It also supports permutative strattling
  10 +which is not included in the original description of F4.
  11 +"""
  12 +import time
  13 +import numpy as np
  14 +from msteg.StegBase import StegBase
  15 +from common import *
  16 +
  17 +
  18 +class F4(StegBase):
  19 + """ This module has two methods: <i>embed_raw_data</i> to embed data
  20 + with the F3 algorithm and <i>extract_raw_data</i> to extract data
  21 + which was embedded previously. """
  22 +
  23 + def __init__(self):
  24 + """
  25 + Constructor of the F3 class.
  26 + """
  27 + StegBase.__init__(self)
  28 +
  29 + def embed_raw_data(self, src_cover, src_hidden, tgt_stego):
  30 + """ This method embeds arbitrary data into a cover image.
  31 + The cover image must be a JPEG.
  32 +
  33 + src_cover - A valid pathname to an image file which serves as cover image
  34 + (the image which the secret image is embedded into).
  35 +
  36 + src_hidden - A valid pathname to an arbitrary file that is supposed to be
  37 + embedded into the cover image.
  38 +
  39 + tgt_stego - Target pathname of the resulting stego image. You should save to a
  40 + PNG or another lossless format, because many LSBs don't survive
  41 + lossy compression.
  42 + """
  43 + self.t0 = time.time()
  44 + StegBase._post_embed_actions(self, src_cover, src_hidden, tgt_stego)
  45 +
  46 + def extract_raw_data(self, src_steg, tgt_hidden):
  47 + """ This method extracts secret data from a stego image. It is
  48 + (obviously) the inverse operation of embed_raw_data.
  49 +
  50 + src_stego - A valid pathname to an image file which serves as stego image.
  51 +
  52 + tgt_hidden - A pathname denoting where the extracted data should be saved to.
  53 + """
  54 + self.t0 = time.time()
  55 + StegBase._post_extract_actions(self, src_steg, tgt_hidden)
  56 +
  57 + def _raw_embed(self, cov_data, hid_data, status_begin=0):
  58 + """
  59 + cov_data - 4-D numpy.int32 array
  60 + hid_data - 1-D numpy.uint8 array
  61 + """
  62 + hid_data = bytes2bits(hid_data)
  63 + i = 0
  64 + cnt = -1
  65 + for x in np.nditer(cov_data, op_flags=['readwrite']):
  66 + cnt = cnt + 1
  67 + if x == 0 or cnt % 64 == 0: continue
  68 +
  69 + m = (hid_data[i] & 1)
  70 + if x > 0 and x & 1 != m:
  71 + x[...] -= 1
  72 + elif x < 0 and x & 1 == m:
  73 + x[...] += 1
  74 + if x == 0: continue
  75 + i += 1
  76 + if i == hid_data.size: break
  77 +
  78 + return cov_data
  79 +
  80 + def _raw_extract(self, steg_data, num_bits):
  81 + """
  82 + Just a small helper function to extract hidden data.
  83 + """
  84 + hid_data = np.zeros(num_bits, np.uint8)
  85 + j = 0
  86 + cnt = -1
  87 + for x in np.nditer(steg_data):
  88 + cnt = cnt + 1
  89 + if x == 0 or cnt % 64 == 0: continue
  90 + if j >= num_bits: break
  91 + if x > 0:
  92 + hid_data[j] = x & 1
  93 + else:
  94 + hid_data[j] = (x & 1) ^ 1
  95 +
  96 + j = j + 1
  97 +
  98 + return hid_data
  99 +
  100 + def __str__(self):
  101 + return "F4'"
... ...
msteg/steganography/F4.py
... ... @@ -74,6 +74,10 @@ class F4(StegBase):
74 74 # recovering file size
75 75 header_size = 4 * 8
76 76 size_data, bits_cnt = self._raw_extract(steg_data, header_size)
  77 + if bits_cnt < header_size:
  78 + raise Exception("Expected embedded size is %db but actually %db." % (
  79 + header_size, bits_cnt))
  80 +
77 81 size_data = bits2bytes(size_data)
78 82  
79 83 size_hd = 0
... ... @@ -120,6 +124,7 @@ class F4(StegBase):
120 124 if x == 0: continue
121 125 i += 1
122 126 if i == hid_data.size: break
  127 +
123 128 return cov_data, i
124 129  
125 130 def _raw_extract(self, steg_data, num_bits):
... ... @@ -127,6 +132,7 @@ class F4(StegBase):
127 132 Just a small helper function to extract hidden data.
128 133 steg_data - 1-D numpy.int16 array (permunated)
129 134 """
  135 +
130 136 hid_data = np.zeros(num_bits, np.uint8)
131 137 j = 0
132 138 for x in steg_data:
... ...
msteg/steganography/F4.pyc
No preview for this file type
msteg/steganography/F5.py
  1 +__author__ = 'chunk'
  2 +
1 3 """
2 4 <p>This module implements the rather sophisticated F5 algorithm which was
3 5 invented by Andreas Westfeld.</p>
... ... @@ -35,118 +37,134 @@ class F5(StegBase):
35 37 with the F5 algorithm and <i>extract_raw_data</i> to extract data
36 38 which was embedded previously. """
37 39  
38   - def __init__(self, key=sample_key):
  40 + def __init__(self, key=sample_key, k=None):
39 41 """
40 42 Constructor of the F5 class.
41 43 """
42 44 StegBase.__init__(self, key)
43 45 self._embed_fun = None
44 46 self.default_embedding = True
45   - self.steg_ind = -1
46   - self.excess_bits = None
  47 +
47 48 # needed because k is embedded separately
48   - self.cov_ind = -1
49   - self.k_coeff = -1
50   -
51   - @describe_annotate_convert((None, None, ident),
52   - ("cover image", ImagePath, str),
53   - ("hidden data", FilePath, str),
54   - ("stego image", NewFilePath, str),
55   - ("seed", int, int),
56   - ("embedding behavior",
57   - ['Default', 'F3', 'JSteg'], str))
58   - def embed_raw_data(self, src_cover, src_hidden, tgt_stego, seed,
59   - embed_fun):
60   - """<p>This method embeds arbitrary data into a cover image.
61   - The cover image must be a JPEG.</p>
62   -
63   - <p>Parameters:
64   - <ol>
65   - <li><pre>src_cover</pre>
66   - A valid pathname to an image file which serves as cover image
67   - (the image which the secret image is embedded into).</li>
68   -
69   - <li><pre>src_hidden</pre>
70   - A valid pathname to an arbitrary file that is supposed to be
71   - embedded into the cover image.</li>
72   -
73   - <li><pre>tgt_stego</pre>
74   - Target pathname of the resulting stego image. You should save to
75   - a PNG or another lossless format, because many LSBs don't survive
76   - lossy compression.</li>
77   -
78   - <li><pre>seed</pre>
79   - A seed for the random number generator that is responsible scattering
80   - the secret data within the cover image.</li>
81   -
82   - <li><pre>param embed_fun</pre>
  49 + self.k_coeff = k
  50 +
  51 +
  52 + def _get_cov_data(self, img_path):
  53 + """
  54 + Returns DCT coefficients of the cover image.
  55 + """
  56 + self.cov_jpeg = jpegObj.Jpeg(img_path, key=self.key)
  57 +
  58 + cov_data = self.cov_jpeg.getsignal(channel='Y')
  59 + self.cov_data = np.array(cov_data, dtype=np.int16)
  60 + return self.cov_data
  61 +
  62 + def embed_raw_data(self, src_cover, src_hidden, tgt_stego, embed_fun='Default'):
  63 + """This method embeds arbitrary data into a cover image.
  64 + The cover image must be a JPEG.
  65 +
  66 + @param embed_fun:
83 67 Specifies which embedding function should be used. Must be one of
84 68 'Default', 'F3', 'Jsteg'. If 'Default' is selected, the algorithm uses
85 69 the same behavior as Westfeld's implementation, i.e. decrementing
86 70 absolute values for n > 1 (F3) and using F4 in the special case n = 1.
87   - Selecting F3 or JSteg results in using that scheme for all n.</li>
88   - </ol>
89   - </p>
  71 + Selecting F3 or JSteg results in using that scheme for all n.
90 72 """
91 73 self.t0 = time.time()
92   - self.seed = seed
  74 +
93 75 if embed_fun == 'F3':
94 76 self._embed_fun = self._f3_embed
95 77 self.default_embedding = False
96   - elif embed_fun == 'JSteg':
  78 + elif embed_fun == 'JSteg' or embed_fun == 'LSB':
97 79 self._embed_fun = self._jsteg_embed
98 80 self.default_embedding = False
99   - elif embed_fun == 'Default':
  81 + else:
100 82 self._embed_fun = self._f3_embed
101 83 self.default_embedding = True
102 84  
103   - self.cov_ind = -1
104   - JPEGSteg._post_embed_actions(self, src_cover, src_hidden, tgt_stego)
  85 + try:
  86 + cov_data = self._get_cov_data(src_cover)
  87 + hid_data = self._get_hid_data(src_hidden)
  88 + # print hid_data.dtype,type(hid_data),hid_data.tolist()
105 89  
106   - @describe_annotate_convert((None, None, ident),
107   - ("stego image", ImagePath, str),
108   - ("hidden data", NewFilePath, str),
109   - ("seed", int, int),
110   - ("embedding behavior", ['Default', 'F3/JSteg'],
111   - str))
112   - def extract_raw_data(self, src_steg, tgt_hidden, seed, embed_fun):
113   - """<p>This method extracts secret data from a stego image. It is
114   - (obviously) the inverse operation of embed_raw_data.</p>
  90 + cov_data, bits_cnt = self._raw_embed(cov_data, hid_data)
115 91  
116   - <p>Parameters:
117   - <ol>
118   - <li><pre>src_stego</pre>
119   - A valid pathname to an image file which serves as stego image.</li>
  92 + if bits_cnt < np.size(hid_data) * 8:
  93 + raise Exception("Expected embedded size is %db but actually %db." % (
  94 + np.size(hid_data) * 8, bits_cnt))
120 95  
121   - <li><pre>tgt_hidden</pre>
122   - A pathname denoting where the extracted data should be saved to.</li>
  96 + self.cov_jpeg.setsignal(cov_data, channel='Y')
  97 + self.cov_jpeg.Jwrite(tgt_stego)
123 98  
124   - <li><pre>param seed</pre>
125   - A seed for the random number generator that is responsible scattering
126   - the secret data within the cover image.</li>
  99 + # size_cov = os.path.getsize(tgt_stego)
  100 + size_cov = np.size(cov_data) / 8
  101 + size_embedded = np.size(hid_data)
127 102  
128   - <li><pre>param embed_fun</pre>
129   - Specifies which embedding function should be used. Must be one of
130   - 'Default', 'F3', 'JSteg'. If 'Default' is selected, the algorithm uses
131   - the same behavior as Westfeld's implementation, i.e. decrementing
132   - absolute values for n > 1 (F3) and using F4 in the special case n = 1.
133   - Selecting F3 or JSteg results in using that scheme for all n.</li>
134   - </ol></pre>
135   - """
  103 + self._display_stats("embedded", size_cov, size_embedded,
  104 + time.time() - self.t0)
136 105  
  106 + except TypeError as e:
  107 + raise e
  108 + except Exception as expt:
  109 + print "Exception when embedding!"
  110 + raise
  111 +
  112 +
  113 + def extract_raw_data(self, src_steg, tgt_hidden, embed_fun='Default'):
137 114 self.t0 = time.time()
138   - self.seed = seed
139   - self.steg_ind = -1
140   - if embed_fun == 'F3/JSteg':
  115 +
  116 + if embed_fun == 'F3':
  117 + self._embed_fun = self._f3_embed
  118 + self.default_embedding = False
  119 + elif embed_fun == 'JSteg' or embed_fun == 'LSB':
  120 + self._embed_fun = self._jsteg_embed
141 121 self.default_embedding = False
142   - elif embed_fun == 'Default':
  122 + else:
  123 + self._embed_fun = self._f3_embed
143 124 self.default_embedding = True
144 125  
145   - # excess bits occur when the size of extracted data is not a multiple
146   - # of k. if excess bits are available, they are prepended to hidden data
147   - self.excess_bits = None
  126 + try:
  127 + steg_data = self._get_cov_data(src_steg)
  128 + # emb_size = os.path.getsize(src_steg)
  129 + emb_size = np.size(steg_data) / 8
  130 +
  131 + # recovering file size
  132 + header_size = 4 * 8
  133 + size_data, bits_cnt = self._raw_extract(steg_data, header_size)
  134 +
  135 + if bits_cnt < header_size:
  136 + raise Exception("Expected embedded size is %db but actually %db." % (
  137 + header_size, bits_cnt))
  138 +
  139 + size_data = bits2bytes(size_data[:header_size])
  140 + print size_data
  141 +
  142 + size_hd = 0
  143 + for i in xrange(4):
  144 + size_hd += size_data[i] * 256 ** i
  145 +
  146 + raw_size = size_hd * 8
  147 +
  148 + if raw_size > np.size(steg_data):
  149 + raise Exception("Supposed secret data too large for stego image.")
  150 +
  151 + hid_data, bits_cnt = self._raw_extract(steg_data, raw_size)
  152 +
  153 + if bits_cnt < raw_size:
  154 + raise Exception("Expected embedded size is %db but actually %db." % (
  155 + raw_size, bits_cnt))
  156 +
  157 + hid_data = bits2bytes(hid_data)
  158 + # print hid_data.dtype,type(hid_data),hid_data.tolist()
  159 + hid_data[4:].tofile(tgt_hidden)
  160 +
  161 + self._display_stats("extracted", emb_size,
  162 + np.size(hid_data),
  163 + time.time() - self.t0)
  164 + except Exception as expt:
  165 + print "Exception when extracting!"
  166 + raise
148 167  
149   - JPEGSteg._post_extract_actions(self, src_steg, tgt_hidden)
150 168  
151 169 def _embed_k(self, cov_data, hid_data):
152 170 np.random.seed(self.seed)
... ... @@ -218,153 +236,89 @@ class F5(StegBase):
218 236  
219 237 def _jsteg_embed(self, cov_data, ind):
220 238 m = 1 ^ (cov_data[ind] & 1)
221   - cov_data[ind] = (cov_data[ind] & 0xffffe) | m
  239 + cov_data[ind] = (cov_data[ind] & 0xfffffffe) | m
222 240  
223   - def _raw_embed(self, cov_data, hid_data, status_begin=0):
  241 + def _raw_embed(self, cov_data, hid_data):
224 242 k = self.k_coeff
225 243 n = (1 << k) - 1
  244 +
226 245 if n == 1 and self.default_embedding:
227   - # in case k = n = 1, Westfeld's implementation uses F4 for
228   - # embedding. Therefore, if 'default' embedding has been selected
229   - # we will do the same
230   - f4 = F4(self.ui, self.core)
231   - f4.seed = self.seed
232   - f4.dct_p = self.dct_p
233   - f4.cov_ind = self.cov_ind
234   - cov_data = f4._raw_embed(cov_data, hid_data, 30)
235   - return cov_data
236   -
237   - cov_ind = self.cov_ind # preventing RSI by writing 'self' less often
238   - hid_ind = 0
239   - remaining_bits = hid_data.size
240   - hid_size = float(hid_data.size)
241   - dct_p = self.dct_p
242   -
243   - update_cnt = int(hid_size / (70.0 * k))
244   - while remaining_bits > 0:
245   - if update_cnt == 0:
246   - self._set_progress(30 + int(((
247   - hid_size - remaining_bits) / hid_size) * 70))
248   - update_cnt = int(hid_size / (70.0 * k))
249   - update_cnt -= 1
250   - msg_chunk_size = min(remaining_bits, k)
251   - msg_chunk = np.zeros(k, np.int8)
252   - cov_chunk = np.zeros(n, np.int32)
253   - msg_chunk[0:msg_chunk_size] = hid_data[hid_ind:hid_ind +
254   - msg_chunk_size]
255   - hid_ind += k
256   -
257   - # get n DCT coefficients
258   - for i in xrange(n):
259   - cov_ind += 1
260   - while cov_data[dct_p[cov_ind]] == 0 \
261   - or dct_p[cov_ind] % 64 == 0:
262   - cov_ind += 1
263   - cov_chunk[i] = dct_p[cov_ind]
  246 + # in case k = n = 1, Westfeld's implementation uses F4 for embedding.
  247 + f4 = F4(key=self.key)
  248 + return f4._raw_embed(cov_data, hid_data)
  249 +
  250 + hid_data = bytes2bits(hid_data)
  251 + if len(hid_data) % k != 0:
  252 + hid_data = list(hid_data) + [0 for x in range(k - len(hid_data) % k)]
  253 +
  254 + ind_nonzero = np.nonzero(cov_data)[0]
  255 +
  256 + if np.size(ind_nonzero) * k < len(hid_data) * n:
  257 + raise Exception("Supposed secret data too large for stego image.")
  258 +
  259 + ind_cov = 0
  260 + for ind_hid in range(0, len(hid_data), k):
  261 + msg_chunk = hid_data[ind_hid:ind_hid + k]
  262 + cov_chunk = ind_nonzero[ind_cov:ind_cov + n]
  263 + ind_cov += n
264 264  
265 265 success = False
266   - while not success: # loop necessary because of shrinkage
  266 + while not success:
267 267 h = 0
268 268 for i in xrange(n):
269 269 h ^= ((cov_data[cov_chunk[i]] & 1) * (i + 1))
270 270 scalar_x = 0
271 271 for i in xrange(k):
272   - scalar_x = (scalar_x << 1) + msg_chunk[i]
  272 + scalar_x = (scalar_x << 1) + msg_chunk[
  273 + i] # N.B. hid_data[0]:high (that is x2), hid_data[1]:low (that is x1)
273 274 s = scalar_x ^ h
274 275 if s != 0:
275 276 self._embed_fun(cov_data, cov_chunk[s - 1])
276 277 else:
277 278 break
278 279  
279   - if cov_data[cov_chunk[s - 1]] == 0: # test for shrinkage
280   - cov_chunk[s - 1:-1] = cov_chunk[s:] # adjusting
281   - cov_ind += 1
282   - while cov_data[dct_p[cov_ind]] == 0 or \
283   - dct_p[cov_ind] % 64 == 0:
284   - cov_ind += 1
285   - cov_chunk[n - 1] = dct_p[cov_ind]
  280 + if cov_data[cov_chunk[s - 1]] == 0: # shrinkage
  281 + cov_chunk[s - 1:-1] = cov_chunk[s:]
  282 + cov_chunk[-1] = ind_nonzero[ind_cov]
  283 + ind_cov += 1
286 284 else:
287 285 success = True
288 286  
289   - remaining_bits -= k
290   -
291   - self.k_coeff = -1 # prevent k being read from this instance
292   - return cov_data
  287 + return cov_data, ind_hid + k
293 288  
294   - def _raw_extract(self, num_bits):
  289 + def _raw_extract(self, steg_data, num_bits):
295 290 k = self.k_coeff
296 291 n = (1 << k) - 1
297   - if self.is_header == None:
298   - self.is_header = True
299   - if n == 1 and self.default_embedding:
300   - f4 = F4(self.ui, self.core)
301   - f4.seed = self.seed
302   - f4.dct_p = self.dct_p
303   - f4.steg_data = self.steg_data
304   - f4.is_header = self.is_header
305   - f4.steg_ind = self.steg_ind
306   - hid_data = f4._raw_extract(num_bits)
307   - self.steg_ind = f4.steg_ind
308   - self.is_header = False
309   - return hid_data
310   - remaining_bits = num_bits
311   - hid_data = np.zeros(num_bits, np.uint8)
312   - hid_ind = 0
313   -
314   - dct_p = self.dct_p
315   -
316   - is_header = False # signals whether or not extracting header
317   -
318   - if self.excess_bits != None:
319   - hid_data[hid_ind:hid_ind + self.excess_bits.size] = \
320   - self.excess_bits
321   - hid_ind += self.excess_bits.size
322   - remaining_bits -= self.excess_bits.size
323   -
324   - curr_chunk = np.zeros(k, np.uint8)
325   -
326   - update_cnt = int(num_bits / (100.0 * k))
327   -
328   - while remaining_bits > 0:
329 292  
330   - if update_cnt == 0 and not is_header:
331   - self._set_progress(int(((float(num_bits) \
332   - - remaining_bits) / num_bits) * 100))
333   - update_cnt = int(num_bits / (100.0 * k))
  293 + if n == 1 and self.default_embedding:
  294 + f4 = F4(key=self.key)
  295 + return f4._raw_extract(steg_data, num_bits)
334 296  
335   - update_cnt -= 1
  297 + num_bits_ceil = num_bits
  298 + if num_bits % k != 0:
  299 + num_bits_ceil = k * (num_bits / k + 1)
336 300  
337   - steg_chunk = [0 for i in xrange(n)]
338   - for i in xrange(n):
339   - self.steg_ind += 1
340   - while self.steg_data[dct_p[self.steg_ind]] == 0 or \
341   - dct_p[self.steg_ind] % 64 == 0:
342   - self.steg_ind += 1
343   - steg_chunk[i] = self.steg_data[dct_p[self.steg_ind]]
  301 + hid_data = np.zeros(num_bits_ceil, np.uint8)
  302 + curr_chunk = np.zeros(k, np.uint8)
  303 + steg_data = steg_data[np.nonzero(steg_data)]
  304 + ind_hid = 0
  305 + for ind_cov in range(0, len(steg_data), n):
  306 + steg_chunk = steg_data[ind_cov:ind_cov + n]
344 307  
345 308 h = 0 # hash value
346 309 for i in xrange(n):
347 310 h ^= ((steg_chunk[i] & 1) * (i + 1))
348 311  
349 312 for i in xrange(k):
350   - curr_chunk[k - i - 1] = h % 2
351   - h /= 2
352   -
353   - l = min(k, remaining_bits)
354   - for i in xrange(l):
355   - hid_data[hid_ind] = curr_chunk[i]
356   - hid_ind += 1
  313 + curr_chunk[k - i - 1] = h & 1 # N.B. hid_data[0]:high (that is x2), hid_data[1]:low (that is x1)
  314 + h >>= 1
357 315  
358   - # save excess bits (for later calls)
359   - if k > remaining_bits:
360   - self.excess_bits = curr_chunk[remaining_bits:]
361   - else:
362   - self.excess_bits = None
  316 + hid_data[ind_hid:ind_hid + k] = curr_chunk[0:k]
  317 + ind_hid += k
363 318  
364   - remaining_bits -= k
  319 + if ind_hid >= num_bits_ceil: break
365 320  
366   - self.is_header = False
367   - return hid_data
  321 + return hid_data, num_bits_ceil
368 322  
369 323 def __str__(self):
370 324 return 'F5'
... ...
msteg/steganography/F5.pyc
No preview for this file type
msteg/steganography/LSB.pyc
No preview for this file type
res/steged.jpg

47.5 KB | W: | H:

47.9 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
test_jpeg.py
... ... @@ -17,7 +17,9 @@ sample = [[7, 12, 14, -12, 1, 0, -1, 0],
17 17 [0, 0, 0, 0, 0, 0, 0, 0],
18 18 [0, 0, 0, 0, 0, 0, 0, 0]]
19 19  
20   -sample_key = [46812L, 20559L, 31360L, 16681L, 27536L, 39553L, 5427L, 63029L, 56572L, 36476L, 25695L, 61908L, 63014L, 5908L, 59816L, 56765L]
  20 +sample_key = [46812L, 20559L, 31360L, 16681L, 27536L, 39553L, 5427L, 63029L, 56572L, 36476L, 25695L, 61908L, 63014L,
  21 + 5908L, 59816L, 56765L]
  22 +
21 23  
22 24 def diffblock(c1, c2):
23 25 diff = False
... ... @@ -32,6 +34,7 @@ def diffblock(c1, c2):
32 34  
33 35 def diffblocks(a, b):
34 36 diff = False
  37 + cnt = 0
35 38 for comp in range(a.image_components):
36 39 xmax, ymax = a.Jgetcompdim(comp)
37 40 for y in range(ymax):
... ... @@ -39,7 +42,8 @@ def diffblocks(a, b):
39 42 if a.Jgetblock(x, y, comp) != b.Jgetblock(x, y, comp):
40 43 print("blocks({},{}) in component {} not match".format(y, x, comp))
41 44 diff = True
42   - return diff
  45 + cnt += 1
  46 + return diff, cnt
43 47  
44 48  
45 49 def test_setblocks():
... ... @@ -131,17 +135,18 @@ def test_rawfile():
131 135 raw[i] = raw_size % 256
132 136 raw_size /= 256
133 137 raw = np.array(raw)
134   - print raw.shape,raw
  138 + print raw.shape, raw
135 139 # print raw.size
136 140 # print bytes2bits(raw)
137 141  
  142 +
138 143 def test_bitbyte():
139 144 timer.mark()
140 145 raw = np.fromfile("res/test4.jpg", np.uint8)
141 146 timer.report()
142 147 print raw
143 148  
144   - bitsraw = bytes2bits(raw)
  149 + bitsraw = bytes2bits(raw)
145 150 # bitsraw = bitsraw[:24]
146 151 timer.report()
147 152 print bitsraw
... ... @@ -150,6 +155,7 @@ def test_bitbyte():
150 155 timer.report()
151 156 print bytesraw
152 157  
  158 +
153 159 def test_iter():
154 160 imb = jpegObj.Jpeg("res/test4.jpg")
155 161 blocks = imb.getCoefBlocks(channel='Y')
... ... @@ -186,12 +192,12 @@ if __name__ == &#39;__main__&#39;:
186 192  
187 193 # test_bitbyte()
188 194  
189   - ima = jpegObj.Jpeg("res/test3.jpg",key=sample_key)
  195 + ima = jpegObj.Jpeg("res/test3.jpg", key=sample_key)
190 196 # imb = jpegObj.Jpeg("res/new.jpg",key=sample_key)
191   - imc = jpegObj.Jpeg("res/steged.jpg",key=sample_key)
  197 + imc = jpegObj.Jpeg("res/steged.jpg", key=sample_key)
192 198 print ima.Jgetcompdim(0)
193   - print ima.getkey(),imc.getkey()
194   - diffblocks(ima, imc)
  199 + print ima.getkey(), imc.getkey()
  200 + print diffblocks(ima, imc)
195 201  
196 202 # c1 = ima.getCoefBlocks()
197 203 # c2 = imb.getCoefBlocks()
... ...
test_steg.py
... ... @@ -7,7 +7,7 @@ import pylab as plt
7 7 import mjpeg
8 8 import mjsteg
9 9 import jpegObj
10   -from msteg.steganography import F3, F4, LSB
  10 +from msteg.steganography import LSB, F3, F4, F5
11 11 from common import *
12 12  
13 13  
... ... @@ -22,13 +22,17 @@ sample = [[7, 12, 14, -12, 1, 0, -1, 0],
22 22 [0, 0, 0, 0, 0, 0, 0, 0],
23 23 [0, 0, 0, 0, 0, 0, 0, 0]]
24 24  
25   -sample_key = [46812L, 20559L, 31360L, 16681L, 27536L, 39553L, 5427L, 63029L, 56572L, 36476L, 25695L, 61908L, 63014L, 5908L, 59816L, 56765L]
  25 +sample_key = [46812L, 20559L, 31360L, 16681L, 27536L, 39553L, 5427L, 63029L, 56572L, 36476L, 25695L, 61908L, 63014L,
  26 + 5908L, 59816L, 56765L]
26 27  
27 28 txtsample = [116, 104, 105, 115, 32, 105, 115, 32, 116, 111, 32, 98, 101, 32, 101, 109, 98, 101, 100, 101, 100, 46, 10]
28 29  
29 30 if __name__ == '__main__':
30   - f3test = F4.F4()
  31 + # f3test = F4.F4(sample_key)
  32 + f3test = F5.F5(sample_key, 3)
31 33 f3test.embed_raw_data("res/test3.jpg", "res/embeded", "res/steged.jpg")
  34 +
  35 + # f3test2 = F4.F4(sample_key)
32 36 f3test.extract_raw_data("res/steged.jpg", "res/extracted")
33 37 print f3test.get_key()
34 38 pass
... ...