├── .gitignore ├── Adjust.m ├── Adjustment.m ├── Calcu.m ├── Chg2bin.m ├── Dec2bin.m ├── Decode.m ├── Embed1.m ├── Embedding.m ├── Encipher.m ├── Encode.m ├── Extraction.m ├── Generate.m ├── Get.m ├── Insert.m ├── Put.m ├── README.md ├── Recover.m ├── Recovery.m ├── Room.m ├── SaveSpace.m ├── Select.m ├── apple.m ├── distsub_est_M.m ├── evaluate.m ├── expansion.m ├── gray.m ├── hist.m ├── ifcvec.m ├── img2gray.m ├── ind2wtree.m ├── jpg2png.m ├── main.m ├── main.py ├── multi.m ├── original.png ├── plant.m ├── refparams_vecgsm.m ├── reserve.m ├── resize.m ├── sub.m ├── test2.m ├── thumbnail.m └── trans.m /.gitignore: -------------------------------------------------------------------------------- 1 | *.asv 2 | test.* 3 | *.pptx 4 | *.docx 5 | *.jpg 6 | *.eps 7 | *.pdf 8 | *.png 9 | *.tmp 10 | *.txt 11 | !original.png 12 | setting.code-workspace 13 | -------------------------------------------------------------------------------- /Adjust.m: -------------------------------------------------------------------------------- 1 | %file: Adjust.m 2 | %to adjust the MSB of pixel in adjustment area in order to keep the Thumbnail the same 3 | %origin: the image after saving space and encipher progress 4 | %(x,y): the start location of block 5 | %value: store the average pixel in every block of the original image 6 | %MSB: the number of every bit in adjustment area used for adjustment 7 | function [AjImage,success] = Adjust(origin,blocksize,x,y,MSB,value) 8 | 9 | %first: calculate the low (8-MSB) bit of all pixel --> sum 10 | %store the all adjustment area location in locationx and locationy 11 | AjImage = origin; 12 | success = 1; 13 | locationx = []; 14 | locationy = []; 15 | len = 1; 16 | success=0; 17 | locationx(len:len+blocksize-1) = x:x+blocksize-1; 18 | locationy(len:len+blocksize-1) = y; 19 | len = len+blocksize; 20 | locationx(len:len+blocksize-1) = x:x+blocksize-1; 21 | locationy(len:len+blocksize-1) = y+blocksize-1; 22 | len = len+blocksize; 23 | locationx(len:len+blocksize-3) = x; 24 | locationy(len:len+blocksize-3) = y+1:y+blocksize-2; 25 | len = len+blocksize-2; 26 | locationx(len:len+blocksize-3) = x+blocksize-1; 27 | locationy(len:len+blocksize-3) = y+1:y+blocksize-2; 28 | len = len+blocksize-3; 29 | sub = origin(x+1:x+blocksize-2,y+1:y+blocksize-2); 30 | Sum = double(sum(sub(:))); 31 | for i = 1 : len 32 | t = Calcu(origin(locationx(i),locationy(i)),MSB); 33 | Sum = Sum+double(t); 34 | end 35 | [~,limit] = size(locationx); 36 | for i = 1 : limit 37 | AjImage(locationx(i),locationy(i)) = Calcu(origin(locationx(i),locationy(i)),MSB); 38 | end 39 | diff = blocksize*blocksize*value - Sum; 40 | if diff < 0 41 | return ; 42 | end 43 | number = Generate(MSB); 44 | [~,count] = size(number); 45 | chan = zeros(1,count); 46 | for i = 1 : count 47 | res = floor(diff / number(i)); 48 | if res > limit 49 | res = limit; 50 | end 51 | chan(i) = res; 52 | diff = diff - res * number(i); 53 | if diff < 0 54 | break; 55 | end 56 | end 57 | 58 | for j = 1 : count 59 | for i = 1 : chan(j) 60 | AjImage(locationx(i),locationy(i)); 61 | AjImage(locationx(i),locationy(i)) = AjImage(locationx(i),locationy(i)) + number(j); 62 | AjImage(locationx(i),locationy(i)); 63 | end 64 | end 65 | sub = AjImage(x:x+blocksize-1,y:y+blocksize-1); 66 | s = double(sum(sub(:))); 67 | difference = abs(s-blocksize*blocksize*value); 68 | end 69 | 70 | 71 | % %second: calculate the difference between 'current' and blocksize*blocksize*value 72 | % number = Generate(MSB); 73 | % difference = blocksize*blocksize*value-Sum %generally the former must bigger than the later 74 | % 75 | % %third: search to find the perfect result 76 | % if difference 0 7 | bits = dec2bin(number); 8 | elseif number == 0 9 | bits = '0'; 10 | else 11 | bit = Get(bit,-number,8); 12 | for i = 1 : 8 13 | if bit(i) == 0 14 | bits(i) = '1'; 15 | else 16 | bits(i) = '0'; 17 | end 18 | end 19 | bit = bin2dec(bits); 20 | bits= dec2bin(bit+1); 21 | end 22 | end -------------------------------------------------------------------------------- /Decode.m: -------------------------------------------------------------------------------- 1 | %file:Decode.m 2 | %to decoding the encoded message 3 | function res = Decode( data , blocksize, MSB) 4 | 5 | [~,length] = size(data); 6 | i = uint16(1);%the index of data 7 | res = []; 8 | sum = 0;%store the sum of num in order to judge the end of the locate-map 9 | j = uint16(1);%index of res 10 | while sum < ((blocksize-2)*(blocksize-2))/2 %locate-map 11 | num = uint16(data(i)*64+data(i+1)*32+data(i+2)*16+data(i+3)*8+data(i+4)*4+data(i+5)*2+data(i+6));%calculate the number 12 | sum = sum+num; 13 | res(j:j+num-1) = data(i+7); 14 | i = i+8; 15 | j = j+num; 16 | end 17 | bit = []; 18 | sum = 0; 19 | p = uint16(length); 20 | q = 1; 21 | while sum < MSB*(4*blocksize-4) %MSB of the adjustment area 22 | num = data(p-1)+data(p-2)*2+data(p-3)*4+data(p-4)*8+data(p-5)*16+data(p-6)*32+data(p-7)*64; 23 | sum = sum+num; 24 | bit(q:q+num-1) = data(p); 25 | p = p-8; 26 | q = q+num; 27 | end 28 | bit = fliplr(bit); 29 | % bits = bit; 30 | if MSB == 1 31 | bits=bit; 32 | end 33 | if MSB == 2 34 | a = 4*blocksize-4; 35 | bits(1:2:2*a-1) = bit(1:a); 36 | bits(2:2:2*a) = bit(a+1:2*a); 37 | end 38 | if MSB == 3 39 | a = 4*blocksize-4; 40 | bits(1:3:3*a-2) = bit(1:a); 41 | bits(2:3:3*a-1) = bit(a+1:2*a); 42 | bits(3:3:3*a) = bit(2*a+1:3*a); 43 | end 44 | [~,n] = size(bits); 45 | if i<=p 46 | res(j:j+p-i) = data(i:p); 47 | end 48 | [~,len] = size(res); 49 | res(len+1:len+n) = bits(1:n); 50 | 51 | end -------------------------------------------------------------------------------- /Embed1.m: -------------------------------------------------------------------------------- 1 | %file:Embedding.m 2 | %origin: the original image blocksize: the size of block 3 | %x,y: the start location of block 4 | %MSB: the number of every bit in adjustment area used for adjustment 5 | %count: the max number of elements in EN1 6 | function [data,SubImage,capacity] = Embedding( origin, blocksize, x, y, MSB, count, bits) 7 | SubImage=origin; 8 | capacity = 0; 9 | %select the highest MSB bits of each pixel in adjustment area 10 | 11 | %1-divide all pixel into different sets: EZ & EN1 & EN2 & CN & NC 12 | %2-generate the lacation-map MAP 13 | %3-store the lowest bit of each pixel in EN2 and CN 14 | %EZ: h=0 || h=-1 used as expandable 15 | %EN1: expandable and used as expandable 16 | %EN2: expandable but used as changable 17 | %CN: changable and used as changable 18 | %NC: not changable and never use 19 | SORT = zeros(blocksize,blocksize);%to store the kind of the pixel NC: 0; EZ&EN1: 1; EN2&CN: 2; 20 | MAP = zeros(blocksize-2,(blocksize-2)/2);%MAP: store the location map to tell which pixel used as expandable 21 | LSB = [];%LSB: store the lowest bit of each pixel used as changable 22 | sum = 0; %calculate the number of elements in EN1 at present 23 | num = 0; %store the size of P 24 | for i = x+1 : 1 : x+blocksize-2 25 | for j = y+1 : 2 : y+blocksize-2 26 | l = floor(double(uint16(origin(i,j))+uint16(origin(i,j+1)))/2); 27 | h = double(double(origin(i,j))-double(origin(i,j+1))); 28 | min = 2*(255-l); 29 | b = 2*l+1; 30 | if( b < min ) 31 | min = b; 32 | end 33 | if h==0 || h==-1 34 | SORT(i-x,j-y) = 1; 35 | MAP(i-x,floor((j-y+1)/2)) = 1; 36 | elseif abs(2*h+1) < min 37 | if sum < count 38 | SORT(i-x,j-y) = 1; 39 | MAP(i-x,floor((j-y+1)/2)) = 1; 40 | sum = sum+1; 41 | else 42 | SORT(i-x,j-y) = 2; 43 | t = Dec2bin(h); 44 | if h~=1 && h~=-2 45 | num=num+1; 46 | [~,len]=size(t); 47 | LSB(num) = t(len)-'0'; 48 | end 49 | end 50 | elseif abs(2*floor(h/2)+1) < min 51 | SORT(i-x,j-y) = 2; 52 | t = Dec2bin(h); 53 | if h~=1 && h~=-2 %as such value could br determined by location map 54 | num=num+1; 55 | [~,len]=size(t); 56 | LSB(num) = t(len)-'0'; 57 | end 58 | end 59 | end 60 | end 61 | %encoding the MAP into L (using 01111110 as the ending of the data) 62 | %when meet five and more than five '1' ,use 0 in the ending of '11111' 63 | L = []; 64 | MAP=MAP'; 65 | MAP=MAP(:); 66 | MAP=MAP'; %to change the MAP to unidimensional matrix 67 | 68 | %embedding bit in L & LSB $ bits into embedding area: EZ & EN1 & EN2 & CN 69 | %in EZ & EN1: the h`=2*h+bit 70 | %in EN2 & CN: the h`=2*(h/2)+bit 71 | %l=(x+y)/2 h=x-y (as x and y are two pixel's value) 72 | %x`=l+(h`+1)/2 y`=l-(h`)/2 73 | %if there are more than len bits spare space, we embed 01111...1 in the end 74 | data=[]; 75 | MAP = Encode(MAP); 76 | [~,len1] = size(MAP); 77 | data(1:len1) = MAP(1:len1); 78 | [~,len2] = size(LSB); 79 | data(len1+1:len1+len2) = LSB(1:len2); 80 | 81 | no=1; %means the index of data to embed 82 | 83 | for i = x+1 : 1 : x+blocksize-2 84 | for j = y+1 : 2 : y+blocksize-2 85 | if SORT(i-x,j-y) == 0 86 | continue; 87 | end 88 | l = floor(double(uint16(origin(i,j))+uint16(origin(i,j+1)))/2); 89 | h = double(double(origin(i,j))-double(origin(i,j+1))); 90 | if SORT(i-x,j-y) == 1 %expandable 91 | hh = 2*h; 92 | capacity = capacity+1; 93 | elseif SORT(i-x,j-y) == 2 %changable 94 | hh = 2*floor(h/2); 95 | capacity = capacity+1; 96 | else 97 | hh = h; 98 | end 99 | no = no+1; 100 | SubImage(i,j) = uint8(l+floor((hh+1)/2)); 101 | SubImage(i,j+1) = uint8(l-floor(hh/2)); 102 | end 103 | end 104 | 105 | 106 | end -------------------------------------------------------------------------------- /Embedding.m: -------------------------------------------------------------------------------- 1 | %file:Embedding.m 2 | %origin: the original image blocksize: the size of block 3 | %x,y: the start location of block 4 | %MSB: the number of every bit in adjustment area used for adjustment 5 | %count: the max number of elements in EN1 6 | function [data,SubImage,capacity] = Embedding( origin, blocksize, x, y, MSB, count) 7 | SubImage=origin; 8 | capacity = 0; 9 | %select the highest MSB bits of each pixel in adjustment area 10 | bits = []; %store the highest MSB bits of pixels in adjustment area 11 | bit = []; 12 | for i = x : x+blocksize-1 13 | bit = Get(bit,origin(i,y),MSB); 14 | end 15 | for i = x : x+blocksize-1 16 | bit = Get(bit,origin(i,y+blocksize-1),MSB); 17 | end 18 | for j = y+1 : y+blocksize-2 19 | bit = Get(bit,origin(x,j),MSB); 20 | end 21 | for j = y+1 : y+blocksize-2 22 | bit = Get(bit,origin(x+blocksize-1,j),MSB); 23 | end 24 | if MSB == 1 25 | bits=bit; 26 | end 27 | if MSB == 2 28 | a = 4*blocksize-4; 29 | bits(1:a) = bit(1:2:2*a-1); 30 | bits(a+1:2*a) = bit(2:2:2*a); 31 | end 32 | if MSB == 3 33 | a = 4*blocksize-4; 34 | bits(1:a) = bit(1:3:3*a-2); 35 | bits(a+1:2*a) = bit(2:3:3*a-1); 36 | bits(2*a+1:3*a) = bit(3:3:3*a); 37 | end 38 | %1-divide all pixel into different sets: EZ & EN1 & EN2 & CN & NC 39 | %2-generate the lacation-map MAP 40 | %3-store the lowest bit of each pixel in EN2 and CN 41 | %EZ: h=0 || h=-1 used as expandable 42 | %EN1: expandable and used as expandable 43 | %EN2: expandable but used as changable 44 | %CN: changable and used as changable 45 | %NC: not changable and never use 46 | SORT = zeros(blocksize,blocksize);%to store the kind of the pixel NC: 0; EZ&EN1: 1; EN2&CN: 2; 47 | MAP = zeros(blocksize-2,(blocksize-2)/2);%MAP: store the location map to tell which pixel used as expandable 48 | LSB = [];%LSB: store the lowest bit of each pixel used as changable 49 | sum = 0; %calculate the number of elements in EN1 at present 50 | num = 0; %store the size of P 51 | for i = x+1 : 1 : x+blocksize-2 52 | for j = y+1 : 2 : y+blocksize-2 53 | l = floor(double(uint16(origin(i,j))+uint16(origin(i,j+1)))/2); 54 | h = double(double(origin(i,j))-double(origin(i,j+1))); 55 | min = 2*(255-l); 56 | b = 2*l+1; 57 | if( b < min ) 58 | min = b; 59 | end 60 | if h==0 || h==-1 61 | SORT(i-x,j-y) = 1; 62 | MAP(i-x,floor((j-y+1)/2)) = 1; 63 | elseif abs(2*h+1) < min 64 | if sum < count 65 | SORT(i-x,j-y) = 1; 66 | MAP(i-x,floor((j-y+1)/2)) = 1; 67 | sum = sum+1; 68 | else 69 | SORT(i-x,j-y) = 2; 70 | t = Dec2bin(h); 71 | if h~=1 && h~=-2 72 | num=num+1; 73 | [~,len]=size(t); 74 | LSB(num) = t(len)-'0'; 75 | end 76 | end 77 | elseif abs(2*floor(h/2)+1) < min 78 | SORT(i-x,j-y) = 2; 79 | t = Dec2bin(h); 80 | if h~=1 && h~=-2 %as such value could br determined by location map 81 | num=num+1; 82 | [~,len]=size(t); 83 | LSB(num) = t(len)-'0'; 84 | end 85 | end 86 | end 87 | end 88 | %encoding the MAP into L (using 01111110 as the ending of the data) 89 | %when meet five and more than five '1' ,use 0 in the ending of '11111' 90 | L = []; 91 | MAP=MAP'; 92 | MAP=MAP(:); 93 | MAP=MAP'; %to change the MAP to unidimensional matrix 94 | 95 | %embedding bit in L & LSB $ bits into embedding area: EZ & EN1 & EN2 & CN 96 | %in EZ & EN1: the h`=2*h+bit 97 | %in EN2 & CN: the h`=2*(h/2)+bit 98 | %l=(x+y)/2 h=x-y (as x and y are two pixel's value) 99 | %x`=l+(h`+1)/2 y`=l-(h`)/2 100 | %if there are more than len bits spare space, we embed 01111...1 in the end 101 | data=[]; 102 | MAP = Encode(MAP); 103 | [~,len1] = size(MAP); 104 | data(1:len1) = MAP(1:len1); 105 | [~,len2] = size(LSB); 106 | data(len1+1:len1+len2) = LSB(1:len2); 107 | bits = Encode(bits); 108 | [~,len3] = size(bits); 109 | data(len1+len2+1:len1+len2+len3) = bits(1:len3); 110 | no=1; %means the index of data to embed 111 | 112 | for i = x+1 : 1 : x+blocksize-2 113 | for j = y+1 : 2 : y+blocksize-2 114 | if SORT(i-x,j-y) == 0 115 | continue; 116 | end 117 | l = floor(double(uint16(origin(i,j))+uint16(origin(i,j+1)))/2); 118 | h = double(double(origin(i,j))-double(origin(i,j+1))); 119 | if SORT(i-x,j-y) == 1 %expandable 120 | hh = 2*h; 121 | capacity = capacity+1; 122 | elseif SORT(i-x,j-y) == 2 %changable 123 | hh = 2*floor(h/2); 124 | capacity = capacity+1; 125 | else 126 | hh = h; 127 | end 128 | no = no+1; 129 | SubImage(i,j) = uint8(l+floor((hh+1)/2)); 130 | SubImage(i,j+1) = uint8(l-floor(hh/2)); 131 | end 132 | end 133 | 134 | 135 | end -------------------------------------------------------------------------------- /Encipher.m: -------------------------------------------------------------------------------- 1 | %file: Encipher.m 2 | %to encipher the image after the saving space progress 3 | %origin: the image after saving space progress 4 | %key: the sub key to generate the stream key to encipher 5 | %using key expansion function 6 | function EnImage = Encipher( origin , key ) 7 | 8 | [M,N] = size(origin); 9 | rng('default'); 10 | rng(key); 11 | stream = uint8(randi(256,M,N)-1); 12 | x = size(stream); 13 | EnImage = bitxor(origin,stream); 14 | 15 | end -------------------------------------------------------------------------------- /Encode.m: -------------------------------------------------------------------------------- 1 | %file: Encode.m 2 | %using run-length code to compress the embedded message 3 | function res = Encode( data ) 4 | 5 | [~,length] = size(data); 6 | i = 1;%the index of data 7 | count = 0;%to store the number of '0' or '1' 8 | res = [];%store the compression result, every progress result in one byte and the LSB is the type of number counted('0' or '1') 9 | l = 1;%index of res 10 | flag = 0;%means the number now to calculate is '0' 11 | while i <= length 12 | if data(i)==0 13 | while i<=length && data(i)==0 && count<127 %calculate the number of '0' 14 | count = count+1; 15 | i = i+1; 16 | end 17 | flag = 0; 18 | elseif data(i)==1 19 | while i<=length && data(i)==1 && count<127 %calculate the number of '0' 20 | count = count+1; 21 | i = i+1; 22 | end 23 | flag = 1; 24 | end 25 | t = Chg2bin(count); 26 | res(l:l+6) = t(1:7); 27 | res(l+7) = flag; 28 | l = l+8; 29 | count = 0; 30 | end 31 | 32 | 33 | end -------------------------------------------------------------------------------- /Extraction.m: -------------------------------------------------------------------------------- 1 | %file: Extration.m 2 | % to extrate the message the is embedded (MSB of pixel in adjustment area) 3 | %origin: the image after decipher 4 | %blocksize: the size of block 5 | %x,y: the start location of block 6 | %MSB: the number of every bit in adjustment area used for adjustment 7 | function ExImage = Extraction( origin, blocksize, x, y, MSB ,data ) 8 | 9 | ExImage = origin; 10 | 11 | %decode the message 'data' 12 | %flag means the end of the locate-map 13 | data = Decode(data,blocksize,MSB); 14 | flag = (blocksize-2)*(blocksize-2)/2; 15 | MAP(1:flag) = data(1:flag); 16 | 17 | %recover the embedding area to original area before embedding 18 | infono = flag+1;%the index of LSB 19 | count=0; 20 | for i = x+1: 1 : x+blocksize-2 21 | for j = y+1: 2 : y+blocksize-2 22 | l = floor(double(uint16(origin(i,j))+uint16(origin(i,j+1)))/2); 23 | hh = double(double(origin(i,j))-double(origin(i,j+1))); 24 | t = (i-x-1)*((blocksize-2)/2)+(j-y+1)/2; 25 | min = 2*(255-l); 26 | b = 2*l+1; 27 | if( b < min ) 28 | min = b; 29 | end 30 | if abs(2*floor(hh/2)+1)1,则将每个像素的同一位一起保存,例如将每个像素的最高位收集在一起,然后将次高位收集存在所有最高位之后) 28 | - 将locate-map以及MSB部分进行游程编码来进行压缩 29 | - 整合为块嵌入数据: data = Encode(locate-map) + LSB + Encode(MSB) 30 | 4. 进行预备工作 31 | - 对于可拓展像素组 32 | - h' = 2*h 33 | - 对于可变像素组 34 | - h' = 2*[h/2] 35 | - x' = l+[(h'+1)/2] 36 | - y' = l-[h'/2] 37 | #### 对图像整体进行处理 38 | 5. 整合待嵌入数据 39 | - 对块内得到的数据信息进行编码,这里采用的是当遇到连续8个‘1’时,在后面加上‘0’ 40 | - 对块与块数据之间插入分隔符‘01111111110’用于区别 41 | 6. 对图像整体进行数据嵌入 42 | - 通过判断 |2*[h/2]+b| 与 min(2(255-l),2l+1) 之间的关系,从而对每组像素进行分类 43 | - CH :|2*[h/2]+b| <= min(2(255-l), 2l+1 即可变集合 44 | - NC :不可变区 45 | - 对于可变像素组 46 | - h' = h+b (b为待嵌入比特) 47 | - 若数据已经嵌入完成,则不再进行嵌入操作 48 | - x' = l+[(h'+1)/2] 49 | - y' = l-[h'/2] 50 | ### 二.加密 51 | - 此处用简单的流加密方式进行加密,当然可以采用更安全的加密方式(包括会改变像素位置的加密方式,但一定要记录可调整区像素位置用于调整) 52 | ### 三.调整 53 | - 通过不断改变调整区像素的MSB,找出所有可能中最接近于原图像块平均像素的一组数据(即遍历查找) 54 | ### 四.解密 55 | - 此处和加密一致,直接将加密过程用于解密即可 56 | ### 五.提取 57 | #### 对图像整体进行处理 58 | 1. 将嵌入区的像素组分类 59 | - 两个像素一组 60 | - 计算两个像素之间的平均值以及差值 61 | - l = [x+y]/2 62 | - hh = x-y 63 | - 通过判断 |2*[h/2]+b| 与 min(2(255-l),2l+1) 之间的关系,从而对每组像素进行分类 64 | - CH :|2*[h/2]+b| <= min(2(255-l), 2l+1 即可变集合 65 | - NC :不可变区 66 | 2. 可变集合CH中的hh的LSB位即为嵌入的信息 67 | 3. 对提取的信息进行解码,并根据分隔符将整体嵌入信息分解为各个块的嵌入信息 68 | #### 对块进行处理 69 | 4. 计算出嵌入信息各组成部分压缩前的大小 70 | - locate-map:(blocksize-2)*(blocksize-2)/2 71 | - MSB:blocksize*4-4 72 | - LSB:size(data) - size(locate-map) - size(MSB) 73 | 5. 对经过压缩的嵌入数据进行还原 74 | - 从data的首部开始:边还原MAP边对已经还原的MAP元素个数进行计算,当达到locate-map原大小时停止 75 | - 从data的尾部开始:边还原MSB边对已经还原的MSB元素个数进行计算,当达到MSB原大小时停止 76 | - 两部分中间的即为LSB部分 77 | 6. 将嵌入区的像素组分类 78 | - 两个像素一组 79 | - 计算两个像素之间的平均值以及差值 80 | - l = [x+y]/2 81 | - hh = x-y 82 | - 通过判断 |2*[h/2]+b| 与 min(2(255-l),2l+1) 之间的关系,从而对每组像素进行分类 83 | - CH :|2*[h/2]+b| <= min(2(255-l), 2l+1 即可变集合 84 | - NC :不可变区 85 | 7. 对可变区的像素进行还原 86 | - 对于属于EZ & EN1的像素组(即locate-map中值为1): h = [hh/2] 87 | - 0 <= hh <= 1: h = 1 88 | - 12 <= hh <= -1: h = -2 89 | - else: h = 2*[hh/2]+LSB 90 | - x = l+[(h+1)/2] 91 | - y = l-[h/2] 92 | 8. 对调整区像素进行还原 93 | - pixel = pixel(8-MSB)+MSB -------------------------------------------------------------------------------- /Recover.m: -------------------------------------------------------------------------------- 1 | %file: Recovery.m 2 | %to recover the image 3 | %origin: the image after decipher progress 4 | %blocksize: size of block 5 | %MSB: the number of every bit in adjustment area used for adjustment 6 | function ReImage = Recover( origin , blocksize , MSB ) 7 | 8 | ReImage = origin; 9 | [M,N] = size(origin); 10 | m = M/blocksize; 11 | n = N/blocksize; 12 | %divide all pixel into two different sets: CH & NC 13 | %(whether it is changable) 14 | %CH: EZ & EN & CN --- changable 15 | %NC: not changable 16 | DATA = zeros(1,((blocksize-2)*(blocksize-2))/2*m*n);%store the embedded message 17 | no = 0; %means the number of elements in data 18 | for i = 1 : m 19 | for j = 1 : n 20 | x = (i-1)*blocksize+1; 21 | y = (j-1)*blocksize+1; 22 | 23 | for p = x+1 : 1 : x+blocksize-2 24 | for q = y+1 : 2 : y+blocksize-2 25 | l = floor((origin(p,q)+origin(p,q+1))/2); 26 | h = double(double(origin(p,q))-double(origin(p,q+1))); 27 | min = 2*(255-l); 28 | b = 2*l+1; 29 | if b < min 30 | min = b; 31 | end 32 | if abs(2*floor(h/2)+1) < min %changable 33 | no = no+1; 34 | a = Dec2bin(h); 35 | [~,len] = size(a); 36 | DATA(no) = a(len)-'0'; %the lowest of h is the embedded message 37 | end 38 | end 39 | end 40 | end 41 | end 42 | 43 | 44 | %calculate every block's data according to the DATA 45 | board =zeros(1,m*n); 46 | mess = zeros(1,((blocksize-2)*(blocksize-2))/2*m*n); 47 | j = 1;%index of board 48 | i = 1;%index of DATA 49 | no = 1;%index of mess 50 | temp = [1,1,1,1,1,1,1,1,0]; 51 | ending = [0,1,1,1,1,1,1,1,1,1,0]; 52 | 53 | while j <= m*n 54 | if DATA(i:i+10) == ending(1:11) 55 | board(j) = no-1; 56 | j = j+1; 57 | i = i+11; 58 | elseif DATA(i:i+8) == temp(1:9) 59 | mess(no:no+7) = temp(1:8); 60 | no = no+8; 61 | i = i+9; 62 | else 63 | mess(no) = DATA(i); 64 | no = no+1; 65 | i = i+1; 66 | end 67 | end 68 | 69 | b = 0; 70 | for i = 1 : m 71 | for j = 1 : n 72 | data = []; 73 | x = (i-1)*blocksize+1; 74 | y = (j-1)*blocksize+1; 75 | t = (i-1)*m+j; 76 | a = uint32(board(t)); 77 | if t > 1 78 | b = uint32(board(t-1)); 79 | end 80 | data(1:a-b) = mess(b+1:a); 81 | ReImage = Extraction(ReImage,blocksize,x,y,MSB,data); 82 | end 83 | end 84 | 85 | 86 | end -------------------------------------------------------------------------------- /Recovery.m: -------------------------------------------------------------------------------- 1 | %file: Recovery.m 2 | %to recover the image 3 | %origin: the image after decipher progress 4 | %blocksize: size of block 5 | %MSB: the number of every bit in adjustment area used for adjustment 6 | function ReImage = Recovery( origin , blocksize , MSB ) 7 | 8 | ReImage = origin; 9 | [M,N] = size(origin); 10 | m = M/blocksize; 11 | n = N/blocksize; 12 | %divide all pixel into two different sets: CH & NC 13 | %(whether it is changable) 14 | %CH: EZ & EN & CN --- changable 15 | %NC: not changable 16 | DATA = zeros(1,((blocksize-2)*(blocksize-2))/2*m*n);%store the embedded message 17 | no = 0; %means the number of elements in data 18 | for i = 1 : m 19 | for j = 1 : n 20 | x = (i-1)*blocksize+1; 21 | y = (j-1)*blocksize+1; 22 | 23 | for p = x+1 : 1 : x+blocksize-2 24 | for q = y+1 : 2 : y+blocksize-2 25 | l = floor((origin(p,q)+origin(p,q+1))/2); 26 | h = double(double(origin(p,q))-double(origin(p,q+1))); 27 | min = 2*(255-l); 28 | b = 2*l+1; 29 | if b < min 30 | min = b; 31 | end 32 | if abs(2*floor(h/2)+1) < min %changable 33 | no = no+1; 34 | a = Dec2bin(h); 35 | [~,len] = size(a); 36 | DATA(no) = a(len)-'0'; %the lowest of h is the embedded message 37 | end 38 | end 39 | end 40 | end 41 | end 42 | 43 | 44 | %calculate every block's data according to the DATA 45 | board =zeros(1,m*n); 46 | mess = zeros(1,((blocksize-2)*(blocksize-2))/2*m*n); 47 | j = 1;%index of board 48 | i = 1;%index of DATA 49 | no = 1;%index of mess 50 | temp = [1,1,1,1,1,1,1,1,0]; 51 | ending = [0,1,1,1,1,1,1,1,1,1,0]; 52 | 53 | while j <= m*n 54 | if DATA(i:i+10) == ending(1:11) 55 | board(j) = no-1; 56 | j = j+1; 57 | i = i+11; 58 | elseif DATA(i:i+8) == temp(1:9) 59 | mess(no:no+7) = temp(1:8); 60 | no = no+8; 61 | i = i+9; 62 | else 63 | mess(no) = DATA(i); 64 | no = no+1; 65 | i = i+1; 66 | end 67 | end 68 | 69 | b = 0; 70 | for i = 1 : m 71 | for j = 1 : n 72 | data = []; 73 | x = (i-1)*blocksize+1; 74 | y = (j-1)*blocksize+1; 75 | t = (i-1)*m+j; 76 | a = uint32(board(t)); 77 | if t > 1 78 | b = uint32(board(t-1)); 79 | end 80 | data(1:a-b) = mess(b+1:a); 81 | ReImage = Extraction(ReImage,blocksize,x,y,MSB,data); 82 | end 83 | end 84 | 85 | 86 | end -------------------------------------------------------------------------------- /Room.m: -------------------------------------------------------------------------------- 1 | %file:SaveSpace.m 2 | %save the MSB of adjustment area pixel in order to adjust 3 | %origin: original image blocksize: size of block 4 | %MSB: the number of every bit in adjustment area used for adjustment 5 | %count: the max number of elements in EN1 6 | function embed_image = Room( origin , blocksize , DATA) 7 | [~,len] = size(DATA); 8 | embed_image = origin; 9 | [M,N] = size(origin); 10 | m = M/blocksize; 11 | n = N/blocksize; 12 | index = 1; 13 | for i = 1 : m 14 | for j = 1 : n 15 | x = (i-1)*blocksize+1; 16 | y = (j-1)*blocksize+1; 17 | 18 | for p = x+1 : 1 : x+blocksize-2 19 | for q = y+1 : 2 : y+blocksize-2 20 | l = floor(double(uint16(embed_image(p,q))+uint16(embed_image(p,q+1)))/2); 21 | h = double(double(embed_image(p,q))-double(embed_image(p,q+1))); 22 | min = 2*(255-l); 23 | b = 2*l+1; 24 | if( b < min ) 25 | min = b; 26 | end 27 | if abs(2*floor(h/2)+1) length 34 | index2 = length; 35 | end 36 | data = []; 37 | [~,x] = size(DATA); 38 | data(1:x) = DATA(:); 39 | data(x+1:x+index2-index+1) = bits(index:index2); 40 | embed_image = Room(embed_image,blocksize,data); 41 | index = index2+1; 42 | end 43 | EnImage = Encipher( embed_image , key); %encipher 44 | [AjImage,s] = Adjustment( EnImage , blocksize , values , MSB); 45 | toc 46 | DeImage = Encipher( AjImage , key); %decipher 47 | ReImage = Recover( DeImage , blocksize , MSB); 48 | imwrite(AjImage,"reserve.png","png"); 49 | -------------------------------------------------------------------------------- /original.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RMDE/ImageEncipher/0cecf157250a1574619cb32f6f1dadcd8b90c645/original.png -------------------------------------------------------------------------------- /plant.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RMDE/ImageEncipher/0cecf157250a1574619cb32f6f1dadcd8b90c645/plant.m -------------------------------------------------------------------------------- /refparams_vecgsm.m: -------------------------------------------------------------------------------- 1 | function [ssarr, l_arr, cu_arr]=refparams_vecgsm(org,subands,M) 2 | 3 | %This function computes the parameters of the reference image. This is 4 | %called by vifvec.m. 5 | 6 | for i=1:length(subands); 7 | sub=subands(i); 8 | y=org{sub}; 9 | 10 | sizey=floor(size(y)./M)*M; % crop to exact multiple size 11 | y=y(1:sizey(1),1:sizey(2)); 12 | 13 | 14 | % Collect MxM blocks. Rearrange each block into an 15 | % M^2 dimensional vector and collect all such vectors. 16 | % Collece ALL possible MXM blocks (even those overlapping) from the subband 17 | temp=[]; 18 | for j=1:M 19 | for k=1:M 20 | temp=cat(1,temp,reshape(y(k:end-(M-k), j:end-(M-j)),1,[])); 21 | end 22 | end 23 | 24 | % estimate mean and covariance 25 | mcu=mean(temp')'; 26 | cu=((temp-repmat(mcu,1,size(temp,2)))*(temp-repmat(mcu,1,size(temp,2)))')./size(temp,2); % covariance matrix for U 27 | 28 | % Collect MxM blocks as above. Use ONLY non-overlapping blocks to 29 | % calculate the S field 30 | temp=[]; 31 | for j=1:M 32 | for k=1:M 33 | temp=cat(1,temp,reshape(y(k:M:end, j:M:end),1,[])); 34 | end 35 | end 36 | 37 | % Calculate the S field 38 | ss=(inv(cu)*temp); 39 | ss=sum(ss.*temp)./(M*M); 40 | ss=reshape(ss,sizey/M); 41 | 42 | % Eigen-decomposition 43 | [v,d]=eig(cu); 44 | l_arr(sub,:)=diag(d)'; 45 | 46 | % rearrange for output 47 | ssarr{sub}=ss; 48 | temp=0; 49 | d=diag(d); 50 | cu_arr{sub}=cu; 51 | end 52 | 53 | -------------------------------------------------------------------------------- /reserve.m: -------------------------------------------------------------------------------- 1 | %file:SaveSpace.m 2 | %save the MSB of adjustment area pixel in order to adjust 3 | %origin: original image blocksize: size of block 4 | %MSB: the number of every bit in adjustment area used for adjustment 5 | %count: the max number of elements in EN1 6 | function [embed_image,Cap,DATA] = reserve( origin , blocksize , MSB , count, bits) 7 | 8 | embed_image = origin; 9 | [M,N] = size(origin); 10 | m = M/blocksize; 11 | n = N/blocksize; 12 | DATA = [];%store the all message of every block to embedding 13 | Cap = 0; 14 | 15 | %collecting the embedding message 16 | for i = 1 : m 17 | for j = 1 : n 18 | x = (i-1)*blocksize+1; 19 | y = (j-1)*blocksize+1; 20 | [data,embed_image,capacity] = Embed1(embed_image,blocksize,x,y,MSB,count); 21 | [~,l] = size(DATA); 22 | [~,len] = size(data); 23 | DATA(l+1:l+len) = data(1:len); 24 | Cap = Cap + capacity; 25 | end 26 | end 27 | 28 | %embedding the data to the whole image 29 | index = 1; 30 | [~,len] = size(DATA) 31 | 32 | end 33 | -------------------------------------------------------------------------------- /resize.m: -------------------------------------------------------------------------------- 1 | for mm =1:3 2 | b=".png"; 3 | c=num2str(mm); 4 | name=strcat("eva\me",c,b) 5 | origin=imread(name,"png"); 6 | [M,N] = size(origin); 7 | AjImage = imresize(origin,2); 8 | b=".png"; 9 | c=num2str(mm); 10 | res=strcat("eva\me",c,b); 11 | imwrite(AjImage,res,'png'); 12 | end -------------------------------------------------------------------------------- /sub.m: -------------------------------------------------------------------------------- 1 | origin = imread("dec-sub1.png","png"); 2 | subimg = imread("me.png","png"); 3 | [M,N] = size(origin); 4 | blocksize = 128; 5 | imresize(subimg,[blocksize,blocksize]); 6 | size(subimg) 7 | MSB = 2; 8 | for i = 1 :32 9 | for j = 1 :32 10 | for x = i*4-3 : i*4 11 | for y = j*4-3 : j*4 12 | subimg(x,y) = origin(i,j); 13 | end 14 | end 15 | 16 | % subimg(i,j) = origin(blocksize*2+i,j); 17 | % subimg(i,j) = origin(M-blocksize*1+i,N-blocksize+j); 18 | end 19 | end 20 | imwrite(subimg,"dec-sub1(b).png","png"); 21 | % ori = imread("dec-sub6.png","png"); 22 | % value = ori(1,1); 23 | % [M,N] = size(ori); 24 | % for i = 1 : M 25 | % ori(i,2) = unifrnd (0,255); 26 | % ori(i,N-1) = unifrnd (0,255); 27 | % end 28 | % for i = 1 : N 29 | % ori(2,i) = unifrnd (0,255); 30 | % ori(M-1,i) = unifrnd (0,255); 31 | % end 32 | % imwrite(ori,"dec-sub6.png","png"); -------------------------------------------------------------------------------- /test2.m: -------------------------------------------------------------------------------- 1 | % % x = imread("origin-th.png","png"); 2 | % % y = imread("thumbnail.png","png"); 3 | % % [M,N] = size(x); 4 | % % dif = double(0); 5 | % % for i = 1:M 6 | % % for j = 1:N 7 | % % p = double(x(i,j)); 8 | % % q = double(y(i,j)); 9 | % % s = double(abs(p-q)); 10 | % % dif = dif + s/double(x(i,j)); 11 | % % end 12 | % % end 13 | % % dif = dif/double((M*N)) 14 | % 15 | % %file: main.m 16 | % %%the main function of the project 17 | % whole = imread("apple.png","png"); 18 | % [M,N,C] = size(whole); 19 | % blocksize = 32; 20 | % MSB = 2; 21 | % count = 20000; 22 | % key = 1; 23 | % m = M/blocksize; 24 | % n = N/blocksize; 25 | % values = zeros(m,n);%store the original average pixel of every block 26 | % sub1 = zeros(blocksize); 27 | % sub2 = zeros(blocksize); 28 | % for chanal = 1 : C 29 | % origin = whole(:,:,chanal); 30 | % for i = 1 : m 31 | % for j = 1 : n 32 | % x = (i-1)*blocksize+1; 33 | % y = (j-1)*blocksize+1; 34 | % sub1(1:blocksize,1:blocksize) = origin(x:x+blocksize-1,y:y+blocksize-1); 35 | % values(i,j) = mean2(sub1); 36 | % end 37 | % end 38 | % 39 | % embed_image = SaveSpace( origin , blocksize , MSB , count); 40 | % EnImage = Encipher( embed_image , key); %encipher 41 | % [AjImage,s] = Adjustment( EnImage , blocksize , values , MSB); 42 | % whole(:,:,chanal) = AjImage(:,:); 43 | % end 44 | % imwrite(whole,"apple-res.png","png"); 45 | % 46 | % 47 | 48 | 49 | % Img=imread('dream\dream-.png'); 50 | % BW = Img; 51 | % R=BW(:,:,1); 52 | % [REDcounts,x] = imhist(R); 53 | % G=BW(:,:,2); 54 | % [Greencounts,y] = imhist(R); 55 | % B=BW(:,:,3); 56 | % [Bluecounts,z] = imhist(R); 57 | % figure; 58 | % subplot(131);imhist(R);title('Red'); 59 | % subplot(132);imhist(G);title('Green'); 60 | % subplot(133);imhist(B);title('Blue'); 61 | 62 | %file: main.m 63 | %%the main function of the project 64 | for pic = 1:20 65 | whole = imread(strcat("temp\",num2str(pic),".jpeg"),"jpeg"); 66 | [M,N,C] = size(whole); 67 | blocksize = 16; 68 | MSB = 2; 69 | count = 20000; 70 | key = 1; 71 | m = M/blocksize; 72 | n = N/blocksize; 73 | values = zeros(m,n);%store the original average pixel of every block 74 | for chanal = 1 : C 75 | origin = whole(:,:,chanal); 76 | for i = 1 : m 77 | for j = 1 : n 78 | x = (i-1)*blocksize+1; 79 | y = (j-1)*blocksize+1; 80 | sub1(1:blocksize,1:blocksize) = origin(x:x+blocksize-1,y:y+blocksize-1); 81 | values(i,j) = mean2(sub1); 82 | end 83 | end 84 | 85 | embed_image = SaveSpace( origin , blocksize , MSB , count); 86 | EnImage = Encipher( embed_image , key); %encipher 87 | [AjImage,s] = Adjustment( EnImage , blocksize , values , MSB); 88 | whole(:,:,chanal) = AjImage(:,:); 89 | end 90 | 91 | imwrite(whole,strcat("temp\res-",num2str(pic),".png"),"png"); 92 | end 93 | -------------------------------------------------------------------------------- /thumbnail.m: -------------------------------------------------------------------------------- 1 | % for photo = 1:28 2 | % name = strcat("eva\flower(64,2)",".png"); 3 | % origin = imread(name,"png"); 4 | % [M,N,C] = size(origin); 5 | % blocksize = 64; 6 | % m = M/blocksize; 7 | % n = N/blocksize; 8 | % values = 0;%store the original average pixel of every block 9 | % sub = zeros(blocksize); 10 | % result = origin; 11 | % for channel = 1 : C 12 | % for i = 1 : m 13 | % for j = 1 : n 14 | % x = (i-1)*blocksize+1; 15 | % y = (j-1)*blocksize+1; 16 | % sub(1:blocksize,1:blocksize) = origin(x:x+blocksize-1,y:y+blocksize-1,channel); 17 | % values = mean2(sub); 18 | % for p = x : x+blocksize-1 19 | % for q = y : y+blocksize-1 20 | % result(p,q,channel) = values; 21 | % end 22 | % end 23 | % end 24 | % end 25 | % end 26 | % res = strcat("eva/t-flower(64,2)",".png"); 27 | % imwrite(result,res,'png'); 28 | % end 29 | 30 | 31 | blocksize = 8; 32 | sum = double(0); 33 | difference = double(0); 34 | str = ['head\','bust\','body\']; 35 | for subx = 2:2 36 | a1 = 'origin\'; 37 | a1 = strcat(a1,str(subx*5+1:(subx+1)*5)); 38 | a2 = 'thumbnail\'; 39 | a2 = strcat(a2,str(subx*5+1:(subx+1)*5)); 40 | for mm =1:60 41 | b=".png"; 42 | c=num2str(mm); 43 | name=strcat(a1,c,b); 44 | origin=imread(name,"png"); 45 | [M,N] = size(origin); 46 | m = M/blocksize; 47 | n = N/blocksize; 48 | sub = zeros(blocksize); 49 | result = origin; 50 | for i = 1 : m 51 | for j = 1 : n 52 | x = (i-1)*blocksize+1; 53 | y = (j-1)*blocksize+1; 54 | sub(1:blocksize,1:blocksize) = origin(x:x+blocksize-1,y:y+blocksize-1); 55 | values = mean2(sub); 56 | for p = x : x+blocksize-1 57 | for q = y : y+blocksize-1 58 | result(p,q) = values; 59 | end 60 | end 61 | end 62 | end 63 | b=".png"; 64 | c=num2str(mm); 65 | res=strcat(a2,c,b); 66 | imwrite(result,res,'png'); 67 | end 68 | end 69 | 70 | sum = double(0); 71 | difference = double(0); 72 | str = ['head\','bust\','body\']; 73 | for subx = 2:2 74 | a1 = 'result\'; 75 | a1 = strcat(a1,str(subx*5+1:(subx+1)*5)); 76 | a2 = 'result2\'; 77 | a2 = strcat(a2,str(subx*5+1:(subx+1)*5)); 78 | for mm =1:60 79 | b=".png"; 80 | c=num2str(mm); 81 | name=strcat(a1,c,b); 82 | origin=imread(name,"png"); 83 | [M,N] = size(origin); 84 | m = M/blocksize; 85 | n = N/blocksize; 86 | sub = zeros(blocksize); 87 | result = origin; 88 | for i = 1 : m 89 | for j = 1 : n 90 | x = (i-1)*blocksize+1; 91 | y = (j-1)*blocksize+1; 92 | sub(1:blocksize,1:blocksize) = origin(x:x+blocksize-1,y:y+blocksize-1); 93 | values = mean2(sub); 94 | for p = x : x+blocksize-1 95 | for q = y : y+blocksize-1 96 | result(p,q) = values; 97 | end 98 | end 99 | end 100 | end 101 | b=".png"; 102 | c=num2str(mm); 103 | res=strcat(a2,c,b); 104 | imwrite(result,res,'png'); 105 | end 106 | end 107 | % 108 | % sum = double(0); 109 | % difference = double(0); 110 | % str = ['head\','bust\','body\']; 111 | % level = double(0); 112 | % level2 = double(0); 113 | % for subx = 2:2 114 | % a1 = 'thumbnail\'; 115 | % a1 = strcat(a1,str(subx*5+1:(subx+1)*5)); 116 | % a2 = 'result2\'; 117 | % a2 = strcat(a2,str(subx*5+1:(subx+1)*5)); 118 | % for mm =1:60 119 | % b=".png"; 120 | % c=num2str(mm); 121 | % name=strcat(a1,c,b); 122 | % x=imread(name,"png"); 123 | % name2=strcat(a2,c,b); 124 | % y=imread(name2,"png"); 125 | % level = level + ssim(x,y); 126 | % level2 = level2 + psnr(x,y); 127 | % % [M,N] = size(x); 128 | % % dif = double(0); 129 | % % for i = 1:M 130 | % % for j = 1:N 131 | % % p = double(x(i,j)); 132 | % % q = double(y(i,j)); 133 | % % s = double(abs(p - q)); 134 | % % if( p == 0 ) 135 | % % % p = 1; 136 | % % continue; 137 | % % end 138 | % % dif = dif + s/double(p); 139 | % % end 140 | % % end 141 | % % dif = dif/double(M*N); 142 | % % level = level + dif; 143 | % end 144 | % end 145 | % level = level/60.0 146 | % level2 = level2/60.0 147 | 148 | % whole = imread("flower.png","png"); 149 | % [M,N,C] = size(whole); 150 | % blocksize =16; 151 | % MSB = 2; 152 | % count = 20000; 153 | % key = 1; 154 | % m = M/blocksize; 155 | % n = N/blocksize; 156 | % values = zeros(m,n);%store the original average pixel of every block 157 | % sub1 = zeros(blocksize); 158 | % sub2 = zeros(blocksize); 159 | % result1 = whole; 160 | % for chanal = 1:C 161 | % for i = 1 : m 162 | % for j = 1 : n 163 | % x = (i-1)*blocksize+1; 164 | % y = (j-1)*blocksize+1; 165 | % sub1(1:blocksize,1:blocksize) = whole(x:x+blocksize-1,y:y+blocksize-1,chanal); 166 | % value1 = mean2(sub1); 167 | % for p = x : x+blocksize-1 168 | % for q = y : y+blocksize-1 169 | % result1(p,q,chanal) = value1; 170 | % end 171 | % end 172 | % end 173 | % end 174 | % end 175 | % imwrite(result1,"thumbnail.png","png"); 176 | % % imwrite(result1,"ave.png","png"); -------------------------------------------------------------------------------- /trans.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RMDE/ImageEncipher/0cecf157250a1574619cb32f6f1dadcd8b90c645/trans.m --------------------------------------------------------------------------------