function data = generateImageDenoiseProblem(im, trainnum, blocksize,...
    dictsize, sigma, gain, maxval, initdict)
%%  Generate Image Denoising Problem
%   
%   generateImageDenoiseProblem is a part of the SMALLbox and generates
%   a problem that can be used for comparison of Dictionary Learning/Sparse
%   Representation techniques in image denoising scenario.
%   The function takes as an input:
%   -   im - image matrix (if not present function promts user for an
%            image file) ,
%   -   trainnum - number of training samples (default - 40000)
%   -   blocksize - block (patch) vertical/horizontal dimension (default 8),
%   -   dictsize - dictionary size (default - 256),
%   -   sigma - noise level (default - 20),
%   -   noise gain (default - 1.15),
%   -   maxval - maximum value (default - 255)
%   -   initdict - initial dictionary (default - 4x overcomlete dct)
%
%   The output of the function is stucture with following fields:
%   -   name - name of the original image (if image is read inside of the
%              function)
%   -   Original - original image matrix,
%   -   Noisy - image with added noise,
%	-   b - training patches,
%	-   m - size of training patches (default 64),
%   -   n - number of training patches,
%   -   p - number of dictionary elements to be learned,
%   -   blocksize - block size (default [8 8]),
%   -   sigma - noise level,
%   -   noise gain (default - 1.15),
%   -   maxval - maximum value (default - 255)
%   -   initdict - initial dictionary (default - 4x overcomlete dct)
%   -   signalDim - signal dimension (default - 2)

%
%   Centre for Digital Music, Queen Mary, University of London.
%   This file copyright 2010 Ivan Damnjanovic.
%
%   This program is free software; you can redistribute it and/or
%   modify it under the terms of the GNU General Public License as
%   published by the Free Software Foundation; either version 2 of the
%   License, or (at your option) any later version.  See the file
%   COPYING included with this distribution for more information.
%
%   Based on KSVD denoise demo by Ron Rubinstein
%   See also KSVDDENOISEDEMO and KSVDDEMO.
%   Ron Rubinstein
%   Computer Science Department
%   Technion, Haifa 32000 Israel
%   ronrubin@cs
%   August 2009
%%
disp(' ');
disp('  **********  Denoising Problem  **********');
disp(' ');
disp('  This function reads an image, adds random Gaussian noise,');
disp('  that can be later denoised by using dictionary learning techniques.');
disp(' ');


%% prompt user for image %%
%ask for file name
FS=filesep;
TMPpath=pwd;
if ~ exist( 'im', 'var' ) || isempty(im)
    [pathstr1, name, ext] = fileparts(which('SMALLboxSetup.m'));
    cd([pathstr1,FS,'data',FS,'images']);
    [filename,pathname] = uigetfile({'*.png;'},'Select an image');
    [pathstr, name, ext] = fileparts(filename);
    data.name=name;
    im = imread(filename);
    %im = double(im);
end;
im = double(im);
cd(TMPpath);

%% check input parameters %%

if ~ exist( 'blocksize', 'var' ) || isempty(blocksize),blocksize = 8;end
if ~ exist( 'dictsize', 'var' ) || isempty(dictsize), dictsize = 256;end
if ~ exist( 'trainnum', 'var' ) || isempty(trainnum),trainnum = 40000;end
if ~ exist( 'sigma', 'var' ) || isempty(sigma), sigma = 20; end
if ~ exist( 'gain', 'var' ) || isempty(gain), gain = 1.15; end
if ~ exist( 'maxval', 'var' ) || isempty(maxval), maxval = 255; end
if ~ exist( 'initdict', 'var' ) || isempty(initdict), initdict = 'odct'; end

%% generate noisy image %%

disp(' ');
disp('Generating noisy image...');

n = randn(size(im)) * sigma;
imnoise = im + n;

%% set parameters %%

x = imnoise;
p = ndims(x);
psnr=20*log10(maxval * sqrt(numel(im)) / norm(im(:)-imnoise(:)));
if (p==2 && any(size(x)==1) && length(blocksize)==1)
    p = 1;
end

% blocksize %

if (numel(blocksize)==1)
    blocksize = ones(1,p)*blocksize;
end

if (strcmpi(initdict,'odct'))
    initdict = odctndict(blocksize,dictsize,p);
elseif (strcmpi(initdict,'data'))
    clear initdict;    % causes initialization using random examples
else
    error('Invalid initial dictionary specified.');
end

if exist( 'initdict', 'var' )
    initdict = initdict(:,1:dictsize);
end

%%%% create training data %%%

ids = cell(p,1);
if (p==1)
    ids{1} = reggrid(length(x)-blocksize+1, trainnum, 'eqdist');
else
    [ids{:}] = reggrid(size(x)-blocksize+1, trainnum, 'eqdist');
end
X = sampgrid(x,blocksize,ids{:});

% remove dc in blocks to conserve memory %

bsize = 2000;
for i = 1:bsize:size(X,2)
    blockids = i : min(i+bsize-1,size(X,2));
    X(:,blockids) = remove_dc(X(:,blockids),'columns');
end

%  Noisy image blocks 
xcol=im2colstep(x,blocksize);
[b1, dc] = remove_dc(xcol,'columns');

%% output structure %%

data.Original = im;
data.Noisy = imnoise;
data.noisy_psnr=psnr;
data.b = X;
data.b1=b1;
data.b1dc=dc;
data.m = size(X,1);
data.n = size(X,2);
data.p = dictsize;
data.blocksize=blocksize;
data.sigma = sigma;
data.gain = gain;
data.maxval = maxval;
data.initdict= initdict;
data.signalDim=2;
data.sparse=1;
end %% end of function