function retrievegui(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 'retrievegui'
%

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 'updateslider',
   updateslider;
end;    % switch action


% End of function retrievegui


% ================================================= %
%  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','Retrieve 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; retrievegui #0');
h5  = uicontrol('Style','PushButton',...
                'String','Next',...
				'Units','Normalized',...
				'Position',[0.125 0.021 0.094 0.042],...
				'Callback','retrievegui #1');
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 watermarked image file',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

% 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];
fig.cross=3;
fig.code='';
fig.density=0;
fig.bitlength=0;
set(figNumber, 'UserData', fig);

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


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

% Recovering user data, updating GUI
% ----------------------------------
fig=get(gcf,'UserData');
set(fig.topbar(2),'String','Enter Retrieval Code')
set(fig.botbar(2),'Visible','on',...
                  'Callback','close; retrievegui #0')
set(fig.botbar(3),'Visible','on',...
                  'Callback','retrievegui #2')
set(fig.botbar(5),'String','Step 1')
if length(fig.axes) > 0
	legend off
	delete(fig.axes);
	fig.axes=[];
end
if length(fig.text) > 0
	delete(fig.text);
	fig.text=[];
end

% Creating textbox for code
% -------------------------
posx=0.75; posy=0.514; 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);
             
% Creating slider for cross shaped neighborhood
% ---------------------------------------------
posx=0.75; posy=0.314; 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.09 dx-0.05 0.07],...
                'Style','Text',...
			    'FontSize',[10],...
			    'FontWeight','bold',...
			    'String','Size of cross shaped neighborhood');
h14 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.025 dx-0.05 0.04],...
                'Style','slider',...
				'Value',fig.cross/10,...
				'Min',0.1,'Max',1,...
				'SliderStep',[1/9 2/9],...
				'Callback','retrievegui #updateslider');
h15 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.065 dx-0.05 0.045],...
                'Style','Text',...
			    'FontSize',[14],...
			    'String',num2str(10*get(h14,'Value')));
          
% 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=[h16 h17 h18];
fig.slider=[h12 h13 h14 h15];
fig.axes=[h8 h8a];
set(gcf, 'UserData', fig);


% ===================================================== %
%  STEP 2: Retrieving Watermark                         %
% ===================================================== %
function step2;

% Recovering user data, updating GUI
% ----------------------------------
fig=get(gcf,'UserData');
delete(fig.axes);
fig.code=get(fig.edit(3),'String');
fig.seed=str2num(fig.code(1:4));
fig.density=str2num(fig.code(5:7))/100;
fig.bitlength=str2num(fig.code(8:end));
delete(fig.edit); fig.edit=[];
fig.cross=round(10*get(fig.slider(3),'Value'));
delete(fig.slider); fig.slider=[];
set(fig.topbar(2),'String','Extracted Signature')
set(fig.botbar(2),'Visible','on',...
                  'Callback','retrievegui #1')
set(fig.botbar(3),'Visible','off')
set(fig.botbar(5),'String','Step 2')

% 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 number of embedding bits
% -----------------------------------
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 bits:'));
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));

% Extracting blue channel
% -----------------------
B=fig.RGB(:,:,3);

% 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,:);

% Estimating original blue values
% using cross shaped neighborhood
% -------------------------------
cross=zeros(2*fig.cross+1,2*fig.cross+1);
cross(:,fig.cross+1)=1;
cross(fig.cross+1,:)=1;
cross(fig.cross+1,fig.cross+1)=0;
Bold=1/(4*fig.cross) * filter2(cross,B,'same');

% Calculating the differences
% ---------------------------
delta=B-Bold;

% Extracting deltas at embedding positions
% ----------------------------------------
y=fig.pos(:,1);
x=fig.pos(:,2);
num=y+H*(x-1); % Converting XY Position to Pixel number
delta=delta(num);
bitlength=fig.bitlength;

% Extrating and averaging signature bits
% --------------------------------------
bit=zeros(bitlength,1);
for k=1:floor(fig.posnum/bitlength)
   bit=bit+delta(bitlength*(k-1)+1:bitlength*k);
end
bit=bit/floor(fig.posnum/bitlength);

% Calculate adaptive treshhold
% ----------------------------
thres=(bit(1)+bit(2))/2;

% Retrieving signature
% --------------------
valid = (fig.bitlength-2)/7 == round((fig.bitlength-2)/7);
if valid
	sigbin = bit > thres;
	sigbin = sigbin(3:end);
	sigasc = zeros(1,round(length(sigbin)/7));
	for k = 1:length(sigasc)
   	bin = '';
   	for l = 1:7
      	bin=[bin num2str(sigbin(l+7*(k-1)))];
   	end
   	sigasc(k)=bin2dec(bin);
	end
   fig.signature=char(sigasc);
   siglabel='Retrieved Signature';
else
   fig.signature='INVALID RETRIEVAL CODE !!!';
   siglabel='WARNING !!!';
end

% Displaying averaged deltas
% --------------------------
h8  = axes('Units','normalized', ...
           'Position',[0.025 0.16 0.7 0.7]);
one_bits_num = find(bit > thres);
one_bits = bit(one_bits_num);        
zero_bits_num = find(bit < thres);
zero_bits = bit(zero_bits_num);        
plot(one_bits_num,one_bits,'r+',zero_bits_num,zero_bits,'bo')
grid
line([1 bitlength],[thres thres],'Color',[0.7 0.7 0.7],'LineWidth',3)
text(2,thres+0.1*max(bit),['Adaptive Threshold: ' num2str(thres)])
axis([1 bitlength 1.1*min(bit) 1.1*max(bit)])
legend('one bits','zero bits',0);
xlabel('Bit Number')
title('Averaged Differences','FontSize',[12],'FontWeight','bold')

% Displaying signature
% --------------------
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',siglabel);
h18 = uicontrol('Units','normalized', ...
				'Position',[posx+0.025 posy+0.025 dx-0.05 0.06],...
                'BackgroundColor',[1 1 1], ...
                'Style','Text',...
			    'String',fig.signature);



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













% ========================= %
%  Various Local Functions  %
% ========================= %
function updateslider;

fig=get(gcf,'UserData');
slider=[fig.slider(3) fig.slider(4)];
set(slider(2),'String',num2str(round(10*get(slider(1),'Value'))));
