%EUSIPCO 2012
%Imperial College London 
%Andriy Gelman, Jon Onativia and Pier Luigi Dragotti 

function [output, uncovered] = inverse_lifting_view_haar_1_decomposition(low, high, label, D, string2, intra, motionVect)

global block_compensation_size;

intra(intra>0) = 1;

wavelet_coefficients = zeros(size(label));
wavelet_coefficients(:,:,1:2:end) = low;
wavelet_coefficients(:,:,2:2:end) = high;

[r,c, number_of_images] = size(wavelet_coefficients);
number_of_layers = length(D);

%initialize output
output = zeros(r,c,number_of_images);

label(label == -1) = max(max(max(label)));

if strcmp(string2, 'ceil') == 1
    disparity = ceil(([0:1: number_of_images-1])'*D');
else
    disparity = round(([0:1: number_of_images-1])'*D');
end


%uncovered pixels appear in frame 2  
uncovered = zeros(r,c,number_of_images/2);
    
for i = 1:number_of_images/2
    %note label is the original label 
    low_pass = wavelet_coefficients(:,:,2*i-1);
    high_pass = wavelet_coefficients(:,:,2*i);
    label_buffer = label(:,:,2*i-1:2*i);
    disparity_buffer = disparity(2*i-1:2*i,:);
    
    %covered pixels are not visible in frame 2
    covered = zeros(r,c);

	%evaluate all uncovered pixels - to evaluate the high pass label
    for l = 1:number_of_layers
        %Update uncovered areas   
        [connected_pixels, new_uncovered_pixels] = evaluate_uncovered_pixels(label_buffer, l, disparity_buffer(2,l) - disparity_buffer(1,l));   
        uncovered(:,:,i) = uncovered(:,:,i) + new_uncovered_pixels;
    end
    buffer = uncovered(:,:,i);
    buffer(buffer>0) = 1;    
    %buffer(intra(:,:,i) > 0) = 0;
    high_pass_label = -(buffer-1);
    

    %Apply inverse update step 
    for l = 1:number_of_layers

        [connected_pixels, new_covered_pixels] = evaluate_covered_pixels(label_buffer, l, disparity_buffer(2,l) - disparity_buffer(1,l));   
        covered = covered + new_covered_pixels;   
    
        output(:,:,2*i-1) = output(:,:,2*i-1) + (low_pass - disparity_comp(high_pass, high_pass_label, D(l), 2, 1)).*connected_pixels;   
    end
    output(:,:,2*i-1) = output(:,:,2*i-1) + low_pass.*covered; 

    %Apply inverse prediction step

    low_pass_label = label(:,:,2*i-1);
    low_pass_label(low_pass_label>0)=1;
    
    %Apply prediction high-pass step
    for l = 1:number_of_layers
        %Update uncovered areas   
        [connected_pixels] = evaluate_uncovered_pixels(label_buffer, l, disparity_buffer(2,l) - disparity_buffer(1,l));   
    
        %apply prediction step to the connected pixels 
    
        output(:,:,2*i) = output(:,:,2*i) + (2*high_pass + disparity_comp(output(:,:,2*i-1), low_pass_label, D(l), 1, 2)).*connected_pixels;
    
        %high_pass = high_pass + ((input(:,:,2) - disparity_comp(input(:,:,1), ones(size(input(:,:,1))), D(l), 1, 2))/2).*connected_pixels;    
    end

    output(:,:,2*i) = output(:,:,2*i) + high_pass.*uncovered(:,:,i);

    %set the pixels at intra locations to zero - as these pixels will be
    %added back in the following stage - (due implementation)
    %{
    buffer_output = output(:,:,2*i);
    buffer_output(intra(:,:,i) > 0) = 0;
    output(:,:,2*i) = buffer_output;
    
    %apply inverse back prediction to data
    if ~isempty(motionVect{i})
        w = cd;    
        cd('..\..\block matching software\BlockMatchingAlgoMPEG');
        imgComp = motionComp(output(:,:,2*i-1), motionVect{i}, block_compensation_size).*intra(:,:,i);
        output(:,:,2*i) = output(:,:,2*i) + (2*high_pass + imgComp).*intra(:,:,i);
        cd(w);
    end
    %}
    
end
end



function [connected_pixels, intra_pixels] = evaluate_uncovered_pixels(label, layer_val, disparity)

    layer = extract_layer(label, label, layer_val);
    layer(layer>0) = 1;
    layer_frame_1 = layer(:,:,1);
    layer_frame_2 = layer(:,:,2);
    
    %disparity compensate frame 1 onto frame 2
    layer_frame_1 = integer_shift(layer_frame_1, disparity );
    
    intra_pixels = layer_frame_2 - layer_frame_1;
    
    intra_pixels((intra_pixels)>0)=1;
    intra_pixels(intra_pixels<0) = 0;
    
    connected_pixels = layer_frame_2;
    connected_pixels(intra_pixels == 1) =0;
end

function [connected_pixels, intra_pixels] = evaluate_covered_pixels(label, layer_val, disparity)

    layer = extract_layer(label, label, layer_val);
    layer(layer>0) = 1;
    layer_frame_1 = layer(:,:,1);
    layer_frame_2 = layer(:,:,2);
    
    %disparity compensate frame 1 onto frame 2
    layer_frame_2 = integer_shift(layer_frame_2, -disparity );
    
    intra_pixels = layer_frame_1 - layer_frame_2;
    
    intra_pixels((intra_pixels)>0)=1;
    intra_pixels(intra_pixels<0) = 0;

    connected_pixels = layer_frame_1;
    connected_pixels(intra_pixels == 1) =0;
end
