
%  put a watermark in the image according the statistic patches method.

function [new_Wvlet,comlen,nsec_sum] = Water_Patch_first(img,generator)
%  put a watermark in the image according the statistic patches method.
img=double(img);
% figure,imshow(uint8(img));
sizeImg=size(img);
sizeImg_x=sizeImg(1);
sizeImg_y=sizeImg(2);
newImage=zeros(size(img));%
half_sizeImg_y = sizeImg_y/2;
multi_size = sizeImg_x * half_sizeImg_y;
t_Wvlet = zeros(sizeImg_x, sizeImg_y);
Wvlet = zeros( sizeImg_x,  sizeImg_y);
new_Wvlet_test = zeros(sizeImg_x, sizeImg_y);
new_Wvlet = zeros(sizeImg_x, sizeImg_y);
location_map = zeros(sizeImg_x,  half_sizeImg_y);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%harr码的实现
for i = 1: sizeImg_x
    for n = 1: half_sizeImg_y
        j = n * 2 - 1;
        k0 = img(i,j); 
        k1 = img(i,j+1); 
        Wvlet(i,j)=floor((k1 + k0)/2);
        Wvlet(i,j+1)=k1 - k0;
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%测试%%%%%%%%%%%%%%%%%%%%%%%%%%%
ncount = 1;
test_map = zeros(1,multi_size);
for i = 1:sizeImg_x
    for n = 1: half_sizeImg_y
        j = n * 2 - 1;
        half_sum = Wvlet(i,j);
        org_h = Wvlet(i,j+1);
        [test_map(ncount)] = Wm_test(half_sum,org_h);   
%         [fir_test_map(ncount)] = fir_wm_test(half_sum,org_h);
        ncount = ncount + 1;
    end
end
% nflag_sum = sum(test_map);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%位置图的获得
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

ncount = 1;
location_map2 = zeros(1,multi_size);
third_map = zeros(1,multi_size);
nflag_sec = zeros(1,multi_size);
two_ncount = 0;
sec_ncount = 0;
for i = 1:sizeImg_x
    for n = 1: half_sizeImg_y
        j = n * 2 - 1;
        half_sum = Wvlet(i,j);
        org_h = Wvlet(i,j+1);
        [location_map2(ncount),third_map(ncount),nflag_sec(ncount),nflag,two_nflag,nflag_01] = Wm_preprocess(half_sum,org_h);
        if third_map(ncount) == -1
            sec_ncount = sec_ncount + 1;
            if sec_ncount == 1
                sec_nflag = zeros(1,sec_ncount);
                if nflag == 1
                    sec_nflag(1:sec_ncount) = 1;
                end
                flag_01 = zeros(sec_ncount, 2);%程序可以编简单                    
                flag_01 = nflag_01;
            else
                tmp = sec_nflag;
                tmp_size = length(sec_nflag);                     
                sec_nflag = zeros(1,sec_ncount);
                sec_nflag(1:tmp_size) = tmp;  
                if nflag == 1
                    sec_nflag((tmp_size + 1): sec_ncount) = 1;
                end
                tmp_nflg = flag_01;
                tmp_nflg_size = size(flag_01,1);
                flag_01 = zeros(sec_ncount,2);
                flag_01(1:tmp_nflg_size,1:2) = tmp_nflg; 
                flag_01((tmp_nflg_size+1):sec_ncount,1:2) = nflag_01;
            end              
        end
        if (two_nflag == 1)
            two_ncount = two_ncount + 1;
            if two_ncount == 1
                two_sec = zeros(1,two_ncount);
                two_sec(1:two_ncount) = location_map2(ncount);
            else
                two_tmp = two_sec;
                two_tmp_size = length(two_sec);
                two_sec = zeros(1,two_ncount);
                two_sec(1:two_tmp_size) = two_tmp; 
                two_sec((two_tmp_size+1):two_ncount) = location_map2(ncount);
            end
        end            
        ncount = ncount + 1;
    end
end
nflag_sum = sum(third_map(find(third_map == -1)));
sec_num = sum(nflag_sec(find(nflag_sec == 1)));
if nflag_sum ~= 0
    nsec_sum = sum(sec_nflag);
else
    nsec_sum = 0;
end
%%%%%%%%%%%%%%%%%%%%%%%%新的测试%%%%%%%%%%%%%%%%%%


% % % % 数据的压缩
% 
bin_index = 8;
% % %算术编码
%if(0)
    cPos_x = cell(1,1);
    cPos_x{1} = two_sec;
    [map_Com,Res] =  Arith06(cPos_x);
    map_com_len = length(map_Com);
    [bin_matrix, bin_matrix_size] = dec_transform_bin(map_Com,bin_index);
    cPos_y = cell(1,1);
    cPos_y{1} = sec_nflag;
    [sec_Com,Res] =  Arith06(cPos_y);
    sec_com_len = length(sec_Com);
    [sec_bin_matrix, sec_bin_matrix_size] = dec_transform_bin(sec_Com,bin_index);
% end
% % %游程编码加哈夫曼编码
if(0)
    bin_index = ceil(log2(code_len));
    runLen = CodeRL(location_map1);  
    run_len = length(runLen);
    [bin_matrix, bin_matrix_size] = dec_transform_bin(runLen,bin_index);
end
%JBIG编码

%数据由十进制变为二进制

%压缩之后的数据加结束符EOF
if nflag_sum ~= 0
    sec_len = length(sec_nflag(find(sec_nflag == 1)));
else
    sec_len = 0;
end
    binLSB_size = bin_matrix_size;
    binLSB = zeros(1,binLSB_size);
    binLSB(1:bin_matrix_size) = bin_matrix(1:bin_matrix_size);
% %水印数据(随机数)
new_index = bin_index*2;% if nflag_sum ~= 0
%     sec_len = length(sec_nflag);
%     [bin_sec, bin_sec_size] = dec_transform_bin(sec_len,new_index);
%     binLSB_size = bin_matrix_size + bin_sec_size + sec_bin_matrix_size;
%     binLSB = zeros(1,binLSB_size);
%     binLSB(1:bin_matrix_size) = bin_matrix(1:bin_matrix_size);
%     binLSB((1+bin_matrix_size):(bin_matrix_size + bin_sec_size)) = bin_sec;
%     binLSB((1+bin_matrix_size + bin_sec_size):binLSB_size) = sec_bin_matrix;
% else
%     sec_len = 0;
%     [bin_sec, bin_sec_size] = dec_transform_bin(sec_len,new_index);
%     binLSB_size = bin_matrix_size + sec_len + bin_sec_size;
%     binLSB = zeros(1,binLSB_size);
%     binLSB(1:bin_matrix_size) = bin_matrix(1:bin_matrix_size);
%     binLSB((1+bin_matrix_size):binLSB_size) = bin_sec;
% end

fir_size = length(find(third_map == 0));%第一类的个数sec_num为跳变第二类的个数
wm_size = multi_size - binLSB_size - fir_size - sec_num;
wm_payload = round(rand(1,wm_size));
% %%%%%%%%%%%%%%%%水印的嵌入%%%%%%%%%%%%%%%%%%%%
ncount = 1;
total_count = 1;
wm_count = 1;
sec_ncount = 1;
for i = 1:sizeImg_x
    for n = 1: half_sizeImg_y
        j = n * 2 - 1;
        half_sum = Wvlet(i,j);
        org_h = Wvlet(i,j+1);
%         if wm_count == 29591
%             half_sum = Wvlet(i,j);
%             org_h = Wvlet(i,j+1);
%         end
        if third_map(total_count)== 1%为1代表的是第三类 
            if (ncount <= binLSB_size)
                [new_Wvlet(i,j), new_Wvlet(i,j+1)] = Wm_Embeded(half_sum, org_h, binLSB(ncount));
                ncount = ncount + 1;
            elseif (ncount > binLSB_size) & (wm_count <= wm_size) 
                [new_Wvlet(i,j), new_Wvlet(i,j+1)] = Wm_Embeded(half_sum,org_h,wm_payload(wm_count));
                wm_count = wm_count + 1;
            end 
        elseif (third_map(total_count)== -1) & (wm_count <= wm_size)%为1代表的是第二类 
            if sec_nflag(sec_ncount) == 1
                if flag_01(sec_ncount,1) == 1
                    new_h = 2 * org_h;
                    new_Wvlet(i,j) = half_sum - floor((new_h)/2);
                    new_Wvlet(i,j+1) = half_sum + floor((new_h+1)/2);
                elseif flag_01(sec_ncount,2) == 1%flag_01的第一位是嵌入0，第二位是嵌入1，若0的位置为1表明它不满足条件， 否则是满足的
                    new_h = 2 * org_h + 1;
                    new_Wvlet(i,j) = half_sum - floor((new_h)/2);
                    new_Wvlet(i,j+1) = half_sum + floor((new_h+1)/2);
                end             
            else
                [new_Wvlet(i,j), new_Wvlet(i,j+1)] = Wm_Embeded(half_sum,org_h,wm_payload(wm_count));
                wm_count = wm_count + 1;              
            end
            sec_ncount = sec_ncount + 1;
        elseif third_map(total_count)== 0
            new_Wvlet(i,j) = half_sum - floor((org_h)/2);
            new_Wvlet(i,j+1) = half_sum + floor((org_h+1)/2);
        end
        if total_count ~=  multi_size
             if (wm_count > wm_size) & (ncount > binLSB_size) 
                 new_Wvlet(i,j) = half_sum - floor((org_h)/2);
                 new_Wvlet(i,j+1) = half_sum + floor((org_h+1)/2);
             end      
         end
        total_count = total_count + 1;
    end
end            
% new_Wvlet(1:max_line, 1:max_row) = newImage(1:10,1:10);
% figure,imshow(uint8(new_Wvlet));
imwrite(uint8(new_Wvlet), 'girl_idea.bmp');
[PSNR]=psnr(img,new_Wvlet);

% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 
% %解压的程序用来比较图像是不是可拟的恢复了
% 
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
t_Wvlet = zeros(sizeImg_x, sizeImg_y);
Wvlet = zeros( sizeImg_x,  sizeImg_y);
for i = 1: sizeImg_x
    for n = 1: half_sizeImg_y
        j = n * 2 - 1;
        k0 = new_Wvlet(i,j); 
        k1 = new_Wvlet(i,j+1); 
        Wvlet(i,j)=floor((k1 + k0)/2);
        Wvlet(i,j+1)=k1 - k0;
    end
end

%水印的提取
nLSB = 1;
ncount = 1;
LSB_size = sizeImg_x*half_sizeImg_y;
LSB = zeros(1,LSB_size);
location_map = zeros(1,LSB_size);
%预处理—也就是来提取位置图的过程 
for i = 1:sizeImg_x
    for n = 1: half_sizeImg_y
        j = n * 2 - 1;
        half_sum = Wvlet(i,j);
        embeded_h = Wvlet(i,j+1);
        [LSB(ncount),location_map(ncount)]= Water_Ex_Preprocess(half_sum,embeded_h);
        ncount = ncount + 1;
    end  
end
%%%%测试%%%%%
 for i =1:LSB_size
     if third_map(i) == -1
         pos_map(i) = 0;
     else
         pos_map(i) = third_map(i);
     end
end
%%%%%%%%%%%%%
%水印的解压
embeded_LSB = LSB(find(LSB~=-1));%找到了嵌入了水印的最低位
embeded_LSB_len = length(embeded_LSB);
%算术编码
% if(0)
    cPos_x = cell(1,1);
    bin_index = 8;
    code_len = 256;
    [dec_matrix, dec_matrix_size] = bin_transform_dec(embeded_LSB,bin_index);
    [wm_Extracted] =  Arith06(dec_matrix');
    map_sq = wm_Extracted{1}';
    cPos_x{1} = wm_Extracted{1};
    [sq_Orig,Res] =  Arith06(cPos_x);%sq_Orig这是恢复出来位置图
    sqlen = length(sq_Orig);
    sq_len = sqlen * 8;%%
    map_sqlen = length(map_sq);
    new_map = zeros(1,map_sqlen);
    new_map = map_sq(1:map_sqlen);
    sec_bin_len = embeded_LSB((sq_len+1): (sq_len+bin_index*2));
    [sec_sq, sec_sq_size] = bin_transform_dec(sec_bin_len,bin_index*2);
    tmp_LSB = dec_matrix((sqlen + 3):dec_matrix_size);
    sec_flip_Ex = Arith06(tmp_LSB');
    sec_sq = sec_flip_Ex{1}';
    cPos_y{1} = sec_flip_Ex{1};
    [sec_Orig,Res] =  Arith06(cPos_y);%  
    total_map = sq_len + bin_index*2 + length(sec_Orig) * 8;
% end
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%水印的提取%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ncount = 1;
change_ncount = 1;
total_count = 1;
wm_bit = zeros(1,wm_size);
wm_ncount = 1;
map_ncount = 1;
for i = 1:sizeImg_x
    for n = 1: half_sizeImg_y            
        j = n * 2 - 1;
        half_sum = Wvlet(i,j);
        embeded_h = Wvlet(i,j+1);
%         if wm_ncount == 29591
%             half_sum = Wvlet(i,j);
%             org_h = Wvlet(i,j+1);
%         end
        if location_map(total_count) == 1%表示的是第三类
            if (ncount <= total_map)
                new_h = floor(embeded_h/2);
                ncount = ncount + 1; 
            elseif(ncount > total_map) & (wm_ncount <= wm_size)
                wm_bit(wm_ncount) =  embeded_h - 2*floor(embeded_h/2);  
                new_h = floor(embeded_h/2);
                wm_ncount = wm_ncount + 1;
            elseif (ncount > total_map) & (wm_ncount > wm_size)
                new_h = embeded_h;
            end
        else
            if new_map(map_ncount) == 1%表示这是第一类和部分第二类
                new_h = embeded_h;              
            elseif new_map(map_ncount) == 0%表示的是第二类
                new_h = floor(embeded_h/2);
                [Ex_test_nflag] = Wm_Ex_test(half_sum,new_h);   
                if Ex_test_nflag == 0
                    if (wm_ncount <= wm_size)
                        new_h = floor(embeded_h/2);
                        wm_bit(wm_ncount) =  embeded_h - 2*floor(embeded_h/2); 
                        wm_ncount = wm_ncount + 1;
                    else
                        new_h = embeded_h;
                    end  
                end
%                 if sec_sq(change_ncount) == 1%表示的是第二类中左右不定的像素
%                     [new_h] = Wm_Ex_map(half_sum,embeded_h);  
%                     half_h = floor(embeded_h/2);
%                 else
%                     if (wm_ncount <= wm_size)
%                         new_h = floor(embeded_h/2);
%                         wm_bit(wm_ncount) =  embeded_h - 2*floor(embeded_h/2); 
%                         wm_ncount = wm_ncount + 1;
%                     else
%                         new_h = embeded_h;
%                     end                            
%                 end        
                change_ncount = change_ncount + 1;                                                   
            end 
            map_ncount = map_ncount + 1;  
        end
        t_Wvlet(i,j) = half_sum - floor((new_h)/2);    
        t_Wvlet(i,j+1) = half_sum + floor((new_h+1)/2);    
        total_count = total_count + 1;
    end
end
%原图的恢复

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%图像的抽取和恢复（测试）%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% BASE_SIZE = 32;
% sizeY = 256;
% sizeX = 256;
% numX = sizeX/BASE_SIZE;
% numY = sizeY/BASE_SIZE;
% BlockNum = (sizeX * sizeY)/(BASE_SIZE*BASE_SIZE);
% match_img_size = zeros(1,BlockNum);
% k = 1;
% for i=1:numX 
%      for j=1:numY
%          img1 = img(i*BASE_SIZE-BASE_SIZE  + 1:i*BASE_SIZE,j*BASE_SIZE-BASE_SIZE + 1:j*BASE_SIZE);%32*32;    
%          img2 = t_Wvlet(i*BASE_SIZE-BASE_SIZE  + 1:i*BASE_SIZE,j*BASE_SIZE-BASE_SIZE + 1:j*BASE_SIZE);
%          match_img_size(k) = length(find(img1 ~= img2));
%          k = k +1;
%      end
%  end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
match_img = zeros( sizeImg_x, sizeImg_y);
k = 1;
for i = 1:sizeImg_x
    for n = 1: half_sizeImg_y
        j = 2 * n - 1;
        half_Ex = t_Wvlet(i,j);
        half_Orig = img(i,j);
        if half_Ex == half_Orig
            match_img(i,n) = 1;
        end
        k = k + 1;
    end  
end
match_img_size = zeros(1,LSB_size);
k = 1;
for i = 1:sizeImg_x
    for n = 1: half_sizeImg_y
        j = 2 * n - 1;
        half_Ex = t_Wvlet(i,j);
        half_Orig = img(i,j);
        if half_Ex == half_Orig
            match_img_size(k) = 1;
        end
        k = k + 1;
    end  
end
wm_Ex_size = length(wm_bit);
match_wm_size = zeros(1,wm_Ex_size);
k = 1;
for i = 1:wm_Ex_size
    wm_Ex = wm_payload(i);
    wm_Orig = wm_bit(i);
    if (wm_Ex == wm_Orig)
        match_wm_size(k) = 1;
    end
    k = k + 1;
end

[dec_matrix1, dec_matrix_size1] = bin_transform_dec(wm_bit,bin_index);%水印的恢复