function task5()

% read image
img = double(imread('lenag.png'));

% Shift image values to a range between -127 and 128
%img = TODO

% number of decomposition levels
ndec = 3;


% quantization weight ("tau" in the work sheet)
qweight = 2^(7.5 - 8 + ndec) * (1 + 8/2^11);

% Perform compression and decompression
% TODO = compress(img, ndec, qweight);
% restored = decompress(TODO, size(img), ndec, qweight);

% Display images
figure(3)
subplot(1, 3, 1)
imagesc(img + 127.);
subplot(1, 3, 2)
imagesc(restored + 127.);
subplot(1, 3, 3)
imagesc(abs(img - restored));
colormap gray;
%colormap jet; % potentially more useful for visualizing details in the difference image than "colormap gray".

% root mean square error between input image and reconstructed image
fprintf(1, 'RMSE: %.2f\n', sqrt(mean((img(:) - restored(:)).^2)));

end

%--------------------------------------------------------------------------
% Compression similar to JPEG 2000
%--------------------------------------------------------------------------
function TODO = compress(signal, ndecs, qweight)

% get filter coefficients for biorthogonal wavelet
%TODO

% perform multiresolution analysis for ndecs levels
%TODO

% quantize the wavelet coefficients
%TODO

% encode the quantized wavelet coefficients
%TODO

end

%--------------------------------------------------------------------------
% Quantization
%--------------------------------------------------------------------------
function coeffs = quantize(coeffs, ndecs, qweight)

% quantize (i.e., divide without remainder) the wavelet coefficients by the
% quantization levels

% first: create a matrix 'qstep' that contains the quantization level for each wavelet
% coefficient
coeffsize = size(coeffs);
qstep = zeros(coeffsize);
for i = 1:ndecs
    % Set quantization level for current level of decomposition in detailH, detailV
    % qstep(TODO) = TODO
    % Set quantization level for current level of decomposition in detailD
    %qstep(TODO) = TODO
    coeffsize = coeffsize/2;
end

% Set quantization level in the approximation coefficients
%TODO

%figure(1);
%subplot(1, 2, 1);
%imagesc(qstep);
%colormap gray;

% apply quantization levels to the coefficients
%coeffs = TODO

%figure(1);
%subplot(1, 2, 2);
%imagesc(coeffs);
%colormap gray;

end

%--------------------------------------------------------------------------
% Encoding
%--------------------------------------------------------------------------
function TODO = encode(coeffs)

% Prepare partitioning into code blocks of 8x8 coefficients
coeffsize = size(coeffs);
% nblocks = TODO

% Partition into 8x8 code blocks, call encode_block and append the result to the full data stream
stream = [];
for y=1:nblocks(1)
    for x=1:nblocks(2)
        %TODO encode_block(TODO)
        stream = [stream codeblock];
		%optional Haeufigkeitsstatistik ergaenzen
    end 
end

% build Huffman dictionary.
% Compute first the relative frequency of each symbol in the stream
% symbol_probabilities = TODO

% TODO

% print the approximate number of bytes of the data after run-length encoding
% (but before Huffman encoding)
%fprintf(1, 'Bytes after RLE (approx.): %.0f\n', TODO);
% print the approximate number of bytes of the data after Huffman coding
% (estimate from word lengths and relative frequencies of the words)
%fprintf(1, 'Bytes after Huffmann: %.0f\n', TODO);

end

%--------------------------------------------------------------------------
% Supporting function for encode(..) to perform bit plane encoding
%--------------------------------------------------------------------------
function [codeblock] = encode_block(block)

% Overall strategy:
% each bit plane of this block is subject to run length encoding. The encoded
% bit planes are concatenated to a 'codeblock'
%
% The format of a codeblock is:
%      codeblock = [plane_1 plane_2 ...]
%   where
%      plane_i = [number_of_entries_in_run_length_encoding entries_in_run_length_encoding]
%   if plane_i starts with a '1', and
%      plane_i = [number_of_entries_in_run_length_encoding+1 0 entries_in_run_length_encoding]
%   if plane_i starts with a '0'.
% Implement also a special treatment of the case if the whole block consists
% only of zeros. In this case, set
%      codeblock = [0]
%

block = block(:);
% Test if block consists of only zero values:
if TODO
	%TODO	
    return
end
% note: process each bit plane separately


% The number of required bitplanes in this block depends on the maximum
% coefficient value in this block.
% Compute number of bits that are required to represent the largest value in
% this block:
%k = TODO
% First entry of the code block shall be the number of bit planes
% codeblock = TODO

% Special case: take care of the '-' for negative values.
%block = TODO


% Run Length Encoding
for b=1:k
	% plane = TODO
	% Runlength encoding does not need to be a for-loop in matlab (think about it or google for it)

	% Handle special case if first value is 0
    if (plane(1) == 0)
        % codeblock = [codeblock TODO];
    else
        % codeblock = [codeblock TODO];
    end
end

end

%--------------------------------------------------------------------------
% Decompression
%--------------------------------------------------------------------------
function img = decompress(TODO, imgsize, ndecs, qweight)

% call decode on the compressed data using the dictionary
% coeffs = TODO
% dequantize
% coeffs = TODO

% get filter coefficients for biorthogonal wavelet
% TODO

% perform multiresolution synthesis
% img = TODO

end

%--------------------------------------------------------------------------
% Decoding of the full data stream
%--------------------------------------------------------------------------
function coeffs = decode(TODO, imgsize)

% Huffman decompression
%stream = TODO
%nblocks = TODO

coeffs = zeros(imgsize);
for y=1:nblocks(1)
    for x=1:nblocks(2)
        % decode one codeblock
        [codeblock, stream] = % TODO decode_block(TODO);
        % coeffs(TODO) = codeblock;
    end 
end

end

%--------------------------------------------------------------------------
% Decoding of a single block in the data stream
%--------------------------------------------------------------------------
function [codeblock, stream] = decode_block(stream)
% this method works analogously to encode_block

codeblock = zeros(64,1);

% read number of bit planes
planecnt = %TODO
% Handle special case if whole block is empty
if (planecnt == 0)
    % codeblock = TODO
    return;
end

% Remove processed value from stream
stream = stream(2:end);


for b = 1:planecnt
    %planelength = TODO
    % hier kann wieder anhand Fussnote 3 vorgegangen werden
	% Handle special case if first value is 0
    if (len(1) == 0)
        val = %TODO
    else
        val = %TODO
    end
    % weiteres vorgehen nach fussnote 3
	% Set bits of current plane in the result code block
    % codeblock = TODO
    % Remove the processed values from the stream
    % stream = TODO
end

% recover the signs of the coefficients
% codeblock = TODO
codeblock = reshape(codeblock, 8, 8);

end


%--------------------------------------------------------------------------
% Dequantization
%--------------------------------------------------------------------------
function coeffs = dequantize(coeffs, ndecs, qweight)

% Define dequantization levels analogously to quantize()
% TODO

% apply quantization levels to the coefficients
%coeffs = TODO

figure(2);
imagesc(coeffs);
colormap gray;

end

