function watermarkgui(action);
%/------------------------------------------\
%| ELE 585                                  |
%| Final Project                            | 
%|                                          |
%| Watermarking an Image using blue channel |
%| amplitude modulation                     |
%\------------------------------------------/
%
% University of Rhode Island
% Dept. of Electrical Engineering
% Roger Meier, May '99
%
%
% -------> to start type 'watermarkgui'
%

if nargin<1,
   action='0';
end
if strmatch('#', action) 
	action=action(2:end);
else
	action='0';
end;


switch action
case '0',
   step0;
case '1',
   step1;
case '2',
   step2;
case '3',
   step3;
case '4',
   step4;
case '5',
   step5;
case 'updateslider1',
   updateslider(1);
case 'updateslider2',
   updateslider(2);
case 'show1',
   show(1);
case 'show2',
   show(2);
   
end;    % switch action


% End of function watermarkgui


% ================================================= %
%  STEP 0: Initializing GUI and loading image file  %
% ================================================= %
function step0;

% Initializing Figure
% -------------------
screen=get(0,'ScreenSize');
switch computer
case 'PCWIN',
   screen=[3 -20 screen(3)-6 screen(4)];
end
%screen=[100 100 640 480];
figNumber=figure( ...
        'Name','Embed Watermark', ...
        'NumberTitle','off', ...
        'MenuBar','none',...
        'IntegerHandle','off', ...
        'PaperOrientation','Landscape',...
        'Position',screen);

% Creating title bar
% ------------------
h1  = uicontrol('Style', 'Frame', ...
				'Units','Normalized',...
				'Position',[0 0.917 1 0.083],...	
                'BackgroundColor',[0.50 0.50 0.50], ...
				'ForegroundColor',[0 0 0]);
h2  = uicontrol('Style','Text',...
                'String','Load Image File...',...
				'Units','Normalized',...
				'HorizontalAlignment','left',...
			    'Position',[0.031 0.934 0.938 0.05],...
                'BackgroundColor',[0.50 0.50 0.50], ...
				'ForegroundColor',[0.9 0.9 0.9],...
			    'FontSize',[18],...
			    'FontWeight','bold');


% Creating bottom bar with controls
% ---------------------------------
h3  = uicontrol('Style', 'Frame', ...
				'Units','Normalized',...
				'Position',[0 0 1 0.083],...	
                'BackgroundColor',[0.50 0.50 0.50], ...
				'ForegroundColor',[0 0 0]);
h4  = uicontrol('Style','PushButton',...
                'String','Prev',...
				'Units','Normalized',...
				'Position',[0.031 0.021 0.094 0.042],...
				'Visible','off',...
				'Callback','close; watermarkgui #0');
h5  = uicontrol('Style','PushButton',...
                'String','Next',...
				'Units','Normalized',...
				'Position',[0.125 0.021 0.094 0.042],...
				'Callback','watermarkgui #1');
h5a = uicontrol('Style','PushButton',...
                'String','Show Original',...
				'Units','Normalized',...
				'Position',[0.24 0.021 0.16 0.042],...
				'Visible','off',...
				'Callback','watermarkgui #show1');
h6  = uicontrol('Style','PushButton',...
                'String','Quit',...
				'Units','Normalized',...
			    'Position',[0.875 0.021 0.094 0.042],...
			    'Callback','close');
h7  = uicontrol('Style','Text',...
                'String','Step 0',...
				'Units','Normalized',...
				'HorizontalAlignment','center',...
			    'Position',[0.4 0.021 0.450 0.05],...
                'BackgroundColor',[0.50 0.50 0.50], ...
				'ForegroundColor',[0.9 0.9 0.9],...
			    'FontSize',[18],...
			    'FontWeight','bold');

% Loading image file and converting it to RGB
% -------------------------------------------
[fname,pname] = uigetfile('*.*','Choose image file to be watermarked',100,100);
if fname == 0
	close;
	break;
end
[im,map]=imread([pname fname]);
if size(im,3) ~= 3
	fig.RGB=255*double(ind2rgb(im,map));
else
	fig.RGB=double(im);
end

% Calculating luminance of the image file
% ---------------------------------------
fig.lum=0.299*fig.RGB(:,:,1) + 0.587*fig.RGB(:,:,2) + 0.114*fig.RGB(:,:,3);
		

% Initiating userdata and attach it to the current figure
% -------------------------------------------------------
fig.fname=fname;
fig.axes=[];
fig.text=[];
fig.topbar=[h1 h2];
fig.botbar=[h3 h4 h5 h6 h7 h5a];
fig.strength=0.1;
fig.density=0.55;
fig.signature='Signature';
set(figNumber, 'UserData', fig);

% Go to Step 1
% ------------
watermarkgui #1;


% ============================= %
%  STEP 1: Entering parameters  %
% ============================= %
function step1;

% Recovering user data, updating GUI
% ----------------------------------
fig=get(gcf,'UserData');
set(fig.topbar(2),'String','Enter Parameters')
set(fig.botbar(2),'Visible','on',...
                  'Callback','close; watermarkgui #0')
set(fig.botbar(3),'Callback','watermarkgui #2')
set(fig.botbar(5),'String','Step 1')
delete(fig.axes); fig.axes=[];
delete(fig.text); fig.text=[];

% Creating textbox for signature
% ------------------------------
posx=0.75; posy=0.614; dx=0.25; dy=0.17;
h9  = uicontrol('Style', 'Frame', ...
				'Units','Normalized',...
				'Position',[posx posy dx dy],...	
                'BackgroundColor',[0.60 0.60 0.60], ...
				'ForegroundColor',[0 0 0]);
h10 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.105 dx-0.05 0.04],...
                'Style','Text',...
			    'FontSize',[10],...
			    'FontWeight','bold',...
			    'String','Signature');
h11 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.025 dx-0.05 0.06],...
                'BackgroundColor',[1 1 1], ...
                'Style','Edit',...
			    'String',fig.signature);

% Creating slider for signature strength
% --------------------------------------
posx=0.75; posy=0.414; dx=0.25; dy=0.17;
h12 = uicontrol('Style', 'Frame', ...
				'Units','Normalized',...
				'Position',[posx posy dx dy],...	
                'BackgroundColor',[0.60 0.60 0.60], ...
				'ForegroundColor',[0 0 0]);
h13 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.105 dx-0.05 0.04],...
                'Style','Text',...
			    'FontSize',[10],...
			    'FontWeight','bold',...
			    'String','Signature Strength');
h14 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.025 dx-0.05 0.04],...
                'Style','slider',...
				'Value',fig.strength,...
				'Min',0,'Max',1,...
				'SliderStep',[0.05 0.25],...
				'Callback','watermarkgui #updateslider1');
h15 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.065 dx-0.05 0.045],...
                'Style','Text',...
			    'FontSize',[14],...
			    'String',num2str(get(h14,'Value'),'%0.2f'));

% Creating slider for density parameter
% -------------------------------------
posx=0.75; posy=0.214; dx=0.25; dy=0.17;
h16 = uicontrol('Style', 'Frame', ...
				'Units','Normalized',...
				'Position',[posx posy dx dy],...	
                'BackgroundColor',[0.60 0.60 0.60], ...
				'ForegroundColor',[0 0 0]);
h17 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.105 dx-0.05 0.04],...
                'Style','Text',...
			    'FontSize',[10],...
			    'FontWeight','bold',...
			    'String','Density Parameter');
h18 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.025 dx-0.05 0.04],...
                'Style','slider',...
				'Value',fig.density,...
				'Min',0,'Max',1,...
				'SliderStep',[0.05 0.25],...
				'Callback','watermarkgui #updateslider2');
h19 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.065 dx-0.05 0.045],...
                'Style','Text',...
			    'FontSize',[14],...
			    'String',num2str(get(h18,'Value'),'%0.2f'));

% Displaying image file
% ---------------------
h8  = axes('Units','normalized', ...
           'Position',[0.025 0.16 0.7 0.7]);
imshow(uint8(fig.RGB))

% Displaying image properties
% ---------------------------
H=size(fig.RGB,1);
W=size(fig.RGB,2);
totalpixels=H*W;
prop=['Filename: ' fig.fname,...
      '     Height: ' num2str(H),...
      '   Width: ' num2str(W),...
      '     Total Pixels: ' num2str(totalpixels)];
h8a = uicontrol('Units','normalized', ...
				'Position',[0.025 0.114 0.7 0.04],...
                'Style','Text',...
             	'BackgroundColor',[0.8 0.8 0.8],...
             'FontSize',[10],...
			    'String',prop);



% Initiating userdata and attach it to the current figure
% -------------------------------------------------------
fig.edit=[h9 h10 h11];
fig.slider=[h12 h13 h14 h15 h16 h17 h18 h19];
fig.axes=[h8];
fig.text=[h8a];
set(gcf, 'UserData', fig);


% ===================================================== %
%  STEP 2: Calculating and Showing Embedding Positions  %
% ===================================================== %
function step2;

% Recovering user data, updating GUI
% ----------------------------------
fig=get(gcf,'UserData');
delete(fig.axes); fig.axes=[];
if length(fig.edit) > 0
	fig.signature=get(fig.edit(3),'String');
	delete(fig.edit); fig.edit=[];
end
if length(fig.slider) > 0
	fig.strength=round(100*get(fig.slider(3),'Value'))/100;
	fig.density=round(100*get(fig.slider(7),'Value'))/100;
	delete(fig.slider); fig.slider=[];
end
delete(fig.text); fig.text=[];
set(fig.topbar(2),'String','Calculated Embedding Positions')
set(fig.botbar(2),'Visible','on',...
                  'Callback','watermarkgui #1')
set(fig.botbar(3),'Callback','watermarkgui #3')
set(fig.botbar(5),'String','Step 2')

% Calculating seed
% ----------------
rand('state',sum(100*clock));
fig.seed=round(9999*rand);

% Feeding random number generator with seed
% -----------------------------------------
rand('state',fig.seed);

% Calculating embedding positions
% -------------------------------
H=size(fig.RGB,1);
W=size(fig.RGB,2);
fig.emb = (rand(H,W) < fig.density);
[y,x] = find(fig.emb);
fig.pos = [y x];
fig.posnum = length(x);

% Displaying embedding positions
% ------------------------------
h8=axes('Units','normalized', ...
        'Position',[0.025 0.15 0.7 0.7]);
imshow(fig.emb)
title('White Pixels:  embedding positions',...
      'FontSize',12,'FontWeight','bold')     

% Converting signature into bitstring
% -----------------------------------
bit1=dec2bin(double(fig.signature),7);
bit2='';
for k = 1:size(bit1,1)
	bit2=[bit2 bit1(k,:)];
end

% Adding the bits '0' and '1' to the bitstring
% to allow to define an adaptive threshold which
% improves signature retrieval. This also defines
% a geometrical reference which is used to counter
% geometrical attacks.
% ------------------------------------------------
bit2=['0' '1' bit2];

% Converting the bitstring to a real vector
% -----------------------------------------
fig.bitlength=length(bit2);
fig.bit=zeros(1,fig.bitlength);
for k = 1:fig.bitlength
	fig.bit(k)=str2num(bit2(k));
end

% Displaying the bitstring
% ------------------------
switch computer
	case 'PCWIN',
  	 st='Edit';
  	 en='off';
otherwise
   st='Text';
   en='on';
end
posx=0.75; posy=0.113; dx=0.25; dy=0.574;
h23  = uicontrol('Style', 'Frame', ...
				'Units','Normalized',...
				'Position',[posx posy dx dy],...	
                'BackgroundColor',[0.60 0.60 0.60], ...
				'ForegroundColor',[0 0 0]);
h24 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.479 dx-0.05 0.07],...
                'Style','Text',...
			    'FontSize',[10],...
			    'FontWeight','bold',...
			    'String',strvcat('Signature:',[num2str(fig.bitlength) ' Bits']));
h25 = uicontrol('Units','normalized', ...
                'Style',st,...
                'Enable',en,...
				'Max',2,...
				'Position',[posx+0.025 posy+0.025 dx-0.05 0.434],...
                'BackgroundColor',[1 1 1], ...
                'String',bit2);

% Displaying number of embedding positions
% ----------------------------------------
posx=0.75; posy=0.717; dx=0.25; dy=0.17;
h26  = uicontrol('Style', 'Frame', ...
				'Units','Normalized',...
				'Position',[posx posy dx dy],...	
                'BackgroundColor',[0.60 0.60 0.60], ...
				'ForegroundColor',[0 0 0]);
h27 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.075 dx-0.05 0.07],...
                'Style','Text',...
			    'FontSize',[10],...
			    'FontWeight','bold',...
			    'String',strvcat('Number of','embedding positions:'));
h28 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.025 dx-0.05 0.04],...
                'BackgroundColor',[1 1 1], ...
                'Style','Text',...
			    'String',num2str(fig.posnum));



% Initiating userdata and attach it to the current figure
% -------------------------------------------------------
fig.axes=[h8];
fig.text=[h23 h24 h25 h26 h27 h28];
set(gcf, 'UserData', fig);

% ================================= %
%  STEP 3: Embedding the Signature  %
% ================================= %
function step3;

% Recovering user data, updating GUI
% ----------------------------------
fig=get(gcf,'UserData');
delete(fig.axes); fig.axes=[];
delete(fig.text); fig.text=[];
if length(fig.edit) > 0
	delete(fig.edit); fig.edit=[];
end
set(fig.topbar(2),'String','Embedding Data in Blue Channel')
set(fig.botbar(2),'Visible','on',...
                  'Callback','watermarkgui #2')
set(fig.botbar(3),'Callback','watermarkgui #4')
set(fig.botbar(5),'String','Step 3')
set(fig.botbar(6),'Visible','off');

% Feeding random number generator with seed
% -----------------------------------------
rand('state',fig.seed);

% 'Shuffeling' the positions of the embedding bits
% ------------------------------------------------
order=randperm(fig.posnum);
fig.pos=fig.pos(order,:);

% Generating the watermark bitstring of length fig.posnum
% by lining up copies of the bitstring
% -------------------------------------------------------
fig.watermark=zeros(fig.posnum,1);
for k=1:floor(fig.posnum/fig.bitlength)
   fig.watermark(fig.bitlength*(k-1)+1:fig.bitlength*k)=fig.bit';
end
remain=fig.posnum-fig.bitlength*floor(fig.posnum/fig.bitlength);
fig.watermark(fig.posnum-remain+1:fig.posnum)=fig.bit(1:remain)';

% Watermarking the image
% ----------------------
H=size(fig.RGB,1);
W=size(fig.RGB,2);
B=fig.RGB(:,:,3);
Bnew=B;
y=fig.pos(:,1);
x=fig.pos(:,2);
num=y+H*(x-1); % Converting XY Position to Pixel number
Bnew(num) = B(num) + ((2*fig.watermark-1) .* fig.lum(num) .* fig.strength);

% Displaying difference between blue channels
% -------------------------------------------
dif=Bnew-B;
colormap(gray(256))
h8=axes('Units','normalized', ...
        'Position',[0.025 0.15 0.7 0.7]);
imagesc(dif)
axis image
axis off
h8b=axes('Units','normalized', ...
        'Position',[0.8 0.15 0.1 0.7]);
imagesc(dif)
colorbar(h8b);
h8a = uicontrol('Units','normalized', ...
				'Position',[0.025 0.855 0.95 0.05],...
                'Style','Text',...
             	'BackgroundColor',[0.8 0.8 0.8],...
             'FontSize',[12],...
             'FontWeight','bold',...
			    'String','Difference between original and modified blue channel');


% Initiating userdata and attach it to the current figure
% -------------------------------------------------------
fig.axes=[h8 h8b];
fig.text=[h8a];
fig.Bnew=Bnew;
set(gcf, 'UserData', fig);


% ============================ %
%  STEP 4: Creating new Image  %
% ============================ %
function step4;

% Recovering user data, updating GUI
% ----------------------------------
fig=get(gcf,'UserData');
delete(fig.axes); fig.axes=[];
delete(fig.text); fig.text=[];
set(fig.topbar(2),'String','Creating new Image')
set(fig.botbar(2),'Visible','on',...
                  'Callback','watermarkgui #3')
set(fig.botbar(3),'Visible','on',...
                  'Callback','watermarkgui #5')
set(fig.botbar(5),'String','Step 4')
set(fig.botbar(6),'Visible','on');

% Creating new image
% ------------------
under=fig.Bnew < 0;  % setting all elements < 0 in new blue channel to zero
under=find(under);
fig.Bnew(under)=0;
over=fig.Bnew > 255; % setting all elements > 255 in new blue channel to 255
over=find(over);
fig.Bnew(over)=255;
fig.RGBnew=fig.RGB;
fig.RGBnew(:,:,3)=fig.Bnew;
fig.RGBnew=uint8(fig.RGBnew);

% Displaying watermarked image
% ----------------------------
h8=axes('Units','normalized', ...
        'Position',[0.025 0.16 0.7 0.7]);
h8a = uicontrol('Units','normalized', ...
				'Position',[0.025 0.855 0.95 0.05],...
                'Style','Text',...
             	'BackgroundColor',[0.8 0.8 0.8],...
             'FontSize',[12],...
             'FontWeight','bold',...
			    'String','The watermarked image');

% Calculating and displaying retrieval code
% -----------------------------------------
if fig.seed > 1000
   seedcode=num2str(fig.seed);
elseif fig.seed > 100
   seedcode=['0' num2str(fig.seed)];
elseif fig.seed > 10
   seedcode=['00' num2str(fig.seed)];
else
   seedcode=['000' num2str(fig.seed)];
end
if fig.density == 1
   denscode=num2str(100*fig.density);
else
   if fig.density >= 0.1
      denscode=['0' num2str(100*fig.density)];
   else
      denscode=['00' num2str(100*fig.density)];
   end
end
lengthcode=num2str(fig.bitlength);
fig.code=[seedcode denscode lengthcode];
posx=0.75; posy=0.414; dx=0.25; dy=0.17;
h16  = uicontrol('Style', 'Frame', ...
				'Units','Normalized',...
				'Position',[posx posy dx dy],...	
                'BackgroundColor',[0.60 0.60 0.60], ...
				'ForegroundColor',[0 0 0]);
h17 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.105 dx-0.05 0.04],...
                'Style','Text',...
			    'FontSize',[10],...
			    'FontWeight','bold',...
			    'String','Retrieval Code');
h18 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.025 dx-0.05 0.06],...
                'BackgroundColor',[1 1 1], ...
                'Style','Edit',...
			    'String',fig.code);
      
   

% Initiating userdata and attach it to the current figure
% -------------------------------------------------------
fig.axes=[h8];
fig.text=[h8a];
fig.edit=[h16 h17 h18];
set(gcf, 'UserData', fig);

show(2);


% ========================== %
%  STEP 5: Saving new Image  %
% ========================== %
function step5;

% Recovering user data, updating GUI
% ----------------------------------
fig=get(gcf,'UserData');
set(fig.topbar(2),'String','Saving new Image File...')
set(fig.botbar(2),'Visible','off')
set(fig.botbar(3),'Visible','off')
set(fig.botbar(5),'String','Step 5')
set(fig.botbar(6),'Visible','off');

% Saving image file
% -----------------
[fname,pname] = uiputfile('*.tif','Save Image File',100,100);
if fname == 0
	watermarkgui #4;
else
   imwrite(fig.RGBnew,[pname fname],'tif')
   close
end



% ========================= %
%  Various Local Functions  %
% ========================= %
function updateslider(n);

fig=get(gcf,'UserData');
slider=[fig.slider(4*(n-1)+3) fig.slider(4*n)];
set(slider(2),'String',num2str(round(100*get(slider(1),'Value'))/100,'%0.2f'))


function show(n)

fig=get(gcf,'UserData');
switch n
	case 1;
		imshow(uint8(fig.RGB));
		set(fig.text,'String','Original Image');
		set(fig.botbar(6),'String','Show Watermarked',...
		                  'Callback','watermarkgui #show2');
	case 2;
		imshow(fig.RGBnew);
		set(fig.text,'String','Watermarked Image');
		set(fig.botbar(6),'String','Show Original',...
		                  'Callback','watermarkgui #show1');
end
	
