/* ******************************************************************************
 *
 *
 * This program and the accompanying materials are made available under the
 * terms of the Apache License, Version 2.0 which is available at
 * https://www.apache.org/licenses/LICENSE-2.0.
 *
 *  See the NOTICE file distributed with this work for additional
 *  information regarding copyright ownership.
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 ******************************************************************************/

//
// @author Oleh Semeniv (oleg.semeniv@gmail.com)
//
//
// @author AbdelRauf    (rauf@konduit.ai)
//

#ifndef LIBND4J_HEADERS_IMAGES_H
#define LIBND4J_HEADERS_IMAGES_H
#include <execution/Threads.h>
#include <helpers/ConstantTadHelper.h>
#include <ops/declarable/CustomOperations.h>
#include <ops/declarable/headers/common.h>
#include <ops/declarable/helpers/imagesHelpers.h>

namespace sd {
namespace ops {

/**
 * Rgb To Hsv
 * Input arrays:
 * 0 - input array with rank >= 1, must have at least one dimension equal 3, that is dimension containing channels.
 * Int arguments:
 * 0 - optional argument, corresponds to dimension with 3 channels
 */
#if NOT_EXCLUDED(OP_rgb_to_hsv)
DECLARE_CONFIGURABLE_OP(rgb_to_hsv, 1, 1, true, 0, 0);
#endif

/**
 * Hsv To Rgb
 * Input arrays:
 * 0 - input array with rank >= 1, must have at least one dimension equal 3, that is dimension containing channels.
 * Int arguments:
 * 0 - optional argument, corresponds to dimension with 3 channels
 */
#if NOT_EXCLUDED(OP_hsv_to_rgb)
DECLARE_CONFIGURABLE_OP(hsv_to_rgb, 1, 1, true, 0, 0);
#endif

/**
 * Rgb To GrayScale
 * Input arrays:
 * 0 - input array with rank >= 1, the RGB tensor to convert. Last dimension must have size 3 and should contain RGB
 * values.
 */
#if NOT_EXCLUDED(OP_rgb_to_grs)
DECLARE_CUSTOM_OP(rgb_to_grs, 1, 1, false, 0, 0);
#endif

/**
 * Rgb To Yuv
 * Input arrays:
 * 0 - input array with rank >= 1, must have at least one dimension equal 3, that is dimension containing channels.
 * Int arguments:
 * 0 - optional argument, corresponds to dimension with 3 channels
 */
#if NOT_EXCLUDED(OP_rgb_to_yuv)
DECLARE_CONFIGURABLE_OP(rgb_to_yuv, 1, 1, true, 0, 0);
#endif

/**
 * Yuv To Rgb
 * Input arrays:
 * 0 - input array with rank >= 1, must have at least one dimension equal 3, that is dimension containing channels.
 * Int arguments:
 * 0 - optional argument, corresponds to dimension with 3 channels
 */
#if NOT_EXCLUDED(OP_rgb_to_yuv)
DECLARE_CONFIGURABLE_OP(yuv_to_rgb, 1, 1, true, 0, 0);
#endif

/**
 * Rgb To Yiq
 * Input arrays:
 * 0 - input array with rank >= 1, must have at least one dimension equal 3, that is dimension containing channels.
 * Int arguments:
 * 0 - optional argument, corresponds to dimension with 3 channels
 */
#if NOT_EXCLUDED(OP_rgb_to_yiq)
DECLARE_CONFIGURABLE_OP(rgb_to_yiq, 1, 1, true, 0, 0);
#endif

/**
 * Yiq To Rgb
 * Input arrays:
 * 0 - input array with rank >= 1, must have at least one dimension equal 3, that is dimension containing channels.
 * Int arguments:
 * 0 - optional argument, corresponds to dimension with 3 channels
 */
#if NOT_EXCLUDED(OP_yiq_to_rgb)
DECLARE_CONFIGURABLE_OP(yiq_to_rgb, 1, 1, true, 0, 0);
#endif

/**
 * resize_images - resize image with given size and method
 *    there are 4 methods allowed: RESIZE_BILINEAR(0), RESIZE_NEIGHBOR(1), RESIZE_AREA(2) and RESIZE_BICUBIC(3)
 * inputs:
 *      0 - 4D tensor with shape {batch, height, width, channels}
 *      1 - 1D integer tensor with {new_height, new_width} (optional)
 *      2 - 0D integer tensor with method (0 to 3) (optional)
 *
 * int args:
 *      0 - new_height
 *      1 - new_width
 *      2 - method
 *
 * bool args:
 *      0 - align corners (default false) - optional
 *      1 - preserve_aspect_ratio (default false) - optional
 *
 * CAUTION: one of methods can be used to give size and method - as tensors or as int args only
 *
 * output:
 *      0 - 4D float32 tensor with shape {batch, new_height, new_width, channels}
 *
 */
#if NOT_EXCLUDED(OP_resize_images)
DECLARE_CUSTOM_OP(resize_images, 1, 1, false, 0, 0);
#endif

/**
 * This op make bilinear or nearest neighbor interpolated resize for given tensor
 *
 * input array:
 *    0 - 4D-Tensor with shape (batch, sizeX, sizeY, channels) numeric type
 *    1 - 2D-Tensor with shape (num_boxes, 4) float type
 *    2 - 1D-Tensor with shape (num_boxes) int type
 *    3 - 1D-Tensor with 2 values (newWidth, newHeight) (optional) int type
 *
 * float arguments (optional)
 *   0 - exprapolation_value (optional) default 0.f
 *
 * int arguments: (optional)
 *   0 - mode (default 0 - bilinear interpolation)
 *
 * output array:
 *   the 4D-Tensor with resized to crop_size images given - float type
 */
#if NOT_EXCLUDED(OP_crop_and_resize)
DECLARE_CUSTOM_OP(crop_and_resize, 4, 1, false, -1, -1);
#endif

/**
 * This op make bilinear interpolated resize for given tensor
 *
 * input array:
 *    0 - 4D-Tensor with shape (batch, sizeX, sizeY, channels)
 *    1 - 1D-Tensor with 2 values (newWidth, newHeight) (optional)
 *
 * int arguments: (optional)
 *   0 - new width
 *   1 - new height
 *
 * output array:
 *   the 4D-Tensor with calculated backproped dots
 *
 * CAUTION: either size tensor or a pair of int params should be provided.
 */

#if NOT_EXCLUDED(OP_resize_bilinear)
DECLARE_CUSTOM_OP(resize_bilinear, 1, 1, false, 0, -2);
#endif

/**
 * This op make nearest neighbor interpolated resize for given tensor
 *
 * input array:
 *    0 - 4D-Tensor with shape (batch, sizeX, sizeY, channels)
 *    1 - 1D-Tensor with 2 values (newWidth, newHeight) (optional)
 *
 * int arguments: (optional)
 *   0 - new width
 *   1 - new height
 *
 * output array:
 *   the 4D-Tensor with resized image (shape is {batch, newWidth, newHeight, channels})
 *
 * CAUTION: either size tensor or a pair of int params should be provided.
 */

#if NOT_EXCLUDED(OP_resize_nearest_neighbor)
DECLARE_CUSTOM_OP(resize_nearest_neighbor, 1, 1, false, 0, -2);
#endif

/**
 * This op make bicubic interpolated resize for given tensor
 *
 * input array:
 *    0 - 4D-Tensor with shape (batch, sizeX, sizeY, channels)
 *    1 - 1D-Tensor with 2 values (newWidth, newHeight)
 *
 * output array:
 *   the 4D-Tensor with resized image (shape is {batch, newWidth, newHeight, channels})
 *
 */
#if NOT_EXCLUDED(OP_resize_bicubic)
DECLARE_CUSTOM_OP(resize_bicubic, 1, 1, false, 0, -2);
#endif

/**
 * This op make area interpolated resize (as OpenCV INTER_AREA algorithm) for given tensor
 *
 * input array:
 *    0 - images - 4D-Tensor with shape (batch, sizeX, sizeY, channels)
 *    1 - size -   1D-Tensor with 2 values (newWidth, newHeight) (if missing a pair of integer args should be provided).
 *
 * int args: - proveded only when size tensor is missing
 *    0 - new height
 *    1 - new width
 * boolean args:
 *    0 - align_corners - optional (default is false)
 *
 * output array:
 *   the 4D-Tensor with resized image (shape is {batch, newWidth, newHeight, channels})
 *
 */
#if NOT_EXCLUDED(OP_resize_area)
DECLARE_CUSTOM_OP(resize_area, 1, 1, false, 0, -2);
#endif

/**
 * This op make interpolated resize for given tensor with given algorithm.
 * Supported algorithms are bilinear, bicubic, nearest_neighbor, lanczos5, gaussian, area and mitchellcubic.
 *
 * input array:
 *    0 - 4D-Tensor with shape (batch, sizeX, sizeY, channels)
 *    1 - 1D-Tensor with 2 values (newWidth, newHeight)
 *
 * optional float args:
 *    0 -bicubicCoefficient - only effective for the bicubic method
 *
 * optional int args:
 *    0 - algorithm - bilinear by default
 *    1 - coordinateTransformationMode - Transformation function of the coordinate in the resized NdArray
 *    to the coordinate in the original NdArray
 *    2 - nearestMode - Effective only for the ResizeNearest interpolation.
 *    Indicates how to get "nearest" pixel in NDArray from original coordinate
 *
 *    optional bool args:
 *    0 - preserve_aspect_ratio - default False
 *    1 - antialias - default False
 *    2 - exclude_outside - only effective for the bicubic method when antialias is False
 *    If set to true, the weight of sampling locations outside the NdArray will be set to 0
 *    and the weight will be renormalized so that their sum is 1.0
 *
 * output array:
 *    the 4D-Tensor with resized by given algorithm image (shape is {batch, newWidth, newHeight, channels})
 *
 */

#if NOT_EXCLUDED(OP_image_resize)
DECLARE_CUSTOM_OP(image_resize, 2, 1, false, -2, -2);
#endif

}  // namespace ops
}  // namespace sd
#endif
