242 lines
7.3 KiB
Python
242 lines
7.3 KiB
Python
|
# -*- coding: utf-8 -*-
|
|||
|
"""
|
|||
|
Created on Wed Jun 12 09:36:29 2019
|
|||
|
|
|||
|
@author: Administrator
|
|||
|
"""
|
|||
|
|
|||
|
import math
|
|||
|
import numpy as np
|
|||
|
import DCT
|
|||
|
|
|||
|
class Jsteg:
|
|||
|
def __init__(self):
|
|||
|
self.sequence_after_dct=None
|
|||
|
|
|||
|
def set_sequence_after_dct(self,sequence_after_dct):
|
|||
|
self.sequence_after_dct=sequence_after_dct
|
|||
|
self.available_info_len=len([i for i in self.sequence_after_dct if i not in (-1,1,0)]) # 不是绝对可靠的
|
|||
|
print ("Load>> 可嵌入",self.available_info_len,'bits')
|
|||
|
|
|||
|
def get_sequence_after_dct(self):
|
|||
|
return self.sequence_after_dct
|
|||
|
|
|||
|
def write(self,info):
|
|||
|
"""先嵌入信息的长度,然后嵌入信息"""
|
|||
|
info=self._set_info_len(info)
|
|||
|
info_len=len(info)
|
|||
|
info_index=0
|
|||
|
im_index=0
|
|||
|
while True:
|
|||
|
if info_index>=info_len:
|
|||
|
break
|
|||
|
data=info[info_index]
|
|||
|
if self._write(im_index,data):
|
|||
|
info_index+=1
|
|||
|
im_index+=1
|
|||
|
#print(self.sequence_after_dct)
|
|||
|
b={0:0,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,-1:0,-2:0,-3:0,-4:0,-5:0,-6:0,-7:0,-8:0}
|
|||
|
for i in self.sequence_after_dct:
|
|||
|
if i in b:
|
|||
|
b[i]+=1
|
|||
|
print("经过信息隐藏后JPEG的DCT系数变化")
|
|||
|
print(b)
|
|||
|
|
|||
|
def read(self):
|
|||
|
"""先读出信息的长度,然后读出信息"""
|
|||
|
_len,sequence_index=self._get_info_len()
|
|||
|
info=[]
|
|||
|
info_index=0
|
|||
|
|
|||
|
while True:
|
|||
|
if info_index>=_len:
|
|||
|
break
|
|||
|
data=self._read(sequence_index)
|
|||
|
if data!=None:
|
|||
|
info.append(data)
|
|||
|
info_index+=1
|
|||
|
sequence_index+=1
|
|||
|
|
|||
|
return info
|
|||
|
|
|||
|
#===============================================================#
|
|||
|
|
|||
|
def _set_info_len(self,info):
|
|||
|
l=int(math.log(self.available_info_len,2))+1
|
|||
|
info_len=[0]*l
|
|||
|
_len=len(info)
|
|||
|
info_len[-len(bin(_len))+2:]=[int(i) for i in bin(_len)[2:]]
|
|||
|
#print(info_len+info)
|
|||
|
return info_len+info
|
|||
|
|
|||
|
def _get_info_len(self):
|
|||
|
l=int(math.log(self.available_info_len,2))+1
|
|||
|
len_list=[]
|
|||
|
_l_index=0
|
|||
|
_seq_index=0
|
|||
|
while True:
|
|||
|
if _l_index>=l:
|
|||
|
break
|
|||
|
_d=self._read(_seq_index)
|
|||
|
if _d!=None:
|
|||
|
len_list.append(str(_d))
|
|||
|
_l_index+=1
|
|||
|
_seq_index+=1
|
|||
|
_len=''.join(len_list)
|
|||
|
_len=int(_len,2)
|
|||
|
return _len,_seq_index
|
|||
|
|
|||
|
# 注意经过DCT会有负值,此处最低有效位的嵌入方式与空域LSB略有不同
|
|||
|
def _write(self,index,data):
|
|||
|
origin=self.sequence_after_dct[index]
|
|||
|
if origin in (-1,1,0):
|
|||
|
return False
|
|||
|
|
|||
|
lower_bit=origin%2
|
|||
|
if lower_bit==data:
|
|||
|
pass
|
|||
|
elif origin>0:
|
|||
|
if (lower_bit,data) == (0,1):
|
|||
|
self.sequence_after_dct[index]=origin+1
|
|||
|
elif (lower_bit,data) == (1,0):
|
|||
|
self.sequence_after_dct[index]=origin-1
|
|||
|
elif origin<0:
|
|||
|
if (lower_bit,data) == (0,1):
|
|||
|
self.sequence_after_dct[index]=origin-1
|
|||
|
elif (lower_bit,data) == (1,0):
|
|||
|
self.sequence_after_dct[index]=origin+1
|
|||
|
|
|||
|
return True
|
|||
|
|
|||
|
def _read(self,index):
|
|||
|
if self.sequence_after_dct[index] not in (-1,1,0):
|
|||
|
return self.sequence_after_dct[index]%2
|
|||
|
else:
|
|||
|
return None
|
|||
|
|
|||
|
|
|||
|
class F3(Jsteg):
|
|||
|
def __init__(self):
|
|||
|
Jsteg.__init__(self)
|
|||
|
|
|||
|
def set_sequence_after_dct(self,sequence_after_dct):
|
|||
|
self.sequence_after_dct=sequence_after_dct
|
|||
|
sum_len=len(self.sequence_after_dct)
|
|||
|
zero_len=len([i for i in self.sequence_after_dct if i==0])
|
|||
|
one_len=len([i for i in self.sequence_after_dct if i in (-1,1)])
|
|||
|
self.available_info_len=sum_len-zero_len-one_len # 不是特别可靠
|
|||
|
print ("Load>> 大约可嵌入",sum_len-zero_len-int(one_len/2),'bits')
|
|||
|
print ("Load>> 最少可嵌入",self.available_info_len,'bits\n')
|
|||
|
|
|||
|
def _write(self,index,data):
|
|||
|
origin=self.sequence_after_dct[index]
|
|||
|
if origin == 0:
|
|||
|
return False
|
|||
|
elif origin in (-1,1) and data==0:
|
|||
|
self.sequence_after_dct[index]=0
|
|||
|
return False
|
|||
|
|
|||
|
lower_bit=origin%2
|
|||
|
|
|||
|
if lower_bit==data:
|
|||
|
pass
|
|||
|
elif origin>0:
|
|||
|
self.sequence_after_dct[index]=origin-1
|
|||
|
elif origin<0:
|
|||
|
self.sequence_after_dct[index]=origin+1
|
|||
|
return True
|
|||
|
|
|||
|
def _read(self,index):
|
|||
|
if self.sequence_after_dct[index] != 0:
|
|||
|
return self.sequence_after_dct[index]%2
|
|||
|
else:
|
|||
|
return None
|
|||
|
|
|||
|
|
|||
|
class F4(Jsteg):
|
|||
|
def __init__(self):
|
|||
|
Jsteg.__init__(self)
|
|||
|
|
|||
|
def set_sequence_after_dct(self,sequence_after_dct):
|
|||
|
self.sequence_after_dct=sequence_after_dct
|
|||
|
sum_len=len(self.sequence_after_dct)
|
|||
|
zero_len=len([i for i in self.sequence_after_dct if i==0])
|
|||
|
one_len=len([i for i in self.sequence_after_dct if i in (-1,1)])
|
|||
|
self.available_info_len=sum_len-zero_len-one_len # 不是特别可靠
|
|||
|
print ("Load>> 大约可嵌入",sum_len-zero_len-int(one_len/2),'bits')
|
|||
|
print ("Load>> 最少可嵌入",self.available_info_len,'bits\n')
|
|||
|
|
|||
|
def _write(self,index,data):
|
|||
|
origin=self.sequence_after_dct[index]
|
|||
|
if origin == 0:
|
|||
|
return False
|
|||
|
elif origin == 1 and data==0:
|
|||
|
self.sequence_after_dct[index]=0
|
|||
|
return False
|
|||
|
|
|||
|
elif origin == -1 and data==1:
|
|||
|
self.sequence_after_dct[index]=0
|
|||
|
return False
|
|||
|
|
|||
|
lower_bit=origin%2
|
|||
|
|
|||
|
if origin >0:
|
|||
|
if lower_bit!=data:
|
|||
|
self.sequence_after_dct[index]=origin-1
|
|||
|
else:
|
|||
|
if lower_bit==data:
|
|||
|
self.sequence_after_dct[index]=origin+1
|
|||
|
return True
|
|||
|
|
|||
|
|
|||
|
def _read(self,index):
|
|||
|
if self.sequence_after_dct[index] >0:
|
|||
|
return self.sequence_after_dct[index]%2
|
|||
|
elif self.sequence_after_dct[index]<0:
|
|||
|
return (self.sequence_after_dct[index]+1)%2
|
|||
|
else:
|
|||
|
return None
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
if __name__=="__main__":
|
|||
|
jsteg=Jsteg()
|
|||
|
f3=F3()
|
|||
|
f4=F4()
|
|||
|
# 写
|
|||
|
sequence_after_dct=DCT.after_dct
|
|||
|
jsteg.set_sequence_after_dct(sequence_after_dct)
|
|||
|
f3.set_sequence_after_dct(sequence_after_dct)
|
|||
|
f4.set_sequence_after_dct(sequence_after_dct)
|
|||
|
a={0:0,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,-1:0,-2:0,-3:0,-4:0,-5:0,-6:0,-7:0,-8:0}
|
|||
|
for i in sequence_after_dct:
|
|||
|
if i in a:
|
|||
|
a[i]+=1
|
|||
|
print("JPEG的DCT系数")
|
|||
|
print(a)
|
|||
|
info1=[int(i+0.5) for i in np.random.rand(200000)]
|
|||
|
|
|||
|
print("Jsteg begin writing!")
|
|||
|
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
|
|||
|
jsteg.write(info1)
|
|||
|
|
|||
|
print("F3steg begin writing!")
|
|||
|
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
|
|||
|
f3.write(info1)
|
|||
|
print("F4steg begin writing!")
|
|||
|
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
|
|||
|
f4.write(info1)
|
|||
|
'''
|
|||
|
# 读
|
|||
|
sequence_after_dct2=jsteg.get_sequence_after_dct()
|
|||
|
sequence_after_dct3=f3.get_sequence_after_dct()
|
|||
|
sequence_after_dct4=f4.get_sequence_after_dct()
|
|||
|
jsteg.set_sequence_after_dct(sequence_after_dct2)
|
|||
|
f3.set_sequence_after_dct(sequence_after_dct3)
|
|||
|
f4.set_sequence_after_dct(sequence_after_dct4)
|
|||
|
info2=jsteg.read()
|
|||
|
info3=f3.read()
|
|||
|
info4=f4.read()
|
|||
|
'''
|