function [normRectImg, normBinImg, normPts] = ...
      normrect( img, binImg, guides, rect, params, opts)
% NORMRECT Get normalized images for recognition
%
%  [NORMRECTIMG, NORMBINIMG, NORMPTS] = NORMRECT( IMG, BINIMG, GUIDES, RECT, 
%                                                 PARAMS, OPTS) where 
%
% Inputs:
%  img        Color text image (double)
%  binImg     Binarized text image (logical)
%  guides     Struct of text guideline coordinates
%  rect       Text bounding rectangle [ x y w h]
%  params     Struct of required parameters
%  opts       Struct of configuration options
%
%    PARAMS is not used
%
%    OPTS may have the following fields:
%       normNumControlPts
%       normImgInterp
%       normImgFill
%       normBinInterp
%       normBinFill
%
% Outputs:
%  normRectImg  Normalized color text image (double)
%  normBinImg   Normalized binary text image (double)
%  normPts      Struct (fields in, out, bounds) contains in/out control points
%                 and output bounds is [left right bottom height].


% Copyright (c) 2014
% Jerod Weinman
% jerod@acm.org

% $Id: normrect.m 101 2014-10-24 18:21:04Z weinman $
 
% Jerod Weinman
% jerod@acm.org
% /home/data/svn/vision/tools/package/GPL_STATEMENT
 
  
validInterpCell = {'nearest', 'bilinear', 'bicubic'};
validFillCell = {'none', 'circular', 'replicate','symmetric'};

% Verify number of inputs
if nargin~=6
  error('vidi:normrect','Wrong number of input arguments')
end

% Verify image is input
if ~(isnumeric(img) && ndims(img)==3 && size(img,3)==3)
  error('vidi:normrect','Input img must be a color image');
end

% Verify binImg 
if ~(islogical(binImg) && ndims(binImg)==2 && ...
     size(binImg,1)==size(img,1) && size(binImg,2)==size(img,2) )
  error('vidi:normrect',...
        'Input binImg must be a logical image the same size as input img');
end

% Verify guides
if ~(isstruct(guides) && ...
     isfield(guides,'bottom') && isvector(guides.bottom) && ...
     all(size(guides.bottom)==[1 3]) && ...
     isfield(guides,'top') && isvector(guides.top) && ...
     all(size(guides.top)==[1 3]))
  error('vidi:normrect',...
        'Input guides must a struct with 1x3 fields ''bottom'' and ''top''');
end

% Verify rectangle
if ~(isnumeric(rect) && isvector(rect) && size(rect,2)==4)
  error('vidi:normrect','Input rect must be an 1x4 vector');
end

if ~isa(opts,'struct')
  error('vidi:normrect','Input opts must be a struct');
end

%-------------------------------------------------------------------------------
% Verify options
%-------------------------------------------------------------------------------

% Verify number of normalization control points
if isfield(opts,'normNumControlPts')
  if ~(isempty(opts.normNumControlPts) || ...
       (isscalar(opts.normNumControlPts) && opts.normNumControlPts>0))
    error('vidi:normrect', ...
          'If non-empty, opts.normNumControlPts must be a positive scalar');
  end
else
  opts.normNumControlPts = []; % Use default value in CONTROLPTS
end
  
% Verify image normalization interpolation method
if isfield(opts,'normImgInterp')
  if ~any(strcmp(opts.normImgInterp, validInterpCell))
    error('vidi:normrect', ...
          ['opts.normImgInterp must be one of the following strings:' ...
           sprintf(' %s',validInterpCell{:})]);
  end
else
  opts.normImgInterp = 'bicubic';
end

% Verify image normalization fill method
if isfield(opts,'normImgFill')
  if ~any(strcmp(opts.normImgFill, validFillCell))
    error('vidi:normrect', ...
          ['opts.normImgFill must be one of the following strings:' ...
           sprintf(' %s',validFillCell{:})]);
  end
else
  opts.normImgFill = 'replicate';
end

% Verify binarized normalization interpolation method
if isfield(opts,'normBinInterp')
  if ~any(strcmp(opts.normBinInterp, validInterpCell))
    error('vidi:normrect', ...
          ['opts.normBinInterp must be one of the following strings:' ...
           sprintf(' %s',validInterpCell{:})]);
  end
else
  opts.normBinInterp = 'bicubic';
end

% Verify binarized normalization fill method
if isfield(opts,'normBinFill')
  if ~any(strcmp(opts.normBinFill, validFillCell))
    error('vidi:normrect', ...
          ['opts.normBinFill must be one of the following strings:' ...
           sprintf(' %s',validFillCell{:})]);
  end
else
  opts.normBinFill = 'none';
end

%-------------------------------------------------------------------------------
% BEGIN ACTUAL PROCESSING
%-------------------------------------------------------------------------------

% Left- and right-most extents of bounding box
leftb = max(rect(1), 1); 
rightb = min( max(rect(1) + rect(3) - 1 ), size(img,2) );

% Get normalization control points
[Xc,Yc,Bt,Ht,Lt,Rt] = controlpts( guides.bottom, guides.top, ...
                                  leftb, rightb, ...
                                  [], opts.normNumControlPts);

% Package control point information
normPts = struct('in',  Xc, ...
                 'out', Yc, ...
                 'bounds', [Lt Rt Bt Ht] );

% Normalize original image
normRectImg = tpsimtform(img, Xc, Yc, opts.normImgInterp, opts.normImgFill);

% Normalize binary image
normBinImg = tpsimtform(binImg, Xc, Yc, opts.normBinInterp, opts.normBinFill);

end % NORMRECT
