function [QI,ET] = SDQI(A, PROC, GRAD)

%=====================================================================
% No-Reference Image Quality Measurement
% Written by Meisam Rakhshnfar, Vidpro Lab
% (http://users.encs.concordia.ca/~amer/SDQI/)
% Revised: February 2016
%
% Copyright Notice:
%  Copyright (c) 2014-2016 Concordia University
%  All Rights Reserved.
%=====================================================================


% SDQI(A)
 
%   A can be an M-by-N (grayscale image) or M-by-N-by-3 (rgb color image)
%   array.  A cannot be an empty array or very small matrix.

% SDQI(A,PROC)

%   PROC defines the processor can be 'CPU' or 'GPU'.
%   default is 'CPU'.
%   For GPU case it first compiles the OpenCL kernels.
%   It's tested only on NVIDIA graphic cards and Windows OS.

% SDQI(A,PROC,GRAD)
%   PROC defines the processor can be 'CPU' or 'GPU' or empty = 'CPU'.
%   GRAD defines the gradient : 'Normal' or 'Sobel'

%  OUTPUTS:
%   QI is the estimated quality index of the image. Can be negative
%   ET is the elappsed time.
%   Note: For GPU there is a setup time (including: getting GPU device info,
%   compiling the kernels and transfreing the data into GPU) which is not
%   considered in the elappsed time. 

%%%
%%% parse input parameters
%%%
if (nargin==0)
    error('Input image is required');
end
if (nargin==1)
    prc = 0; 
    grd = 0;
elseif (nargin>1)
    grd = 0;
    if (strcmpi(PROC,'CPU'))
        prc = 0;
    elseif (strcmpi(PROC,'GPU'))
        prc = 1;
    elseif isempty(PROC)
        prc = 0;
    else
        error('PROC should be either ''CPU'' or ''GPU');
    end    
elseif (nargin>2)
    if (strcmpi(GRAD,'Normal'))
        grd = 0;
    elseif (strcmpi(GRAD,'Sobel'))
        grd = 1;
    elseif isempty(GRAD)
        grd = 0;
    else
        error('GRAD should be either ''Normal'' or ''Sobel');
    end
    
else    
    error('Too many input parameters');
end
    
if (size(A,3)==3)
    % input assmed to RGB
    A = rgb2ycbcr(A);
    A = double(A(:,:,1));
elseif (size(A,3)==1)
    A = double(A);
else
    error('Input image should be either grayscale or RGB');
end
    
A = padarray(A,8*ceil(size(A)/8)-size(A),'post','symmetric');

if (any(size(A)<80))
    error('Too Small Image');
end
    
% call mex function of SDQI
if prc == 0
    Out = sdqimex_nogpu(single(A),single([prc grd]));
else
    Out = sdqimex(single(A),single([prc grd]));
end

QI = Out(1); % Quality Index
ET = Out(2); % Estimated time

