function Bout = imresize(Ain, varargin) %#codegen

%IMRESIZE Resize image.
%   B = IMRESIZE(A, SCALE) returns an image that is SCALE times the
%   size of A, which is a grayscale, RGB, or binary image.
%
%   B = IMRESIZE(A, [NUMROWS NUMCOLS]) resizes the image so that it has
%   the specified number of rows and columns.  Either NUMROWS or NUMCOLS
%   may be NaN, in which case IMRESIZE computes the number of rows or
%   columns automatically in order to preserve the image aspect ratio.
%
%   To control the interpolation method used by IMRESIZE, add a METHOD
%   argument to any of the syntaxes above, like this:
%
%       IMRESIZE(A, SCALE, METHOD)
%       IMRESIZE(A, [NUMROWS NUMCOLS], METHOD),
%
%   METHOD can be a string naming a general interpolation method:
%
%       'nearest'    - nearest-neighbor interpolation
%
%       'bilinear'   - bilinear interpolation
%
%       'bicubic'    - cubic interpolation; the default method
%
%   METHOD can also be a string naming an interpolation kernel:
%
%       'box'        - interpolation with a box-shaped kernel
%
%       'triangle'   - interpolation with a triangular kernel
%                         (equivalent to 'bilinear')
%
%       'cubic'      - interpolation with a cubic kernel
%                         (equivalent to 'bicubic')
%
%       'lanczos2'   - interpolation with a Lanczos-2 kernel
%
%       'lanczos3'   - interpolation with a Lanczos-3 kernel
%
%   You can achieve additional control over IMRESIZE by using
%   parameter/value pairs following any of the syntaxes above.  For
%   example:
%
%       B = IMRESIZE(A, SCALE, PARAM1, VALUE1, PARAM2, VALUE2, ...)
%
%   Parameters include:
%
%       'Antialiasing'  - true or false; specifies whether to perform
%                         antialiasing when shrinking an image. The
%                         default value depends on the interpolation
%                         method you choose.  For the 'nearest' method,
%                         the default is false; for all other methods,
%                         the default is true.
%
%       'Method'        - As described above
%
%       'OutputSize'    - A two-element vector, [MROWS NCOLS],
%                         specifying the output size.  One element may
%                         be NaN, in which case the other value is
%                         computed automatically to preserve the aspect
%                         ratio of the image.
%
%       'Scale'         - A scalar or two-element vector specifying the
%                         resize scale factors.  If it is a scalar, the
%                         same scale factor is applied to each
%                         dimension.  If it is a vector, it contains
%                         the scale factors for the row and column
%                         dimensions, respectively.
%
%   Examples
%   --------
%   Shrink by factor of two using the defaults of bicubic interpolation
%   and antialiasing.
%
%       I = imread('rice.png');
%       J = imresize(I, 0.5);
%       figure, imshow(I), figure, imshow(J)
%
%   Shrink by factor of two using nearest-neighbor interpolation.
%   (This is the fastest method, but it has the lowest quality.)
%
%       J2 = imresize(I, 0.5, 'nearest');
%
%   Resize an RGB image to have 64 rows.  The number of columns is
%   computed automatically.
%
%       RGB = imread('peppers.png');
%       RGB2 = imresize(RGB, [64 NaN]);
%
%   For bicubic interpolation, the output image may have some values
%   slightly outside the range of pixel values in the input image.
%
%   Class Support
%   -------------
%   The input image A can be numeric or logical and it must be nonsparse.
%   The output image is of the same class as the input image.
%
%   See also IMWARP

%   Copyright 2015-2019 The MathWorks, Inc.

%#ok<*EMCA>

narginchk(2,inf);



coder.internal.prefer_const(varargin);


% Image
validateattributes(Ain,...
    {'numeric', 'logical'},...
    {'nonsparse', 'nonempty'},...
    mfilename, 'A', 1);
convertToUint8 = islogical(Ain);
if convertToUint8
    A = uint8(255) .* uint8(Ain);
else
    A = Ain;
end

% Rest of the inputs
scaleOrSize = [1 1];
resizeSpecSpecified     = false;
isResizeSpecScale       = false;
isResizeSpecScalarScale = true;
% Number of times the resize spec is specifed, possible max of 4, codegen
% only supports 1
numResizeSpecSpecification = 0;

antialiasing           = true;
antialiasingThroughPV  = false;


methodStrings = {'nearest', ...
    'bilinear',...
    'bicubic',...
    'box',...
    'triangle',...
    'cubic',...
    'lanczos2',...
    'lanczos3',...
    'preduce',...
    'pexpand'};


switch numel(varargin)
    case 1
        if(ischar(varargin{1}))
            % imresize(A, method)
            % Fail later with missing scale message
            method = varargin{1};
        else
            % imresize(A, scaleOrSize)
            resizeSpecSpecified = true;
            if(numel(varargin{1})==1)
                scaleOrSize(1) = varargin{1};
                isResizeSpecScale = true;
            else
                scaleOrSize = varargin{1};
            end
            
            method = 'bicubic';
            numResizeSpecSpecification = numResizeSpecSpecification+1;
        end
        
    case 2
        if(ischar(varargin{1}))
            % imresize(A, P, V)
            [antialiasing, antialiasingThroughPV, scaleOrSize, resizeSpecSpecified, isResizeSpecScale, isResizeSpecScalarScale, method, numResizeSpecSpecification] = ...
                parsePV(1, antialiasing, antialiasingThroughPV, scaleOrSize, resizeSpecSpecified, isResizeSpecScale, isResizeSpecScalarScale, numResizeSpecSpecification, varargin{:});
            
        else
            % imresize(A, scaleOrSize, method)
            resizeSpecSpecified = true;
            if(numel(varargin{1})==1)
                scaleOrSize(1) = varargin{1};
                isResizeSpecScale = true;
            else
                scaleOrSize = varargin{1};
            end
            
            eml_invariant(eml_is_const(varargin{2}), ...
                eml_message('MATLAB:images:validate:codegenInputNotConst', 'METHOD'),...
                'IfNotConst','Fail');
            method = varargin{2};
            numResizeSpecSpecification = numResizeSpecSpecification+1;
        end
        
    otherwise
        % 3 additional args and up
        
        if(isnumeric(varargin{1}))
            % imresize(A, scaleSize,  ...)
            resizeSpecSpecified = true;
            numResizeSpecSpecification = numResizeSpecSpecification+1;
            if(numel(varargin{1})==1)
                scaleOrSize(1) = varargin{1};
                isResizeSpecScale = true;
            else
                scaleOrSize = varargin{1};
            end
            
            if(isMethodString(varargin{2}))
                % imresize(A, scaleSize, method, {PVs, ...})
                method = varargin{2};
                eml_invariant(eml_is_const(varargin{2}), ...
                    eml_message('MATLAB:images:validate:codegenInputNotConst', 'METHOD'),...
                    'IfNotConst','Fail');
                
                if(numel(varargin)>2)
                    % PV
                    [antialiasing, antialiasingThroughPV, scaleOrSize, resizeSpecSpecified, isResizeSpecScale,isResizeSpecScalarScale, ~, numResizeSpecSpecification] = ...
                        parsePV(3, antialiasing, antialiasingThroughPV, scaleOrSize, resizeSpecSpecified, isResizeSpecScale,isResizeSpecScalarScale, numResizeSpecSpecification,varargin{:});
                end
            else
                % imresize(A, scaleSize, {PVs,...})
                [antialiasing, antialiasingThroughPV, scaleOrSize, resizeSpecSpecified, isResizeSpecScale,isResizeSpecScalarScale, method, numResizeSpecSpecification] = ...
                    parsePV(2, antialiasing, antialiasingThroughPV, scaleOrSize, resizeSpecSpecified, isResizeSpecScale,isResizeSpecScalarScale,numResizeSpecSpecification, varargin{:});
            end
        else
            % imresize(A, PVs,...)
            [antialiasing, antialiasingThroughPV, scaleOrSize, resizeSpecSpecified, isResizeSpecScale,isResizeSpecScalarScale, method, numResizeSpecSpecification] = ...
                parsePV( 1, antialiasing, antialiasingThroughPV, scaleOrSize, resizeSpecSpecified, isResizeSpecScale, isResizeSpecScalarScale, numResizeSpecSpecification, varargin{:});
        end
        
end
coder.internal.errorIf(numResizeSpecSpecification>1,...
    'MATLAB:images:imresize:tooManyOutputSizeSpecificationsForCodegen');

% Convert method to function handle
method = validatestring(method, methodStrings, mfilename);

switch(method)
    case 'nearest'
        kernel = 'box';
        kwidth = 1.0;
        if(~antialiasingThroughPV)
            antialiasing = false;
        end
    case 'box'
        kernel = 'box';
        kwidth = 1.0;
        if(~antialiasingThroughPV)
            antialiasing = true;
        end
    case {'bilinear', 'triangle'}
        kernel = 'tri';
        kwidth = 2.0;
        if(~antialiasingThroughPV)
            antialiasing = true;
        end
    case {'cubic','bicubic'}
        kernel = 'cub';
        kwidth = 4.0;
        if(~antialiasingThroughPV)
            antialiasing = true;
        end
    case 'lanczos2'
        kernel = 'la2';
        kwidth = 4.0;
        if(~antialiasingThroughPV)
            antialiasing = true;
        end
    case 'lanczos3'
        kernel = 'la3';
        kwidth = 6.0;
        if(~antialiasingThroughPV)
            antialiasing = true;
        end
    case 'preduce'
        kernel = 'pre';
        kwidth = 5;
        antialiasing = false;
    case 'pexpand'
        kernel = 'pex';
        kwidth = 3;
        antialiasing = false;
    otherwise
        assert(false, 'Unsupported method');
        kernel = 'cub';
        kwidth = 4.0;
        if(~antialiasingThroughPV)
            antialiasing = true;
        end
end

coder.internal.errorIf( ~ ( (isnumeric(antialiasing) || islogical(antialiasing)) && isscalar(antialiasing) ),...
    'MATLAB:images:imresize:badAntialiasing');

% Find required scale
coder.internal.errorIf(resizeSpecSpecified==false,...
    'MATLAB:images:imresize:missingScaleAndSize');

coder.internal.prefer_const(scaleOrSize);

outputSize_ = size(A);
outputSize  = outputSize_(1:2);

if(isResizeSpecScale && isResizeSpecScalarScale)
    validateattributes(scaleOrSize(1), {'numeric'}, {'nonzero', 'positive','real'},...
        mfilename, 'SCALE');
    scale = [scaleOrSize(1), scaleOrSize(1)];
    outputSize = ceil(outputSize.*scale);
elseif(isResizeSpecScale && ~isResizeSpecScalarScale)
    scale = [scaleOrSize(1), scaleOrSize(2)];
    coder.internal.errorIf(~isnumeric(scale) || (numel(scale) == 1) || ~all(scale(:)>0),...
        'MATLAB:images:imresize:invalidScale');
    outputSize = ceil(outputSize.*scale);
else
    % not scale, but output size
    coder.internal.errorIf(...
        ~isnumeric(scaleOrSize)|| numel(scaleOrSize)~=2 ...
        || all(isnan(scaleOrSize(:))) || any(scaleOrSize(:)<=0),...
        'MATLAB:images:imresize:badOutputSize');
    
    coder.internal.errorIf(all(isnan(scaleOrSize(:))),...
        'MATLAB:images:imresize:allNaN');
    
    % Convert output size to scale factor
    outputSize = scaleOrSize;
    if isnan(outputSize (1))
        outputSize (1) = outputSize (2) * size(A, 1) / size(A, 2);
        outputSize = ceil(outputSize);
        scale = [outputSize(2)/size(A,2), outputSize(2)/size(A,2)];
    elseif isnan(outputSize(2))
        outputSize(2) = outputSize (1) * size(A, 2) / size(A, 1);
        outputSize = ceil(outputSize);
        scale = [outputSize(1)/size(A,1), outputSize(1)/size(A,1)];
    else
        outputSize = ceil(outputSize);
        scale = outputSize(1:2)./([size(A,1), size(A,2)]);
    end
    
end

% Rigid scale specification for impyramid
switch(method)
    case 'preduce'
        scale = [0.5, 0.5];
    case 'pexpand'
        scale = [2 2];
    otherwise
        % scale doesn't change
end

coder.internal.prefer_const(scale);
coder.internal.prefer_const(outputSize);

%  Gpu Enabled condition is added here and it supported when
%  the method is not 'preduce' and 'pexpand'(impyramid function kernels).
if (coder.gpu.internal.isGpuEnabled && (~strcmp(method,'preduce')) && (~strcmp(method,'pexpand')) )
    % gpu specific implementation for imresize is called here.
    [ResizedImage] = coder.internal.gpu_imresize_kernel(A,scale,outputSize,kernel,kwidth,antialiasing);
    % for logical input.
    if convertToUint8
        Bout = ResizedImage > 128;
    else
        Bout = ResizedImage;
    end
else  % MLC implementation.
    
    % Resize the smaller scale first. Split into if/else to ensure constant
    % folding of output size.
    if scale(1) <= scale(2)        
        %> Resize first dimension
        dim = 1;
        [weights, indices] = contributions(coder.internal.indexInt(size(A, dim)), outputSize(dim), ...
            scale(dim), kernel, ...
            kwidth, antialiasing);
        APartialResize = resizeAlongDim(A, dim, weights, indices);
        
        %> Resize second dimension
        dim = 2;
        [weights, indices] = contributions(coder.internal.indexInt(size(A, dim)),outputSize(dim),  ...
            scale(dim), kernel, ...
            kwidth, antialiasing);
        B = resizeAlongDim(APartialResize, dim, weights, indices);
    else
        dim = 2;
        [weights, indices] = contributions(coder.internal.indexInt(size(A, dim)), outputSize(dim), ...
            scale(dim), kernel, ...
            kwidth, antialiasing);
        APartialResize = resizeAlongDim(A, dim, weights, indices);
        
        %> Resize second dimension
        dim = 1;
        [weights, indices] = contributions(coder.internal.indexInt(size(A, dim)),outputSize(dim),  ...
            scale(dim), kernel, ...
            kwidth, antialiasing);
        B = resizeAlongDim(APartialResize, dim, weights, indices);
    end
    
    if convertToUint8
        Bout = B > 128;
    else
        Bout = B;
    end
end

function out_ = resizeAlongDim(in_, dim, weights, indices)
% Resize along a specified dimension
%
% in           - input array to be resized
% dim          - dimension along which to resize
% weights      - weight matrix; row k is weights for k-th output pixel
% indices      - indices matrix; row k is indices for k-th output pixel


out_length = size(weights, 2);
coder.internal.prefer_const(out_length);

outSize = size(in_);
outSize(dim) = out_length;
out = coder.nullcopy(zeros(outSize,'like', in_));

size_in = size(in_);
coder.internal.prefer_const(size_in);

if (ndims(in_) > 3)
    % Reshape to a three-dimensional array.  The size of this
    % three-dimensional array is the variable pseudo_size_in below.
    %
    % Final output will be consistent with the original input.
    pseudo_size_in = [size_in(1:2) prod(size_in(3:end))];
    in = reshape(in_, pseudo_size_in);
    out = resizeAlongDim2D(in, dim, weights, indices, out_length, out);
    size_out = size_in;
    size_out(dim) = out_length;    
    out_ = reshape(out, size_out);
else
    out_ = resizeAlongDim2D(in_, dim, weights, indices, out_length, out);
end


function out = resizeAlongDim2D(in, dim, weights, indices, out_length, out)
coder.inline('always');
% The 'out' will be uint8 if 'in' is logical
% Otherwise 'out' datatype will be same as 'in' datatype

if(dim==1)
    parfor inCInd = 1:numel(in)/size(in,1) % input columns.
        inCol = in(:, inCInd);
        for outRInd = 1:out_length % output rows
            if(isreal(in)) %#ok<PFBNS>
                sumVal1 = 0.0;
            else
                sumVal1 = 0.0+0.0i;
            end
            linearInds = coder.internal.indexInt(sub2ind(size(weights),1, outRInd));
            %> Core - first dimension
            for k = 1:size(weights,1)
                sumVal1 = sumVal1 + weights(linearInds) * double(inCol(indices(linearInds))); %#ok<PFBNS>
                linearInds = coder.internal.indexPlus(linearInds,1);
            end
            
            out(outRInd, inCInd) = sumVal1;
        end
    end
else
    for pInd = 1: size(in,3) % planes
        parfor inRInd = 1:size(in,1) % input rows.
            rowStart = sub2ind(size(in),inRInd,1, pInd);
            for outCInd = 1:out_length
                if(isreal(in))
                    sumVal1 = 0.0;
                else
                    sumVal1 = 0.0+0.0i;
                end
                
                %> Core - second dimension
                linearInds = coder.internal.indexInt(sub2ind(size(weights),1, outCInd));
                for k = 1:size(weights,1)
                    pixelIndex = coder.internal.indexPlus( rowStart,...
                        coder.internal.indexTimes(...
                        coder.internal.indexMinus(indices(linearInds),1),...
                        size(in,1))); %#ok<PFBNS>
                    pixelValue = in(pixelIndex);
                    sumVal1 = sumVal1 + weights(linearInds) * double(pixelValue);
                    linearInds = linearInds +1;
                end
                
                out(inRInd, outCInd, pInd) = sumVal1;
            end
        end
    end
end


function [weights, indices] = contributions(in_length,out_length, ...
    scale, kernel, kernel_width, antialiasing)

coder.internal.prefer_const(out_length);

%> Contributions, using pixel indices

if (scale < 1) && (antialiasing)
    % Use a modified kernel to simultaneously interpolate and
    % antialias.
    kernel_width = kernel_width / scale;
end



% Output-space coordinates.
x = (1:out_length)';

% Input-space coordinates. Calculate the inverse mapping such that 0.5
% in output space maps to 0.5 in input space, and 0.5+scale in output
% space maps to 1.5 in input space.
u = x/scale + 0.5 * (1 - 1/scale);

% What is the left-most pixel that can be involved in the computation?
left = coder.internal.indexInt(floor(u - kernel_width/2));

% What is the maximum number of pixels that can be involved in the
% computation?  Note: it's OK to use an extra pixel here; if the
% corresponding weights are all zero, it will be eliminated at the end
% of this function.
P = coder.internal.indexInt(ceil(kernel_width) + 2);

% The indices of the input pixels involved in computing the k-th output
% pixel are in row k of the indices matrix.
indices = bsxfun(@coder.internal.indexPlus, left, 0:P-1);

% The weights used to compute the k-th output pixel are in row k of the
% weights matrix.
weights = kernelWrapper(bsxfun(@minus, u, double(indices)),kernel, scale, antialiasing);

% Normalize the weights matrix so that each row sums to 1.
weights = bsxfun(@rdivide, weights, sum(weights, 2));

% Mirror out-of-bounds indices; equivalent of doing symmetric padding

%> Create the auxiliary matrix:
% aux = [1:in_length,in_length:-1:1];

% in_length is assumed to be indexInt
auxLength = coder.internal.indexTimes(in_length,2);

% Allocate space without initializing
aux = coder.nullcopy(coder.internal.indexInt(zeros(1,auxLength)));

% Fill values
aux(1) = coder.internal.indexInt(1);
aux(in_length+1) = in_length;

for i = 2:in_length
    aux(i) = aux(i-1) + 1;
    aux(in_length+i) = aux(in_length+i-1) - 1;
end

%> Mirror the out-of-bounds indices using mod:
% tmp = mod(double(indices)-1,length(aux));
% indices = aux(coder.internal.indexPlus(tmp,1));

for i = 1:numel(indices)
    oldIdx = double(indices(i));
    % use mod only with two doubles. using indexInt will segv.
    k = mod(oldIdx-1,double(auxLength));
    indices(i) = aux(coder.internal.indexPlus(k,1));
end

% If a column in weights is all zero, get rid of it.
% kill = find(~any(weights, 1));
% if ~isempty(kill)
%     weights(:,kill) = [];
%     indices(:,kill) = [];
% end

% Alternatively, copy non-zero columns
copyCols = any(weights, 1);
weightsNonZeroCols = weights(:, copyCols);
indicesNonZeroCols = indices(:, copyCols);

% Transpose to allow for cache friendly access in the core resizer
weights = weightsNonZeroCols';
indices = indicesNonZeroCols';

function xout = kernelWrapper(xin, kernel, scale, antialiasing)

coder.inline('always');

if (scale < 1) && (antialiasing)
    % Use a modified kernel to simultaneously interpolate and
    % antialias.
    x = scale * xin;
else
    x = xin;
end

switch kernel
    case 'cub'
        % See Keys, "Cubic Convolution Interpolation for Digital Image
        % Processing," IEEE Transactions on Acoustics, Speech, and Signal
        % Processing, Vol. ASSP-29, No. 6, December 1981, p. 1155.
        
        absx = abs(x);
        absx2 = absx.^2;
        absx3 = absx.^3;
        
        f = (1.5*absx3 - 2.5*absx2 + 1) .* (absx <= 1) + ...
            (-0.5*absx3 + 2.5*absx2 - 4*absx + 2) .* ...
            ((1 < absx) & (absx <= 2));
    case 'box'
        f = double((-0.5 <= x) & (x < 0.5));
    case 'tri'
        f = (x+1) .* ((-1 <= x) & (x < 0)) + (1-x) .* ((0 <= x) & (x <= 1));
    case 'la2'
        % See Graphics Gems, Andrew S. Glasser (ed), Morgan Kaufman, 1990,
        % pp. 156-157.
        f = (sin(pi*x) .* sin(pi*x/2) + eps) ./ ((pi^2 * x.^2 / 2) + eps);
        f = f .* (abs(x) < 2);
    case 'la3'
        % See Graphics Gems, Andrew S. Glasser (ed), Morgan Kaufman, 1990,
        % pp. 157-158.
        f = (sin(pi*x) .* sin(pi*x/3) + eps) ./ ((pi^2 * x.^2 / 3) + eps);
        f = f .* (abs(x) < 3);
    case 'pre'
        % See impyramid
        bPoints = [3.5 2.5      1.5    0.5    -0.5   -1.5    -Inf];
        bValues = [0.0 0.0625   0.25   0.375   0.25   0.0625  0.0];
        f = coder.nullcopy(x);
        for ind=1:numel(x)
            f(ind) = 0;
            for bInd=1:numel(bPoints)
                if(x(ind)>=bPoints(bInd))
                    f(ind) = bValues(bInd);
                    break;
                end
            end
        end
        
    case 'pex'
        % See impyramid
        bPoints = [1.25   0.75    0.25   -0.25   -0.75   -1.25   -Inf];
        bValues = [0.0    0.125   0.5     0.75    0.5    0.125    0.0];
        f = coder.nullcopy(x);
        for ind=1:numel(x)
            f(ind) = 0;
            for bInd=1:numel(bPoints)
                if(x(ind)>=bPoints(bInd))
                    f(ind) = bValues(bInd);
                    break;
                end
            end
        end
        
    otherwise
        assert(false, 'Unsupported method');
        f=x;
end

if (scale < 1) && (antialiasing)
    % Use a modified kernel to simultaneously interpolate and
    % antialias.
    xout = scale * f;
else
    xout = f;
end

function [antialiasing, antialiasingThroughPV, scaleOrSize,resizeSpecSpecified, isResizeSpecScale, isResizeSpecScalarScale, method, numResizeSpecSpecification] = ...
    parsePV(startInd, antialiasing, antialiasingThroughPV, scaleOrSize, resizeSpecSpecified, isResizeSpecScale, isResizeSpecScalarScale, numResizeSpecSpecification, varargin)

coder.inline('always');
% parse all PV's
coder.internal.errorIf(mod(numel(varargin)-startInd+1,2)~=0,...
    'MATLAB:images:imresize:oddNumberArgs');

paramStrings = {...
    'Antialiasing',...
    'Method',...
    'OutputSize',...
    'Scale'};

methodStrings = {'nearest', ...
    'bilinear',...
    'bicubic',...
    'box',...
    'triangle',...
    'cubic',...
    'lanczos2',...
    'lanczos3',...
    'preduce',...
    'pexpand'};
methodIdx = 0;
coder.unroll;
for ind=startInd:2:numel(varargin)
    eml_invariant(eml_is_const(varargin{ind}), ...
        eml_message('MATLAB:images:validate:codegenInputNotConst', 'PARAMETER'),...
        'IfNotConst','Fail');
    
    paramString =  validatestring(varargin{ind}, paramStrings, mfilename);
    switch(paramString)
        case 'Antialiasing'
            eml_invariant(eml_is_const(varargin{ind+1}), ...
                eml_message('MATLAB:images:validate:codegenInputNotConst', 'ANTIALIASING'),...
                'IfNotConst','Fail');
            antialiasingThroughPV = true;
            validateattributes(varargin{ind+1}, {'logical'}, {'scalar'},...
                mfilename, 'ANTIALIASING');
            antialiasing = varargin{ind+1};
        case 'Scale'
            eml_invariant(eml_is_const(varargin{ind+1}), ...
                eml_message('MATLAB:images:validate:codegenInputNotConst', 'SCALE'),...
                'IfNotConst','Fail');
            % This value could be in the form [scalex, scaley]
            validateattributes(varargin{ind+1}, {'numeric'}, {'nonzero', 'real'},...
                mfilename, 'SCALE');
            resizeSpecSpecified = true;
            isResizeSpecScale = true;
            if(numel(varargin{ind+1})==1)
                scaleOrSize(1) = varargin{ind+1};
                isResizeSpecScalarScale = true;
            else
                scaleOrSize = varargin{ind+1};
                isResizeSpecScalarScale = false;
            end
            numResizeSpecSpecification = numResizeSpecSpecification + 1;
        case 'OutputSize'
            coder.internal.prefer_const(varargin{ind+1});
            validateattributes(varargin{ind+1}, {'numeric'}, {'nonzero', 'real'},...
                mfilename, 'OUTPUTSIZE');
            coder.internal.errorIf(numel(varargin{ind+1})~=2,...
                'MATLAB:images:imresize:badOutputSize');
            scaleOrSize = varargin{ind+1};
            coder.internal.errorIf(all(isnan(scaleOrSize(:))),...
                'MATLAB:images:imresize:allNaN');
            resizeSpecSpecified = true;
            numResizeSpecSpecification = numResizeSpecSpecification + 1;
        case 'Method'
            eml_invariant(eml_is_const(varargin{ind+1}), ...
                eml_message('MATLAB:images:validate:codegenInputNotConst', 'METHOD'),...
                'IfNotConst','Fail');
            % The method can be specified more than once,
            % but all method inputs must be validated.
            validatestring(varargin{ind+1}, methodStrings, mfilename);
            methodIdx = ind + 1;
        otherwise
            % numResizeSpecSpecification doesn't change
    end
end
if methodIdx >= 1
    method = validatestring(varargin{methodIdx}, methodStrings, mfilename);
else
    method = 'bicubic';
end
    
function tf = isMethodString(methodStr)
coder.inline('always');
tf = strncmpi(methodStr,'nearest', numel(methodStr))...
    ||strncmpi(methodStr,'bilinear',numel(methodStr))...
    ||strncmpi(methodStr,'bicubic',numel(methodStr))...
    ||strncmpi(methodStr,'box',numel(methodStr))...
    ||strncmpi(methodStr,'triangle',numel(methodStr))...
    ||strncmpi(methodStr,'cubic',numel(methodStr))...
    ||strncmpi(methodStr,'lanczos2',numel(methodStr))...
    ||strncmpi(methodStr,'lanczos3',numel(methodStr))...
    ||strncmpi(methodStr,'pexpand',numel(methodStr))...
    ||strncmpi(methodStr,'preduce',numel(methodStr));
