%
% All.m
%
% For a specified light field, lambda value and disparity value pdf, 
% this function returns the resulting distortion and rate for
% encoding the light field reference image using the specified
% scheme
%
%

function [R, D, pdfout, Ipredict] = All(Itarget, Irefs, lambda, ...
										indices, pdfin, ...
										blocksize, scheme)

% split image into blocks
[r,c] = size(Itarget);
numRblocks = r/blocksize;
numCblocks = c/blocksize;

% other initialization
pdfout = zeros(size(pdfin));
R = 0;
D = 0;
Ipredict = zeros(size(Itarget));

for i=1:numRblocks
  for j=1:numCblocks

	if (strcmp(scheme,'std'))
	  [Rij, Dij, pdfij, predBlock] = ...
		  StandardDisparity(Itarget, Irefs, lambda, ...
							indices, pdfin, ... 
							i, j, blocksize);
	elseif (strcmp(scheme,'h1'))
	  [Rij, Dij, pdfij, predBlock] = ...
		  SingleHypoDisparity(Itarget, Irefs, ...
							  lambda, ...
							  indices, pdfin, ...
							  i, j, blocksize);
	elseif (strcmp(scheme,'h2'))
	  [Rij, Dij, pdfij, predBlock] = ...
		  TwoHypoDisparity(Itarget, Irefs, ...
						   lambda, ...
						   indices, pdfin, ...
						   i, j, blocksize);
	elseif (strcmp(scheme,'switch'))
	  % pick the scheme that produces the minimum D + lambda*R
	  [Rij, Dij, pdfij, predBlock] = ...
		  StandardDisparity(Itarget, Irefs, lambda, ...
							indices, pdfin, ... 
							i, j, blocksize);
	  Jmin = Dij + lambda*Rij;
	  Rmin = Rij;
	  Dmin = Dij;
	  predBlockMin = predBlock;
	  
	  [Rij, Dij, pdfij, predBlock] = ...
		  SingleHypoDisparity(Itarget, Irefs, ...
							  lambda, ...
							  indices, pdfin, ...
							  i, j, blocksize);
	  Jcurr = Dij + lambda*Rij;
	  if (Jcurr<Jmin)
		Rmin = Rij;
		Dmin = Dij;
		Jmin = Jcurr;
		predBlockMin = predBlock;
	  end
	  
	  [Rij, Dij, pdfij, predBlock] = ...
		  TwoHypoDisparity(Itarget, Irefs, ...
						   lambda, ...
						   indices, pdfin, ...
						   i, j, blocksize);
	  Jcurr = Dij + lambda*Rij;
	  if (Jcurr<Jmin)
		Rmin = Rij;
		Dmin = Dij;
		Jmin = Jcurr;
		predBlockMin = predBlock;
	  end
	  
	  Rij = Rmin + log2(3);
	  Dij = Dmin;
	  predBlock = predBlockMin;
	end

	Ipredict((i-1)*blocksize+1:i*blocksize, ...
			 (j-1)*blocksize+1:j*blocksize) = ...
		predBlock;
	
	R = R + Rij;
	D = D + Dij;
	pdfout = pdfout + pdfij;

	[dummy, index] = max(pdfij);
	
  end
end

R = R / (numRblocks*numCblocks);
D = D / (numRblocks*numCblocks);

