% *****************************************************************
% Vodoznaceni v jasové oblasti na principu Patchworkova algoritmu
% 
% Stagl Lubos
% Diplomova prace - metoda cislo I.
% *****************************************************************

function [PSNR, OH, WO, Obr_uprav, S1]=patchwork(uplna_cesta,hladina,klic_bit,velke)

help patchwork;             % zobrazeni helpu a popisu funkce

% <<<<<<< Nacteni obrazu bez vodoznaku + informace o nem >>>>>>>

obr = (imread(uplna_cesta));                                % info 0 - 255 o kazdem bodu obrazu  
imwrite(uint8(obr),'Patchwork1.jpg','Quality',100);         % ulozeni kvuli hodnoceni

puvodni_obraz = obr;
save puvodni_obraz                                          % ulozeni puvodni obraz

PO_info = imfinfo(uplna_cesta);
PO_vyska = PO_info.Width;                                   % PO = puvodni_obraz
PO_sirka = PO_info.Height;

x_source = puvodni_obraz;
temp_hladina = puvodni_obraz;


% <<<<<<< Tvorba klice, vyber 0 +1 a -1 z dane mnoziny S >>>>>>>

Key = sign(round(randn(size(puvodni_obraz))));                % nahodne vygener. klic k wodoznaku

% ******** zisk obrazu z dané hladiny ****************
[OH]=najdi_prvky_z_hladiny(temp_hladina,hladina,velke);       % OH = dana hladina obrazu
 OH = uint8(OH./255);                                         % abym vratili zpet na puvodni hodnoty pred upravou na zobrazeni

% <<<<<<<<<<<<<<<<<<<<<<<<<< Patchwork >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
% <<<<< Pouziti mnoziny S1 a nebo obrazu, pro vlozeni vodoznaku >>>>>>>>
 
switch (klic_bit)
            case 1
                S1 = zeros(PO_sirka, PO_vyska);                             % cerny podklad obrazu

                for i=1:PO_sirka;
                    for j=1:PO_vyska;
                        if Key(i,j)==1
                            S1(i,j)= Key(i,j);                              % 1 -> bile v obraze
                        end
                        Obr_uprav(i,j) = bitxor(OH(i,j) , S1(i,j));         % vlozeni vodoznaku
                    end   
                end    
                % velS1= sum(sum(S1));       S1+S2+S3 = PO_info.bitmapsize
                
            case 2
                S1 = zeros(PO_sirka, PO_vyska);
                for i=1:PO_sirka;
                    for j=1:PO_vyska;
                        if Key(i,j)==-1
                            S1(i,j)= 1;                                     % 1 -> bile v obraze
                        end
                        Obr_uprav(i,j) = bitxor(OH(i,j) , S1(i,j));         % vlozeni vodoznaku    
                    end
                end 
               % velS2= sum(sum(S2))*(-1);    
                
            case 3
                S1 = zeros(PO_sirka, PO_vyska);                             % cerny obraz ones(PO_vyska,PO_sirka)
                for i=1:PO_sirka;
                    for j=1:PO_vyska;
                        if Key(i,j)==0
                            S1(i,j)= 1;                                     % 1 -> bile v obraze
                        end                        
                        Obr_uprav(i,j) = bitxor(OH(i,j) , S1(i,j));         % vlozeni vodoznaku
                    end
                end
               % velS3= sum(sum(S3))/(2);

            case 4
                load Vodoznak
                OH_vodo = OH;                                                % abychom nemenili puvodni OH
                [vy,vx] = size(Vodoznak);                                    % velikost vodoznaku                
                for a=1:vy;                                                  % vlozeni vodoznaku do obrazu
                    for b=1:vx;     
                        OH_vodo(a,b) = Vodoznak(a,b);   
                        OH_vodo(PO_sirka-vy+a,b) = Vodoznak(a,b);                  % je mozno vlozit vicekrat kvuli orezovým utokum                        
                        OH_vodo(a,PO_vyska-vx+b) = Vodoznak(a,b);
                        OH_vodo(PO_sirka-vy+a,PO_vyska-vx+b) = Vodoznak(a,b);
                  end 
                end 
                S1= OH_vodo;
               Obr_uprav = S1; 
end
 
% pokud je hladina 3, je zmena + - 8 -> kdybychom chteli 9 -> modifikace stejnym klicem 
% 0 a 3 hladinu. 
% d parametr na + - do ktere bitove rovinny, melo by se d0 - d3
% coz jsou hodnoty 1 - 8 ale posuvnik bude na d7
% Budeme zmenu provadet podle XOR fce.

% <<<<<<<<<<<<<<<<<<<< Vlozeni zpet do puvodniho obrazu >>>>>>>>>>>>>>>>>>>>>>>>>    

[WO] = vloz_prvky_do_hladiny(temp_hladina,Obr_uprav,hladina);

imwrite(uint8(WO),'PatchworkWM1.jpg','Quality',100);                        % ulozeni kvuli checkmarku

% <<<<<<<< zobrazeni veskerych vysledku do noveho FIGURE velke obrazky >>>>>>>>>>>>>

if velke == 1
    
figure(252);
imshow(uint8(obr));                                         % puvodni obraz
title('Puvodni obraz','Fontsize',12,'color','blue');
    
figure(253);
imshow(uint8(S1.*255));                                     % klic
title('Klic vygenerovany k obrazu','Fontsize',12,'color','blue');
 
figure(255);
imshow(uint8(Obr_uprav.*255));
imwrite(uint8(Obr_uprav),'Vlozene_pixely.bmp');
title('Uprava danych koeficientu','Fontsize',12,'color','blue');
    
figure(254);
imshow(uint8(WO));
title('Obraz s vlozenym vodoznakem ','Fontsize',12,'color','blue');

end

% >>>>>>>>>>>>>>>>>> PSNR obrazu s vodoznakem >>>>>>>>>>>>>>>>>>>>>>>>> 

obr_original = double(x_source);
obr_vodoznak = double(WO);
obr_velikost = double(PO_sirka*PO_vyska);
MSE=(sum(sum((obr_original-obr_vodoznak).^2)))/obr_velikost;
PSNR=10*log10(255^2/(MSE));

save S1                     % ulozeni klice na disk kvuli pozdejsimu pouziti pri dekodovani
save hladina                % cislo hladiny jiz nemusime odecitat 8
save W0                     % vodoznaceny obraz
save OH                     % kvuli rychlejsimu dekodovani ulozime hladinu puvodniho obrazu

end